diff options
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 19 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 13 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 37 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 5 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/util.py | 2 |
5 files changed, 55 insertions, 21 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 86da9a61d..7effd8e58 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -131,7 +131,7 @@ class QueryableAttribute(interfaces._MappedAttribute, self.key = key self.impl = impl self.comparator = comparator - self.parententity = parententity + self._parententity = parententity self._of_type = of_type manager = manager_of_class(class_) @@ -159,6 +159,10 @@ class QueryableAttribute(interfaces._MappedAttribute, return self @property + def parent(self): + return self._parententity + + @property def expression(self): return self.comparator.__clause_element__() @@ -171,7 +175,7 @@ class QueryableAttribute(interfaces._MappedAttribute, self.key, self.impl, self.comparator.of_type(cls), - self.parententity, + self._parententity, of_type=cls) def label(self, name): @@ -191,9 +195,11 @@ class QueryableAttribute(interfaces._MappedAttribute, return getattr(self.comparator, key) except AttributeError: raise AttributeError( - 'Neither %r object nor %r object has an attribute %r' % ( + 'Neither %r object nor %r object associated with %s ' + 'has an attribute %r' % ( type(self).__name__, type(self.comparator).__name__, + self, key) ) @@ -281,7 +287,7 @@ def create_proxied_attribute(descriptor): return self.descriptor.__get__(instance, owner) def __str__(self): - return self.key + return "%s.%s" % (self.class_.__name__, self.key) def __getattr__(self, attribute): """Delegate __getattr__ to the original descriptor and/or @@ -294,12 +300,15 @@ def create_proxied_attribute(descriptor): return getattr(self.comparator, attribute) except AttributeError: raise AttributeError( - 'Neither %r object nor %r object has an attribute %r' % ( + 'Neither %r object nor %r object associated with %s ' + 'has an attribute %r' % ( type(descriptor).__name__, type(self.comparator).__name__, + self, attribute) ) + Proxy.__name__ = type(descriptor).__name__ + 'Proxy' util.monkeypatch_proxied_specials(Proxy, type(descriptor), diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index 272d4edd5..b30630434 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -305,11 +305,12 @@ class PropComparator(operators.ColumnOperators): """ - def __init__(self, prop, mapper, adapter=None): + def __init__(self, prop, parentmapper, adapter=None): self.prop = self.property = prop - self.mapper = mapper + self._parentmapper = parentmapper self.adapter = adapter + def __clause_element__(self): raise NotImplementedError("%r" % self) @@ -319,7 +320,7 @@ class PropComparator(operators.ColumnOperators): """ - return self.__class__(self.prop, self.mapper, adapter) + return self.__class__(self.prop, self._parentmapper, adapter) @staticmethod def any_op(a, b, **kwargs): @@ -503,7 +504,7 @@ class PropertyOption(MapperOption): d['key'] = ret = [] for token in util.to_list(self.key): if isinstance(token, PropComparator): - ret.append((token.mapper.class_, token.key)) + ret.append((token._parentmapper.class_, token.key)) else: ret.append(token) return d @@ -628,7 +629,7 @@ class PropertyOption(MapperOption): # matching tokens to entities if current_path: if current_path[0:2] == \ - [token.parententity, prop.key]: + [token._parententity, prop.key]: current_path = current_path[2:] continue else: @@ -638,7 +639,7 @@ class PropertyOption(MapperOption): entity = self._find_entity_prop_comparator( query, prop.key, - token.parententity, + token._parententity, raiseerr) if not entity: return no_result diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 048b4fad3..a0abb2743 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -189,8 +189,8 @@ class ColumnProperty(StrategizedProperty): return self.adapter(self.prop.columns[0]) else: return self.prop.columns[0]._annotate({ - "parententity": self.mapper, - "parentmapper": self.mapper}) + "parententity": self._parentmapper, + "parentmapper": self._parentmapper}) def __getattr__(self, key): """proxy attribute access down to the mapped column. @@ -352,13 +352,13 @@ class RelationshipProperty(StrategizedProperty): _of_type = None - def __init__(self, prop, mapper, of_type=None, adapter=None): + def __init__(self, prop, parentmapper, of_type=None, adapter=None): """Construction of :class:`.RelationshipProperty.Comparator` is internal to the ORM's attribute mechanics. """ self.prop = prop - self.mapper = mapper + self._parentmapper = parentmapper self.adapter = adapter if of_type: self._of_type = of_type @@ -370,14 +370,37 @@ class RelationshipProperty(StrategizedProperty): """ - return self.__class__(self.property, self.mapper, + return self.__class__(self.property, self._parentmapper, getattr(self, '_of_type', None), adapter) @util.memoized_property - def parententity(self): + def mapper(self): + """The target :class:`.Mapper` referred to by this + :class:`.RelationshipProperty.Comparator. + + This is the "target" or "remote" side of the + :func:`.relationship`. + + """ + return self.property.mapper + + @util.memoized_property + def parent(self): + """The parent :class:`.Mapper` or :class:`.AliasedClass` + referred to by this + :class:`.RelationshipProperty.Comparator. + + This is the "parent" or "local" side of the + :func:`.relationship`. + + """ return self.property.parent + @util.memoized_property + def _parententity(self): + return self.parent + def _source_selectable(self): elem = self.property.parent._with_polymorphic_selectable if self.adapter: @@ -412,7 +435,7 @@ class RelationshipProperty(StrategizedProperty): """ return RelationshipProperty.Comparator( self.property, - self.mapper, + self._parentmapper, cls, adapter=self.adapter) def in_(self, other): diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index a6d20a973..02fb7d4f7 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1727,7 +1727,7 @@ class Query(object): # and Class is that of the current joinpoint elif from_joinpoint and \ isinstance(onclause, interfaces.PropComparator): - left_entity = onclause.parententity + left_entity = onclause._parententity info = inspect(self._joinpoint_zero()) left_mapper, left_selectable, left_is_aliased = \ @@ -1750,7 +1750,8 @@ class Query(object): else: right_entity = onclause.property.mapper - left_entity = onclause.parententity + left_entity = onclause._parententity + assert left_entity is onclause.parent prop = onclause.property if not isinstance(onclause, attributes.QueryableAttribute): diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 2e38e0ce3..fb4197c58 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -464,7 +464,7 @@ class AliasedClass(object): # used to assign a name to the RowTuple object # returned by Query. self._sa_label_name = aliased_insp.name - self.__name__ = 'AliasedClass_' + str(self.__target) + self.__name__ = 'AliasedClass_%s' % self.__target.__name__ @util.memoized_property def _sa_path_registry(self): |
