]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- moved SynonymProperty to interfaces, since its more generalized and synonym-aware...
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 20 Feb 2007 00:09:37 +0000 (00:09 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 20 Feb 2007 00:09:37 +0000 (00:09 +0000)
take place without knowning so much about properties
- mapper options like eagerload(), lazyload(), deferred(), will work for "synonym()" relationships [ticket:485]

CHANGES
lib/sqlalchemy/orm/__init__.py
lib/sqlalchemy/orm/interfaces.py
lib/sqlalchemy/orm/properties.py
lib/sqlalchemy/orm/query.py
test/orm/mapper.py

diff --git a/CHANGES b/CHANGES
index 2a768269615a7f9ab997dec95a7e2e8591e4446f..5a2ee05606429637ed38fd06edc9075f7657ceb7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -33,6 +33,8 @@
   - improved support for complex queries embedded into "where" criterion
   for query.select() [ticket:449]
   - contains_eager('foo') automatically implies eagerload('foo')
+  - mapper options like eagerload(), lazyload(), deferred(), will work for "synonym()"
+  relationships [ticket:485]
   - fixed bug where cascade operations incorrectly included deleted collection
   items in the cascade [ticket:445]
   - fixed relationship deletion error when one-to-many child item is moved to a new 
index 3fab0e63e5f0d2cf43327b6eba6c19066cf69f67..222383085dac7e4ba37a677349a0a5270f69cc87 100644 (file)
@@ -14,7 +14,7 @@ from sqlalchemy.orm.mapper import *
 from sqlalchemy.orm import mapper as mapperlib
 from sqlalchemy.orm.query import Query
 from sqlalchemy.orm.util import polymorphic_union
-from sqlalchemy.orm import properties, strategies
+from sqlalchemy.orm import properties, strategies, interfaces
 from sqlalchemy.orm.session import Session as create_session
 from sqlalchemy.orm.session import object_session, attribute_manager
 
@@ -59,7 +59,7 @@ def synonym(name, proxy=False):
     """set up 'name' as a synonym to another MapperProperty.  
     
     Used with the 'properties' dictionary sent to mapper()."""
-    return properties.SynonymProperty(name, proxy=proxy)
+    return interfaces.SynonymProperty(name, proxy=proxy)
 
 def compile_mappers():
     """compile all mappers that have been defined.  
index f40856b41a27df25682278c5bbfd5d31a296db4d..0327205ce9dd78ffb95d0c2ced39fd593ce3351a 100644 (file)
@@ -58,7 +58,31 @@ class MapperProperty(object):
         """returns a compare operation for the columns represented by this MapperProperty to the given value,
         which may be a column value or an instance."""
         raise NotImplementedError()
-        
+
+class SynonymProperty(MapperProperty):
+    def __init__(self, name, proxy=False):
+        self.name = name
+        self.proxy = proxy
+    def setup(self, querycontext, **kwargs):
+        pass
+    def execute(self, selectcontext, instance, row, identitykey, isnew):
+        pass
+    def do_init(self):
+        if not self.proxy:
+            return
+        class SynonymProp(object):
+            def __set__(s, obj, value):
+                setattr(obj, self.name, value)
+            def __delete__(s, obj):
+                delattr(obj, self.name)
+            def __get__(s, obj, owner):
+                if obj is None:
+                    return s
+                return getattr(obj, self.name)
+        setattr(self.parent.class_, self.key, SynonymProp())
+    def merge(self, session, source, dest, _recursive):
+        pass
+
 class StrategizedProperty(MapperProperty):
     """a MapperProperty which uses selectable strategies to affect loading behavior.
     There is a single default strategy selected, and alternate strategies can be selected
@@ -135,6 +159,8 @@ class PropertyOption(MapperOption):
             mapper = context.mapper
             for token in self.key.split('.'):
                 prop = mapper.props[token]
+                if isinstance(prop, SynonymProperty):
+                    prop = mapper.props[prop.name]
                 mapper = getattr(prop, 'mapper', None)
             self.__prop = prop
         return prop
index 2d18ccaa2a7ab9ba34c43ccc5c3bcf81c2fd479f..cd9624e96b916c5dc4d24c0048dd71c619c26193 100644 (file)
@@ -15,31 +15,6 @@ from sqlalchemy.orm import session as sessionlib
 from sqlalchemy.orm import util as mapperutil
 import sets, random
 from sqlalchemy.orm.interfaces import *
-
-
-class SynonymProperty(MapperProperty):
-    def __init__(self, name, proxy=False):
-        self.name = name
-        self.proxy = proxy
-    def setup(self, querycontext, **kwargs):
-        pass
-    def execute(self, selectcontext, instance, row, identitykey, isnew):
-        pass
-    def do_init(self):
-        if not self.proxy:
-            return
-        class SynonymProp(object):
-            def __set__(s, obj, value):
-                setattr(obj, self.name, value)
-            def __delete__(s, obj):
-                delattr(obj, self.name)
-            def __get__(s, obj, owner):
-                if obj is None:
-                    return s
-                return getattr(obj, self.name)
-        setattr(self.parent.class_, self.key, SynonymProp())
-    def merge(self, session, source, dest, _recursive):
-        pass
         
 class ColumnProperty(StrategizedProperty):
     """describes an object attribute that corresponds to a table column."""
index e7b12437279fcdf0e0c88806f3cf1bb25fc7b6f5..bf64266388c2829f22639bfb9d9bbfc3571a5e5a 100644 (file)
@@ -6,7 +6,7 @@
 
 from sqlalchemy import sql, util, exceptions, sql_util, logging, schema
 from sqlalchemy.orm import mapper, class_mapper
-from sqlalchemy.orm.interfaces import OperationContext
+from sqlalchemy.orm.interfaces import OperationContext, SynonymProperty
 
 __all__ = ['Query', 'QueryContext', 'SelectionContext']
 
@@ -149,7 +149,7 @@ class Query(object):
             seen.add(mapper_)
             if mapper_.props.has_key(key):
                 prop = mapper_.props[key]
-                if isinstance(prop, properties.SynonymProperty):
+                if isinstance(prop, SynonymProperty):
                     prop = mapper_.props[prop.name]
                 if isinstance(prop, properties.PropertyLoader):
                     keys.insert(0, prop.key)
index ed4cb897738865bebc6d78718b8945480a3ca93a..aa3ca04773d9952289d01f3771ee7656f5840114 100644 (file)
@@ -402,7 +402,19 @@ class MapperTest(MapperSuperTest):
         assert u.uname == "some user name"
         assert u.user_name == "some user name"
         assert u in sess.dirty
-    
+
+    def testsynonymoptions(self):
+        sess = create_session()
+        mapper(User, users, properties = dict(
+            addresses = relation(mapper(Address, addresses), lazy = True),
+            adlist = synonym('addresses', proxy=True)
+        ))
+        
+        def go():
+            u = sess.query(User).options(eagerload('adlist')).get_by(user_name='jack')
+            self.assert_result(u.adlist, Address, *(user_address_result[0]['addresses'][1]))
+        self.assert_sql_count(db, go, 1)
+        
     def testextensionoptions(self):
         sess  = create_session()
         class ext1(MapperExtension):