diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-23 17:03:48 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-23 17:03:48 -0500 |
commit | ae4629e6a0ff442a819b80f418dee76c25c50938 (patch) | |
tree | c2fccb7619c5ee3bf2a2433f489b54b8ebf2d251 /lib/sqlalchemy | |
parent | 6b79d2ea7951abc2bb6083b541db0fbf71590dd3 (diff) | |
download | sqlalchemy-ae4629e6a0ff442a819b80f418dee76c25c50938.tar.gz |
- Some refinements to the :class:`.AliasedClass` construct with regards
to descriptors, like hybrids, synonyms, composites, user-defined
descriptors, etc. The attribute
adaptation which goes on has been made more robust, such that if a descriptor
returns another instrumented attribute, rather than a compound SQL
expression element, the operation will still proceed.
Addtionally, the "adapted" operator will retain its class; previously,
a change in class from ``InstrumentedAttribute`` to ``QueryableAttribute``
(a superclass) would interact with Python's operator system such that
an expression like ``aliased(MyClass.x) > MyClass.x`` would reverse itself
to read ``myclass.x < myclass_1.x``. The adapted attribute will also
refer to the new :class:`.AliasedClass` as its parent which was not
always the case before. [ticket:2872]
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 8 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/util.py | 20 |
2 files changed, 13 insertions, 15 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 6071b565d..e3c6a3512 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -149,6 +149,12 @@ class QueryableAttribute(interfaces._MappedAttribute, return self.comparator._query_clause_element() + def adapt_to_entity(self, adapt_to_entity): + assert not self._of_type + return self.__class__(adapt_to_entity.entity, self.key, impl=self.impl, + comparator=self.comparator.adapt_to_entity(adapt_to_entity), + parententity=adapt_to_entity) + def of_type(self, cls): return QueryableAttribute( self.class_, @@ -270,7 +276,7 @@ def create_proxied_attribute(descriptor): return self._comparator def adapt_to_entity(self, adapt_to_entity): - return self.__class__(self.class_, self.key, self.descriptor, + return self.__class__(adapt_to_entity.entity, self.key, self.descriptor, self._comparator, adapt_to_entity) diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 973707249..1b8f53c9d 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -331,8 +331,10 @@ class AliasedClass(object): else: raise AttributeError(key) - if isinstance(attr, attributes.QueryableAttribute): - return _aliased_insp._adapt_prop(attr, key) + if isinstance(attr, PropComparator): + ret = attr.adapt_to_entity(_aliased_insp) + setattr(self, key, ret) + return ret elif hasattr(attr, 'func_code'): is_method = getattr(_aliased_insp._target, key, None) if is_method and is_method.__self__ is not None: @@ -343,7 +345,8 @@ class AliasedClass(object): ret = attr.__get__(None, self) if isinstance(ret, PropComparator): return ret.adapt_to_entity(_aliased_insp) - return ret + else: + return ret else: return attr @@ -465,17 +468,6 @@ class AliasedInsp(_InspectionAttr): 'parentmapper': self.mapper} ) - def _adapt_prop(self, existing, key): - comparator = existing.comparator.adapt_to_entity(self) - queryattr = attributes.QueryableAttribute( - self.entity, key, - impl=existing.impl, - parententity=self, - comparator=comparator) - setattr(self.entity, key, queryattr) - return queryattr - - def _entity_for_mapper(self, mapper): self_poly = self.with_polymorphic_mappers if mapper in self_poly: |