From c7c55d4e2e18b39833554699f2887ffe45350bdf Mon Sep 17 00:00:00 2001 From: Jason Kirtland Date: Fri, 29 Jun 2007 18:28:40 +0000 Subject: [PATCH] Working around the pickle memoization quirk in attributes test. --- lib/sqlalchemy/orm/collections.py | 6 ++-- test/orm/attributes.py | 47 ++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py index 2de417c17c..f485d29b7b 100644 --- a/lib/sqlalchemy/orm/collections.py +++ b/lib/sqlalchemy/orm/collections.py @@ -548,14 +548,12 @@ class CollectionAdaptor(object): self.attr.fire_remove_event(self._owner(), item, initiator) def __getstate__(self): - # FIXME: temporarily reversing the key *only* for the purposes of - # the pickle unittest. it needs a solution there, not here. - return { 'key': self.attr.key[::-1], + return { 'key': self.attr.key, 'owner': self.owner, 'data': self.data } def __setstate__(self, d): - self.attr = getattr(d['owner'].__class__, d['key'][::-1]) + self.attr = getattr(d['owner'].__class__, d['key']) self._owner = weakref.ref(d['owner']) self._data = weakref.ref(d['data']) diff --git a/test/orm/attributes.py b/test/orm/attributes.py index 7aeddeff8f..70e786bc1d 100644 --- a/test/orm/attributes.py +++ b/test/orm/attributes.py @@ -51,14 +51,47 @@ class AttributesTest(PersistTest): # shouldnt be pickling callables at the class level def somecallable(*args): return None - manager.register_attribute(MyTest, 'mt2', uselist = True, trackparent=True, callable_=somecallable) - x = MyTest() - x.mt2.append(MyTest2()) + attr_name = 'mt2' + manager.register_attribute(MyTest, attr_name, uselist = True, trackparent=True, callable_=somecallable) + + o = MyTest() + o.mt2.append(MyTest2()) + o.user_id=7 + pk_o = pickle.dumps(o) + + o2 = pickle.loads(pk_o) + + # so... pickle is creating a new 'mt2' string after a roundtrip here, + # so we'll brute-force set it to be id-equal to the original string + o_mt2_str = [ k for k in o.__dict__ if k == 'mt2'][0] + o2_mt2_str = [ k for k in o2.__dict__ if k == 'mt2'][0] + self.assert_(o_mt2_str == o2_mt2_str) + self.assert_(o_mt2_str is not o2_mt2_str) + # take current mt2 from o2 + former = o2.__dict__['mt2'] + del o2.__dict__['mt2'] + for k in o.__dict__: + if k == 'mt2': + # set it back with the id-equal key from o, + o2.__dict__[k] = former + + pk_o2 = pickle.dumps(o2) + + self.assert_(pk_o == pk_o2) + + # the above is kind of distrurbing, so let's do it again a little + # differently. the string-id in serialization thing is just an + # artifact of pickling that comes up in the first round-trip. + # a -> b differs in pickle memoization of 'mt2', but b -> c will + # serialize identically. + + o3 = pickle.loads(pk_o2) + pk_o3 = pickle.dumps(o3) + o4 = pickle.loads(pk_o3) + pk_o4 = pickle.dumps(o4) + + self.assert_(pk_o3 == pk_o4) - x.user_id=7 - s = pickle.dumps(x) - x2 = pickle.loads(s) - assert s == pickle.dumps(x2) def testlist(self): class User(object):pass -- 2.47.3