"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
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):
"""
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):
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
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()
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()