diff options
| -rw-r--r-- | CHANGES | 6 | ||||
| -rw-r--r-- | lib/sqlalchemy/ext/mutable.py | 20 | ||||
| -rw-r--r-- | test/ext/test_mutable.py | 18 |
3 files changed, 34 insertions, 10 deletions
@@ -89,6 +89,12 @@ CHANGES mapping, the attributes beyond the first would not get instrumented. + - Fixed bug in the mutable extension whereby + if None or a non-corresponding type were set, + an error would be raised. None is now accepted + which assigns None to all attributes, + illegal values raise ValueError. + - examples - Repaired the examples/versioning test runner to not rely upon SQLAlchemy test libs, diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py index b31710ca8..ece7e3ad4 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -347,6 +347,16 @@ class MutableBase(object): return weakref.WeakKeyDictionary() @classmethod + def coerce(cls, key, value): + """Given a value, coerce it into this type. + + By default raises ValueError. + """ + if value is None: + return None + raise ValueError("Attribute '%s' does not accept objects of type %s" % (key, type(value))) + + @classmethod def _listen_on_attribute(cls, attribute, coerce, parent_cls): """Establish this type as a mutation listener for the given mapped descriptor. @@ -424,16 +434,6 @@ class Mutable(MutableBase): flag_modified(parent, key) @classmethod - def coerce(cls, key, value): - """Given a value, coerce it into this type. - - By default raises ValueError. - """ - if value is None: - return None - raise ValueError("Attribute '%s' does not accept objects of type %s" % (key, type(value))) - - @classmethod def associate_with_attribute(cls, attribute): """Establish this type as a mutation listener for the given mapped descriptor. diff --git a/test/ext/test_mutable.py b/test/ext/test_mutable.py index 9d0a4a0c8..df4006c01 100644 --- a/test/ext/test_mutable.py +++ b/test/ext/test_mutable.py @@ -355,6 +355,24 @@ class MutableCompositesTest(_CompositeTestBase, fixtures.MappedTest): f2.data.y = 12 assert f2 in sess.dirty + def test_set_none(self): + sess = Session() + f1 = Foo(data=None) + sess.add(f1) + sess.commit() + eq_(f1.data, Point(None, None)) + + f1.data.y = 5 + sess.commit() + eq_(f1.data, Point(None, 5)) + + def test_set_illegal(self): + f1 = Foo() + assert_raises_message( + ValueError, + "Attribute 'data' does not accept objects", + setattr, f1, 'data', 'foo' + ) class MutableInheritedCompositesTest(_CompositeTestBase, fixtures.MappedTest): @classmethod |
