From 550141b14c8e165218cd32c27d91541eeee86d2a Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 26 Jul 2013 00:01:04 -0400 Subject: - The mechanism by which attribute events pass along an :class:`.AttributeImpl` as an "initiator" token has been changed; the object is now an event-specific object called :class:`.attributes.Event`. Additionally, the attribute system no longer halts events based on a matching "initiator" token; this logic has been moved to be specific to ORM backref event handlers, which are the typical source of the re-propagation of an attribute event onto subsequent append/set/remove operations. End user code which emulates the behavior of backrefs must now ensure that recursive event propagation schemes are halted, if the scheme does not use the backref handlers. Using this new system, backref handlers can now peform a "two-hop" operation when an object is appended to a collection, associated with a new many-to-one, de-associated with the previous many-to-one, and then removed from a previous collection. Before this change, the last step of removal from the previous collection would not occur. [ticket:2789] --- test/orm/test_attributes.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'test/orm/test_attributes.py') diff --git a/test/orm/test_attributes.py b/test/orm/test_attributes.py index 4bcecb71b..f3a6f7d8e 100644 --- a/test/orm/test_attributes.py +++ b/test/orm/test_attributes.py @@ -1162,12 +1162,8 @@ class BackrefTest(fixtures.ORMTest): p2.children.append(c1) assert c1.parent is p2 - # note its still in p1.children - - # the event model currently allows only - # one level deep. without the parent_token, - # it keeps going until a ValueError is raised - # and this condition changes. - assert c1 in p1.children + # event propagates to remove as of [ticket:2789] + assert c1 not in p1.children class CyclicBackrefAssertionTest(fixtures.TestBase): """test that infinite recursion due to incorrect backref assignments -- cgit v1.2.1 From 9a49e09d0bae23bde869842c1444b65dc7e58c3d Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 4 Aug 2013 15:11:17 -0400 Subject: - add predictable_gc to a few more tests showing up on pypy --- test/orm/test_attributes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test/orm/test_attributes.py') diff --git a/test/orm/test_attributes.py b/test/orm/test_attributes.py index f3a6f7d8e..de44e4be3 100644 --- a/test/orm/test_attributes.py +++ b/test/orm/test_attributes.py @@ -294,6 +294,7 @@ class AttributesTest(fixtures.ORMTest): assert state.obj() is None assert state.dict == {} + @testing.requires.predictable_gc def test_object_dereferenced_error(self): class Foo(object): pass @@ -317,7 +318,8 @@ class AttributesTest(fixtures.ORMTest): ) def test_deferred(self): - class Foo(object):pass + class Foo(object): + pass data = {'a':'this is a', 'b':12} def loader(state, keys): -- cgit v1.2.1 From 2b1c8eabb10c932f6e83d08147c75bb05f96a161 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 25 Oct 2013 13:13:24 -0400 Subject: - :func:`.attributes.get_history()` when used with a scalar column-mapped attribute will now honor the "passive" flag passed to it; as this defaults to ``PASSIVE_OFF``, the function will by default query the database if the value is not present. This is a behavioral change vs. 0.8. [ticket:2787] - Added new method :meth:`.AttributeState.load_history`, works like :attr:`.AttributeState.history` but also fires loader callables. --- test/orm/test_attributes.py | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'test/orm/test_attributes.py') diff --git a/test/orm/test_attributes.py b/test/orm/test_attributes.py index de44e4be3..c282bc44c 100644 --- a/test/orm/test_attributes.py +++ b/test/orm/test_attributes.py @@ -1339,7 +1339,7 @@ class PendingBackrefTest(fixtures.ORMTest): ] ) - def test_lazy_history(self): + def test_lazy_history_collection(self): Post, Blog, lazy_posts = self._fixture() p1, p2, p3 = Post("post 1"), Post("post 2"), Post("post 3") @@ -1511,6 +1511,12 @@ class HistoryTest(fixtures.TestBase): return Foo, Bar def _someattr_history(self, f, **kw): + passive = kw.pop('passive', None) + if passive is True: + kw['passive'] = attributes.PASSIVE_NO_INITIALIZE + elif passive is False: + kw['passive'] = attributes.PASSIVE_OFF + return attributes.get_state_history( attributes.instance_state(f), 'someattr', **kw) @@ -1685,19 +1691,19 @@ class HistoryTest(fixtures.TestBase): Foo = self._fixture(uselist=True, useobject=True, active_history=True) f = Foo() - eq_(self._someattr_history(f, passive=True), ((), (), ())) + eq_(self._someattr_history(f, passive=True), (None, None, None)) def test_scalar_obj_never_set(self): Foo = self._fixture(uselist=False, useobject=True, active_history=True) f = Foo() - eq_(self._someattr_history(f, passive=True), ((), (), ())) + eq_(self._someattr_history(f, passive=True), (None, None, None)) def test_scalar_never_set(self): Foo = self._fixture(uselist=False, useobject=False, active_history=True) f = Foo() - eq_(self._someattr_history(f, passive=True), ((), (), ())) + eq_(self._someattr_history(f, passive=True), (None, None, None)) def test_scalar_active_set(self): Foo = self._fixture(uselist=False, useobject=False, @@ -1793,6 +1799,24 @@ class HistoryTest(fixtures.TestBase): eq_(self._someattr_history(f), (['two'], (), ())) + def test_scalar_passive_flag(self): + Foo = self._fixture(uselist=False, useobject=False, + active_history=True) + f = Foo() + f.someattr = 'one' + eq_(self._someattr_history(f), (['one'], (), ())) + + self._commit_someattr(f) + + state = attributes.instance_state(f) + state._expire_attribute_pre_commit(state.dict, 'someattr') + + def scalar_loader(state, toload): + state.dict['someattr'] = 'one' + state.manager.deferred_scalar_loader = scalar_loader + + eq_(self._someattr_history(f), ((), ['one'], ())) + def test_scalar_inplace_mutation_set(self): Foo = self._fixture(uselist=False, useobject=False, @@ -1848,6 +1872,7 @@ class HistoryTest(fixtures.TestBase): f.someattr = ['a'] eq_(self._someattr_history(f), ([['a']], (), ())) + def test_use_object_init(self): Foo, Bar = self._two_obj_fixture(uselist=False) f = Foo() -- cgit v1.2.1