]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed bugs in sqlalchemy.ext.mutable extension where
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 14 May 2011 14:23:12 +0000 (10:23 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 14 May 2011 14:23:12 +0000 (10:23 -0400)
    `None` was not appropriately handled, replacement
    events were not appropriately handled.
    [ticket:2143]

CHANGES
lib/sqlalchemy/ext/mutable.py
test/ext/test_mutable.py

diff --git a/CHANGES b/CHANGES
index ec90b8bd87ec81baa423126f5956eb758d64df23..e8e29e3e795a673cd91e9e66b7f5734d85daf075 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -132,6 +132,12 @@ CHANGES
     "generic_associations".   Each presents an alternative
     table layout.
 
+- ext
+  - Fixed bugs in sqlalchemy.ext.mutable extension where
+    `None` was not appropriately handled, replacement
+    events were not appropriately handled.
+    [ticket:2143]
+
 0.7.0b4
 =======
 - general
index d14cfe3c0f11466bf0edd7907f4445486440458e..078f9f3a2d89b9ad2ac27dc75ebbaebd6d28a97f 100644 (file)
@@ -378,12 +378,12 @@ class MutableBase(object):
             outgoing.
 
             """
-
             if not isinstance(value, cls):
-                value = cls.coerce(key, value) 
-            value._parents[target.obj()] = key
+                value = cls.coerce(key, value)
+            if value is not None:
+                value._parents[target.obj()] = key
             if isinstance(oldvalue, cls):
-                oldvalue._parents.pop(state.obj(), None)
+                oldvalue._parents.pop(target.obj(), None)
             return value
 
         def pickle(state, state_dict):
@@ -426,7 +426,7 @@ class Mutable(MutableBase):
         """
         if value is None:
             return None
-        raise ValueError("Attribute '%s' accepts objects of type %s" % (key, cls))
+        raise ValueError("Attribute '%s' does not accept objects of type %s" % (key, type(value)))
 
     @classmethod
     def associate_with_attribute(cls, attribute):
index 236d711b2a96c6ec2ce3ae04321e31c2b7875090..ceff0d6499c9e96acac15bbfb9606ddfb19c2457 100644 (file)
@@ -4,7 +4,7 @@ from sqlalchemy.orm import mapper, Session, composite
 from sqlalchemy.orm.mapper import Mapper
 from sqlalchemy.orm.instrumentation import ClassManager
 from test.lib.schema import Table, Column
-from test.lib.testing import eq_
+from test.lib.testing import eq_, assert_raises_message
 from test.lib.util import picklers
 from test.lib import testing
 from test.lib import fixtures
@@ -60,6 +60,21 @@ class _MutableDictTestBase(object):
         ClassManager.dispatch._clear()
         super(_MutableDictTestBase, self).teardown()
 
+    def test_coerce_none(self):
+        sess = Session()
+        f1 = Foo(data=None)
+        sess.add(f1)
+        sess.commit()
+        eq_(f1.data, None)
+
+    def test_coerce_raise(self):
+        assert_raises_message(
+            ValueError,
+            "Attribute 'data' does not accept objects of "
+            "type <type 'set'>",
+            Foo, data=set([1,2,3])
+        )
+
     def test_in_place_mutation(self):
         sess = Session()
 
@@ -72,6 +87,16 @@ class _MutableDictTestBase(object):
 
         eq_(f1.data, {'a':'c'})
 
+    def test_replace(self):
+        sess = Session()
+        f1 = Foo(data={'a':'b'})
+        sess.add(f1)
+        sess.flush()
+
+        f1.data = {'b':'c'}
+        sess.commit()
+        eq_(f1.data, {'b':'c'})
+
     def test_pickle_parent(self):
         sess = Session()