From 409a95adf44f577a204114469ff414bebefca293 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 1 Jul 2011 11:32:07 -0400 Subject: [PATCH] - 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. --- CHANGES | 6 ++++++ lib/sqlalchemy/ext/mutable.py | 20 ++++++++++---------- test/ext/test_mutable.py | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 92881a3416..4c2243f9fb 100644 --- a/CHANGES +++ b/CHANGES @@ -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 b31710ca8b..ece7e3ad48 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -346,6 +346,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 @@ -423,16 +433,6 @@ class Mutable(MutableBase): for parent, key in self._parents.items(): 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 diff --git a/test/ext/test_mutable.py b/test/ext/test_mutable.py index 9d0a4a0c89..df4006c01b 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 -- 2.39.5