]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Mutable collection passed to the "extension" attribute
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 23 Oct 2009 19:46:58 +0000 (19:46 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 23 Oct 2009 19:46:58 +0000 (19:46 +0000)
of relation(), column_property() etc. will not be mutated
or shared among multiple instrumentation calls, preventing
duplicate extensions, such as backref populators,
from being inserted into the list.
[ticket:1585]

CHANGES
lib/sqlalchemy/orm/properties.py
lib/sqlalchemy/orm/strategies.py
test/orm/test_mapper.py

diff --git a/CHANGES b/CHANGES
index baa34e7896b16e36e5794f4b1c44e0921e325b75..a5b759163e18f45abe9d299781e7e05c0d52da89 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -591,6 +591,13 @@ CHANGES
       by contains_eager() out of individual instance states.
       [ticket:1553]
 
+    - Mutable collection passed to the "extension" attribute
+      of relation(), column_property() etc. will not be mutated
+      or shared among multiple instrumentation calls, preventing
+      duplicate extensions, such as backref populators,
+      from being inserted into the list.
+      [ticket:1585]
+      
 - sql
     - Fixed the "numeric" paramstyle, which apparently is the
       default paramstyle used by Informixdb.
index 9f9bbd62a7ccba7811e73aced1b19e888bef3d50..0ad0ef5a0382bd83ce508af19e584444b853350c 100644 (file)
@@ -1044,7 +1044,7 @@ class RelationProperty(StrategizedProperty):
 
 
         if self.back_populates:
-            self.extension = util.to_list(self.extension) or []
+            self.extension = list(util.to_list(self.extension, default=[]))
             self.extension.append(attributes.GenericBackrefExtension(self.back_populates))
             self._add_reverse_property(self.back_populates)
         
index 5ee99ac136f039f58fd4a2f602d32434f0dddef9..08c60a1d2376b15ed9e11eba30ed601630d56f75 100644 (file)
@@ -32,7 +32,7 @@ def _register_attribute(strategy, mapper, useobject,
 ):
 
     prop = strategy.parent_property
-    attribute_ext = util.to_list(prop.extension) or []
+    attribute_ext = list(util.to_list(prop.extension, default=[]))
         
     if useobject and prop.single_parent:
         attribute_ext.insert(0, _SingleParentValidator(prop))
index 1fe0eead3701d885a6769db3e007b144f051459d..62bf636b898aec86c71d1065d1b3ab41604818ed 100644 (file)
@@ -7,7 +7,7 @@ from sqlalchemy import MetaData, Integer, String, ForeignKey, func, util
 from sqlalchemy.test.schema import Table, Column
 from sqlalchemy.engine import default
 from sqlalchemy.orm import mapper, relation, backref, create_session, class_mapper, compile_mappers, reconstructor, validates, aliased
-from sqlalchemy.orm import defer, deferred, synonym, attributes, column_property, composite, relation, dynamic_loader, comparable_property
+from sqlalchemy.orm import defer, deferred, synonym, attributes, column_property, composite, relation, dynamic_loader, comparable_property,AttributeExtension
 from sqlalchemy.test.testing import eq_, AssertsCompiledSQL
 from test.orm import _base, _fixtures
 from sqlalchemy.test.assertsql import AllOf, CompiledSQL
@@ -255,6 +255,28 @@ class MapperTest(_fixtures.FixtureTest):
         mapper(Foo, addresses, inherits=User)
         assert getattr(Foo().__class__, 'name').impl is not None
 
+    @testing.resolve_artifact_names
+    def test_extension_collection_frozen(self):
+        class Foo(User):pass
+        m = mapper(User, users)
+        mapper(Order, orders)
+        compile_mappers()
+        mapper(Foo, addresses, inherits=User)
+        ext_list = [AttributeExtension()]
+        m.add_property('somename', column_property(users.c.name, extension=ext_list))
+        m.add_property('orders', relation(Order, extension=ext_list, backref='user'))
+        assert len(ext_list) == 1
+
+        assert Foo.orders.impl.extensions is User.orders.impl.extensions
+        assert Foo.orders.impl.extensions is not ext_list
+        
+        compile_mappers()
+        assert len(User.somename.impl.extensions) == 1
+        assert len(Foo.somename.impl.extensions) == 1
+        assert len(Foo.orders.impl.extensions) == 3
+        assert len(User.orders.impl.extensions) == 3
+        
+
     @testing.resolve_artifact_names
     def test_compile_on_get_props_1(self):
         m =mapper(User, users)