]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- step one, remove "resolve_synonyms" and start using class attribute
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 6 Aug 2010 17:19:59 +0000 (13:19 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 6 Aug 2010 17:19:59 +0000 (13:19 -0400)
access to get at mapped properties by name

lib/sqlalchemy/orm/dynamic.py
lib/sqlalchemy/orm/interfaces.py
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/properties.py
lib/sqlalchemy/orm/query.py
lib/sqlalchemy/orm/scoping.py
lib/sqlalchemy/orm/strategies.py
lib/sqlalchemy/orm/util.py
test/orm/test_mapper.py
test/orm/test_query.py

index d558380114fd4cee7230c1c7b7ccfe0a55084974..d2063dbc6f79c9f0a262375c8a4e9f3d800c7715 100644 (file)
@@ -192,7 +192,7 @@ class AppenderMixin(object):
         self.attr = attr
 
         mapper = object_mapper(instance)
-        prop = mapper.get_property(self.attr.key, resolve_synonyms=True)
+        prop = mapper.get_property(self.attr.key)
         self._criterion = prop.compare(
                             operators.eq, 
                             instance, 
index 91c2ae403e68b80156f86ae46d5e0f7dcf4c5f1a..40531697696b486e0b2c0ab3664d88467150e236 100644 (file)
@@ -838,8 +838,10 @@ class PropertyOption(MapperOption):
                     path_element = entity.path_entity
                     mapper = entity.mapper
                 mappers.append(mapper)
-                prop = mapper.get_property(token,
-                        resolve_synonyms=True, raiseerr=raiseerr)
+                if mapper.has_property(token):
+                    prop = mapper.get_property(token)
+                else:
+                    prop = None
                 key = token
             elif isinstance(token, PropComparator):
                 prop = token.property
index 9cb3581517182adf46e3f8ff26c085e6ad29b158..7c2f550eb7eb853ffd52c64391380dd7428cf3b7 100644 (file)
@@ -905,26 +905,22 @@ class Mapper(object):
     def has_property(self, key):
         return key in self._props
 
-    def get_property(self, key, resolve_synonyms=False, raiseerr=True):
-        """return a MapperProperty associated with the given key."""
+    def get_property(self, key, _compile_mappers=True):
+        """return a MapperProperty associated with the given key.
+        
+        Calls getattr() against the mapped class itself, so that class-level 
+        proxies will be resolved to the underlying property, if any.
+        
+        """
 
-        if not self.compiled:
+        if _compile_mappers and not self.compiled:
             self.compile()
-        return self._get_property(key, 
-                            resolve_synonyms=resolve_synonyms,
-                            raiseerr=raiseerr)
-
-    def _get_property(self, key, resolve_synonyms=False, raiseerr=True):
-        prop = self._props.get(key, None)
-        if resolve_synonyms:
-            while isinstance(prop, SynonymProperty):
-                prop = self._props.get(prop.name, None)
-        if prop is None and raiseerr:
+        try:
+            return getattr(self.class_, key).property
+        except AttributeError:
             raise sa_exc.InvalidRequestError(
-                    "Mapper '%s' has no property '%s'" % 
-                    (self, key))
-        return prop
-    
+                    "Mapper '%s' has no property '%s'" % (self, key))
+            
     @property
     def iterate_properties(self):
         """return an iterator of all MapperProperty objects."""
index cf5f31162f05abe304c602cafb85c00413dbd92e..53503862bb624d61650035642889b1464a3d126a 100644 (file)
@@ -284,7 +284,7 @@ class ConcreteInheritedProperty(MapperProperty):
         comparator_callable = None
         # TODO: put this process into a deferred callable?
         for m in self.parent.iterate_to_root():
-            p = m._get_property(self.key)
+            p = m._props[self.key]
             if not isinstance(p, ConcreteInheritedProperty):
                 comparator_callable = p.comparator_factory
                 break
@@ -337,8 +337,8 @@ class SynonymProperty(MapperProperty):
 
         def comparator_callable(prop, mapper):
             def comparator():
-                prop = self.parent._get_property(
-                                        self.key, resolve_synonyms=True)
+                prop = getattr(self.parent.class_,
+                                        self.name).property
                 if self.comparator_factory:
                     return self.comparator_factory(prop, mapper)
                 else:
@@ -837,7 +837,7 @@ class RelationshipProperty(StrategizedProperty):
                     yield (c, instance_mapper, instance_state)
 
     def _add_reverse_property(self, key):
-        other = self.mapper._get_property(key)
+        other = self.mapper.get_property(key, _compile_mappers=False)
         self._reverse_property.add(other)
         other._reverse_property.add(self)
         
@@ -924,8 +924,7 @@ class RelationshipProperty(StrategizedProperty):
         if not self.parent.concrete:
             for inheriting in self.parent.iterate_to_root():
                 if inheriting is not self.parent \
-                    and inheriting._get_property(self.key,
-                        raiseerr=False):
+                    and inheriting.has_property(self.key):
                     util.warn("Warning: relationship '%s' on mapper "
                               "'%s' supercedes the same relationship "
                               "on inherited mapper '%s'; this can "
@@ -1216,7 +1215,7 @@ class RelationshipProperty(StrategizedProperty):
     def _assert_is_primary(self):
         if not self.is_primary() \
             and not mapper.class_mapper(self.parent.class_,
-                compile=False)._get_property(self.key, raiseerr=False):
+                compile=False).has_property(self.key):
             raise sa_exc.ArgumentError("Attempting to assign a new "
                     "relationship '%s' to a non-primary mapper on "
                     "class '%s'.  New relationships can only be added "
@@ -1234,8 +1233,7 @@ class RelationshipProperty(StrategizedProperty):
             else:
                 backref_key, kwargs = self.backref
             mapper = self.mapper.primary_mapper()
-            if mapper._get_property(backref_key, raiseerr=False) \
-                is not None:
+            if mapper.has_property(backref_key):
                 raise sa_exc.ArgumentError("Error creating backref "
                         "'%s' on relationship '%s': property of that "
                         "name exists on mapper '%s'" % (backref_key,
index cc6d15a74b3ad343407f3094ca01e1f89617cfc0..8d468babe32168803eed23fa579d0bccfc247903 100644 (file)
@@ -662,7 +662,7 @@ class Query(object):
                             instance.__class__.__name__)
                         )
         else:
-            prop = mapper.get_property(property, resolve_synonyms=True)
+            prop = mapper.get_property(property)
         return self.filter(prop.compare(
                                 operators.eq, 
                                 instance, value_is_parent=True))
index 40bbb3299d9dfc2a3cc2fb624bf10e78c015c4c2..1b9ad8e6f0a280ee063aa24b1484dc48e5f72ec5 100644 (file)
@@ -179,8 +179,7 @@ class _ScopedExt(MapperExtension):
         def __init__(self, **kwargs):
             for key, value in kwargs.iteritems():
                 if ext.validate:
-                    if not mapper.get_property(key, resolve_synonyms=False,
-                                               raiseerr=False):
+                    if not mapper.has_property(key):
                         raise sa_exc.ArgumentError(
                             "Invalid __init__ argument: '%s'" % key)
                 setattr(self, key, value)
index 1c4571aed8257c5a13a2ea82a39050c7110c51dd..afa3ebf4ca5db9cef31bdb90d8eb61a452969413 100644 (file)
@@ -1215,7 +1215,7 @@ class LoadEagerFromAliasOption(PropertyOption):
             if isinstance(self.alias, basestring):
                 mapper = mappers[-1]
                 (root_mapper, propname) = paths[-1][-2:]
-                prop = mapper.get_property(propname, resolve_synonyms=True)
+                prop = mapper.get_property(propname)
                 self.alias = prop.target.alias(self.alias)
             query._attributes[
                         ("user_defined_eager_row_processor", 
@@ -1224,7 +1224,7 @@ class LoadEagerFromAliasOption(PropertyOption):
         else:
             (root_mapper, propname) = paths[-1][-2:]
             mapper = mappers[-1]
-            prop = mapper.get_property(propname, resolve_synonyms=True)
+            prop = mapper.get_property(propname)
             adapter = query._polymorphic_adapters.get(prop.mapper, None)
             query._attributes[
                         ("user_defined_eager_row_processor", 
index ef5413724b22a3b68ad19e0372b33132e6d4cc6d..c9004990ab7a07814420d99c4e0ab9bb3c8f3073 100644 (file)
@@ -347,10 +347,6 @@ class AliasedClass(object):
         return queryattr
 
     def __getattr__(self, key):
-        prop = self.__mapper._get_property(key, raiseerr=False)
-        if prop:
-            return self.__adapt_prop(prop)
-
         for base in self.__target.__mro__:
             try:
                 attr = object.__getattribute__(base, key)
@@ -360,7 +356,10 @@ class AliasedClass(object):
                 break
         else:
             raise AttributeError(key)
-
+        
+        if isinstance(attr, attributes.QueryableAttribute):
+            return self.__adapt_prop(attr.property)
+            
         if hasattr(attr, 'func_code'):
             is_method = getattr(self.__target, key, None)
             if is_method and is_method.im_self is not None:
@@ -494,7 +493,7 @@ def with_parent(instance, prop):
     """
     if isinstance(prop, basestring):
         mapper = object_mapper(instance)
-        prop = mapper.get_property(prop, resolve_synonyms=True)
+        prop = mapper.get_property(prop)
     elif isinstance(prop, attributes.QueryableAttribute):
         prop = prop.property
 
index e24906a1f57e99954c6e4776ab74fbab97b34b5d..e301b8d07ec47edfbc18928a2317bd7a7573253d 100644 (file)
@@ -1543,10 +1543,22 @@ class ComparatorFactoryTest(_fixtures.FixtureTest, AssertsCompiledSQL):
         class MyFactory(ColumnProperty.Comparator):
             __hash__ = None
             def __eq__(self, other):
-                return func.foobar(self.__clause_element__()) == func.foobar(other)
-        mapper(User, users, properties={'name':synonym('_name', map_column=True, comparator_factory=MyFactory)})
-        self.assert_compile(User.name == 'ed', "foobar(users.name) = foobar(:foobar_1)", dialect=default.DefaultDialect())
-        self.assert_compile(aliased(User).name == 'ed', "foobar(users_1.name) = foobar(:foobar_1)", dialect=default.DefaultDialect())
+                return func.foobar(self.__clause_element__()) ==\
+                            func.foobar(other)
+
+        mapper(User, users, properties={
+                    'name':synonym('_name', map_column=True,
+                                    comparator_factory=MyFactory)
+                    })
+        self.assert_compile(
+                    User.name == 'ed', 
+                    "foobar(users.name) = foobar(:foobar_1)",
+                    dialect=default.DefaultDialect())
+
+        self.assert_compile(
+                    aliased(User).name == 'ed', 
+                    "foobar(users_1.name) = foobar(:foobar_1)",
+                    dialect=default.DefaultDialect())
 
     @testing.resolve_artifact_names
     def test_relationship(self):
index ebe72b56550032259ddf1f26f2e048de1e34df24..5fa316b76fcd9631648903508359d0e0a7f61ae2 100644 (file)
@@ -3448,53 +3448,92 @@ class SelectFromTest(QueryTest, AssertsCompiledSQL):
             'orders':relationship(Order, backref='user'), # o2m, m2o
         })
         mapper(Order, orders, properties={
-            'items':relationship(Item, secondary=order_items, order_by=items.c.id),  #m2m
+            'items':relationship(Item, secondary=order_items,
+                                        order_by=items.c.id),  #m2m
         })
         mapper(Item, items, properties={
-            'keywords':relationship(Keyword, secondary=item_keywords, order_by=keywords.c.id) #m2m
+            'keywords':relationship(Keyword, secondary=item_keywords,
+                                        order_by=keywords.c.id) #m2m
         })
         mapper(Keyword, keywords)
 
-        sel = users.select(users.c.id.in_([7, 8]))
         sess = create_session()
-    
-        eq_(sess.query(User).select_from(sel).join('orders', 'items', 'keywords').filter(Keyword.name.in_(['red', 'big', 'round'])).all(), [
+        sel = users.select(users.c.id.in_([7, 8]))
+
+        eq_(sess.query(User).select_from(sel).\
+                join('orders', 'items', 'keywords').\
+                filter(Keyword.name.in_(['red', 'big', 'round'])).\
+                all(), 
+        [
             User(name=u'jack',id=7)
         ])
 
-        eq_(sess.query(User).select_from(sel).join('orders', 'items', 'keywords', aliased=True).filter(Keyword.name.in_(['red', 'big', 'round'])).all(), [
+        eq_(sess.query(User).select_from(sel).\
+                    join('orders', 'items', 'keywords', aliased=True).\
+                    filter(Keyword.name.in_(['red', 'big', 'round'])).\
+                    all(), 
+        [
             User(name=u'jack',id=7)
         ])
 
         def go():
             eq_(
                 sess.query(User).select_from(sel).
-                            options(joinedload_all('orders.items.keywords')).
-                            join('orders', 'items', 'keywords', aliased=True).
-                            filter(Keyword.name.in_(['red', 'big', 'round'])).all(), 
+                        options(joinedload_all('orders.items.keywords')).
+                        join('orders', 'items', 'keywords', aliased=True).
+                        filter(Keyword.name.in_(['red', 'big', 'round'])).\
+                        all(), 
                 [
                 User(name=u'jack',orders=[
                     Order(description=u'order 1',items=[
-                        Item(description=u'item 1',keywords=[Keyword(name=u'red'), Keyword(name=u'big'), Keyword(name=u'round')]),
-                        Item(description=u'item 2',keywords=[Keyword(name=u'red',id=2), Keyword(name=u'small',id=5), Keyword(name=u'square')]),
-                        Item(description=u'item 3',keywords=[Keyword(name=u'green',id=3), Keyword(name=u'big',id=4), Keyword(name=u'round',id=6)])
+                        Item(description=u'item 1',
+                            keywords=[
+                                Keyword(name=u'red'), 
+                                Keyword(name=u'big'),
+                                Keyword(name=u'round')
+                            ]),
+                        Item(description=u'item 2',
+                            keywords=[
+                                Keyword(name=u'red',id=2),
+                                Keyword(name=u'small',id=5),
+                                Keyword(name=u'square')
+                            ]),
+                        Item(description=u'item 3',
+                                keywords=[
+                                    Keyword(name=u'green',id=3),
+                                    Keyword(name=u'big',id=4),
+                                    Keyword(name=u'round',id=6)])
                     ]),
                     Order(description=u'order 3',items=[
-                        Item(description=u'item 3',keywords=[Keyword(name=u'green',id=3), Keyword(name=u'big',id=4), Keyword(name=u'round',id=6)]),
+                        Item(description=u'item 3',
+                                keywords=[
+                                    Keyword(name=u'green',id=3),
+                                    Keyword(name=u'big',id=4),
+                                    Keyword(name=u'round',id=6)
+                                ]),
                         Item(description=u'item 4',keywords=[],id=4),
                         Item(description=u'item 5',keywords=[],id=5)
                         ]),
-                    Order(description=u'order 5',items=[Item(description=u'item 5',keywords=[])])])
+                    Order(description=u'order 5',
+                        items=[
+                            Item(description=u'item 5',keywords=[])])
+                        ])
                 ])
         self.assert_sql_count(testing.db, go, 1)
-
+        
         sess.expunge_all()
         sel2 = orders.select(orders.c.id.in_([1,2,3]))
-        eq_(sess.query(Order).select_from(sel2).join('items', 'keywords').filter(Keyword.name == 'red').order_by(Order.id).all(), [
+        eq_(sess.query(Order).select_from(sel2).\
+                    join('items', 'keywords').\
+                    filter(Keyword.name == 'red').\
+                    order_by(Order.id).all(), [
             Order(description=u'order 1',id=1),
             Order(description=u'order 2',id=2),
         ])
-        eq_(sess.query(Order).select_from(sel2).join('items', 'keywords', aliased=True).filter(Keyword.name == 'red').order_by(Order.id).all(), [
+        eq_(sess.query(Order).select_from(sel2).\
+                    join('items', 'keywords', aliased=True).\
+                    filter(Keyword.name == 'red').\
+                    order_by(Order.id).all(), [
             Order(description=u'order 1',id=1),
             Order(description=u'order 2',id=2),
         ])