From: Mike Bayer Date: Sat, 7 Aug 2010 00:11:18 +0000 (-0400) Subject: some cleanup, some screwing around with comparators...many more issues coming up X-Git-Tag: rel_0_7b1~252^2~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=518b374f5bf57db92a7f8bdf408bc06f561e1f0d;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git some cleanup, some screwing around with comparators...many more issues coming up --- diff --git a/lib/sqlalchemy/ext/hybrid.py b/lib/sqlalchemy/ext/hybrid.py index 3134db12de..b74b407c5c 100644 --- a/lib/sqlalchemy/ext/hybrid.py +++ b/lib/sqlalchemy/ext/hybrid.py @@ -63,6 +63,7 @@ or as the class itself:: """ from sqlalchemy import util +from sqlalchemy.orm import attributes, interfaces class method(object): def __init__(self, func, expr=None): @@ -111,4 +112,34 @@ class property_(object): self.expr = expr return self + def compare_with(self, comparator): + proxy_attr = attributes.\ + create_proxied_attribute(self) + def expr(owner): + return proxy_attr(self.__name__, self, comparator(owner)) + self.expr = expr + return self + + +class Comparator(interfaces.PropComparator): + def __init__(self, expression, adapter=None): + self._expression = expression + self.adapter = adapter + + @property + def expression(self): + return self.__clause_element__() + + def __clause_element__(self): + if self.adapter: + return self.adapter(self._expression) + else: + return self._expression + + def adapted(self, adapter): + return self.__class__(self._expression, adapter) + + + + \ No newline at end of file diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index c21585cea6..ea04b0910e 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -162,17 +162,10 @@ class InstrumentedAttribute(QueryableAttribute): return self.impl.get(instance_state(instance), instance_dict(instance)) -class _ProxyImpl(object): - accepts_scalar_loader = False - expire_missing = True - - def __init__(self, key): - self.key = key - -def proxied_attribute_factory(descriptor): - """Create an InstrumentedAttribute / user descriptor hybrid. +def create_proxied_attribute(descriptor): + """Create an QueryableAttribute / user descriptor hybrid. - Returns a new InstrumentedAttribute type that delegates descriptor + Returns a new QueryableAttribute type that delegates descriptor behavior and getattr() to the given descriptor. """ @@ -181,10 +174,8 @@ def proxied_attribute_factory(descriptor): def __init__(self, key, descriptor, comparator, adapter=None): self.key = key - # maintain ProxiedAttribute.user_prop compatability. - self.descriptor = self.user_prop = descriptor + self.descriptor = descriptor self._comparator = comparator - self.impl = _ProxyImpl(key) self.adapter = adapter @util.memoized_property @@ -199,22 +190,10 @@ def proxied_attribute_factory(descriptor): return self.__class__(self.key, self.descriptor, self._comparator, adapter) - - def __get__(self, instance, owner): - """Delegate __get__ to the original descriptor.""" - if instance is None: - descriptor.__get__(instance, owner) - return self - return descriptor.__get__(instance, owner) - - def __set__(self, instance, value): - """Delegate __set__ to the original descriptor.""" - return descriptor.__set__(instance, value) - - def __delete__(self, instance): - """Delegate __delete__ to the original descriptor.""" - return descriptor.__delete__(instance) + def __str__(self): + return self.key + def __getattr__(self, attribute): """Delegate __getattr__ to the original descriptor and/or comparator.""" @@ -223,7 +202,7 @@ def proxied_attribute_factory(descriptor): return getattr(descriptor, attribute) except AttributeError: try: - return getattr(self.comparator, attribute) + return getattr(self._comparator, attribute) except AttributeError: raise AttributeError( 'Neither %r object nor %r object has an attribute %r' % ( @@ -1424,15 +1403,12 @@ def unregister_class(class_): instrumentation_registry.unregister(class_) def register_attribute(class_, key, **kw): - proxy_property = kw.pop('proxy_property', None) - comparator = kw.pop('comparator', None) parententity = kw.pop('parententity', None) doc = kw.pop('doc', None) - register_descriptor(class_, key, proxy_property, + register_descriptor(class_, key, comparator, parententity, doc=doc) - if not proxy_property: - register_attribute_impl(class_, key, **kw) + register_attribute_impl(class_, key, **kw) def register_attribute_impl(class_, key, uselist=False, callable_=None, @@ -1464,16 +1440,11 @@ def register_attribute_impl(class_, key, manager.post_configure_attribute(key) -def register_descriptor(class_, key, proxy_property=None, comparator=None, +def register_descriptor(class_, key, comparator=None, parententity=None, property_=None, doc=None): manager = manager_of_class(class_) - if proxy_property: - raise NotImplementedError() - proxy_type = proxied_attribute_factory(proxy_property) - descriptor = proxy_type(key, proxy_property, comparator, parententity) - else: - descriptor = InstrumentedAttribute(key, comparator=comparator, + descriptor = InstrumentedAttribute(key, comparator=comparator, parententity=parententity) descriptor.__doc__ = doc diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 4e7702698f..1895798b16 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1074,10 +1074,6 @@ class Mapper(object): return result def _is_userland_descriptor(self, obj): -# return not isinstance(obj, -# (MapperProperty, attributes.InstrumentedAttribute)) and \ -# hasattr(obj, '__get__') - return not isinstance(obj, (MapperProperty, attributes.InstrumentedAttribute)) and \ hasattr(obj, '__get__') and not \ diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 50d95b7771..d0de4bbbb0 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -290,14 +290,15 @@ class DescriptorProperty(MapperProperty): ) proxy_attr = attributes.\ - proxied_attribute_factory(self.descriptor - or descriptor)\ - (self.key, self.descriptor or descriptor, - lambda: self._comparator_factory(mapper)) + create_proxied_attribute(self.descriptor or descriptor)\ + ( + self.key, + self.descriptor or descriptor, + lambda: self._comparator_factory(mapper) + ) def get_comparator(owner): return proxy_attr descriptor.expr = get_comparator - descriptor.impl = _ProxyImpl(self.key) mapper.class_manager.instrument_attribute(self.key, descriptor) @@ -328,8 +329,6 @@ class ConcreteInheritedProperty(DescriptorProperty): """ - extension = None - def _comparator_factory(self, mapper): comparator_callable = None @@ -361,8 +360,6 @@ class ConcreteInheritedProperty(DescriptorProperty): class SynonymProperty(DescriptorProperty): - extension = None - def __init__(self, name, map_column=None, descriptor=None, comparator_factory=None, doc=None): @@ -436,8 +433,6 @@ class ComparableProperty(DescriptorProperty): return self.comparator_factory(self, mapper) - - class RelationshipProperty(StrategizedProperty): """Describes an object property that holds a single item or list of items that correspond to a related database table. diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index c05dfe1e44..ed1eefee49 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -866,7 +866,8 @@ class Query(object): clauses = [_entity_descriptor(self._joinpoint_zero(), key) == value for key, value in kwargs.iteritems()] - + import pdb + pdb.set_trace() return self.filter(sql.and_(*clauses)) @_generative(_no_statement_condition, _no_limit_offset) diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index c9b86e8ee7..194ba67a5d 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -901,8 +901,6 @@ class MapperTest(_fixtures.FixtureTest): args = (UCComparator,) mapper(User, users, properties=dict( uc_name = sa.orm.comparable_property(*args))) -# import pdb -# pdb.set_trace() return User for User in (map_(True), map_(False)):