Commit 8dbdceec authored by Jim Fulton's avatar Jim Fulton

Fixed the last fix and fixed the test that failed to show the need for

the fix fix.
parent 0cd1074f
...@@ -29,7 +29,7 @@ ResolvedSerial = 'rs' ...@@ -29,7 +29,7 @@ ResolvedSerial = 'rs'
class BadClassName(Exception): class BadClassName(Exception):
pass pass
class BadClass: class BadClass(object):
def __init__(self, *args): def __init__(self, *args):
self.args = args self.args = args
...@@ -123,13 +123,13 @@ class PersistentReference(object): ...@@ -123,13 +123,13 @@ class PersistentReference(object):
self.data = data self.data = data
# see serialize.py, ObjectReader._persistent_load # see serialize.py, ObjectReader._persistent_load
if isinstance(data, tuple): if isinstance(data, tuple):
self.oid, self.klass = data self.oid, klass = data
if isinstance(self.klass, BadClass): if isinstance(klass, BadClass):
# We can't use the BadClass directly because, if # We can't use the BadClass directly because, if
# resolution succeeds, there's no good way to pickle # resolution succeeds, there's no good way to pickle
# it. Fortunately, a class reference in a persistent # it. Fortunately, a class reference in a persistent
# reference is allowed to be a module+name tuple. # reference is allowed to be a module+name tuple.
self.klass = self.klass.args self.data = self.oid, klass.args
elif isinstance(data, str): elif isinstance(data, str):
self.oid = data self.oid = data
else: # a list else: # a list
...@@ -140,7 +140,7 @@ class PersistentReference(object): ...@@ -140,7 +140,7 @@ class PersistentReference(object):
# or persistent weakref: (oid, database_name) # or persistent weakref: (oid, database_name)
# else it is a weakref: reference_type # else it is a weakref: reference_type
if reference_type == 'm': if reference_type == 'm':
self.database_name, self.oid, self.klass = data[1] self.database_name, self.oid, _ = data[1]
elif reference_type == 'n': elif reference_type == 'n':
self.database_name, self.oid = data[1] self.database_name, self.oid = data[1]
elif reference_type == 'w': elif reference_type == 'w':
...@@ -173,6 +173,16 @@ class PersistentReference(object): ...@@ -173,6 +173,16 @@ class PersistentReference(object):
def __getstate__(self): def __getstate__(self):
raise PicklingError("Can't pickle PersistentReference") raise PicklingError("Can't pickle PersistentReference")
@property
def klass(self):
# for tests
data = self.data
if isinstance(data, tuple):
return data[1]
elif isinstance(data, list) and data[0] == 'm':
return data[1][2]
class PersistentReferenceFactory: class PersistentReferenceFactory:
data = None data = None
......
...@@ -158,6 +158,9 @@ def resolve_even_when_referenced_classes_are_absent(): ...@@ -158,6 +158,9 @@ def resolve_even_when_referenced_classes_are_absent():
We often want to be able to resolve even when there are pesistent We often want to be able to resolve even when there are pesistent
references to classes that can't be imported. references to classes that can't be imported.
>>> class P(persistent.Persistent):
... pass
>>> db = ZODB.DB('t.fs') # FileStorage! >>> db = ZODB.DB('t.fs') # FileStorage!
>>> storage = db.storage >>> storage = db.storage
>>> conn = db.open() >>> conn = db.open()
...@@ -166,20 +169,19 @@ references to classes that can't be imported. ...@@ -166,20 +169,19 @@ references to classes that can't be imported.
>>> oid = conn.root.x._p_oid >>> oid = conn.root.x._p_oid
>>> serial = conn.root.x._p_serial >>> serial = conn.root.x._p_serial
>>> class P(persistent.Persistent): >>> conn.root.x.a = P()
... pass
>>> conn.root.x.a = a = P()
>>> transaction.commit() >>> transaction.commit()
>>> aid = conn.root.x.a._p_oid
>>> serial1 = conn.root.x._p_serial >>> serial1 = conn.root.x._p_serial
>>> del conn.root.x.a >>> del conn.root.x.a
>>> conn.root.x.b = b = P() >>> conn.root.x.b = P()
>>> transaction.commit() >>> transaction.commit()
>>> serial2 = conn.root.x._p_serial >>> serial2 = conn.root.x._p_serial
Bwahaha: Bwahaha:
>>> P_aside = P
>>> del P >>> del P
Now, even though we can't import P, we can still resolve the conflict: Now, even though we can't import P, we can still resolve the conflict:
...@@ -187,10 +189,18 @@ Now, even though we can't import P, we can still resolve the conflict: ...@@ -187,10 +189,18 @@ Now, even though we can't import P, we can still resolve the conflict:
>>> p = storage.tryToResolveConflict( >>> p = storage.tryToResolveConflict(
... oid, serial1, serial, storage.loadSerial(oid, serial2)) ... oid, serial1, serial, storage.loadSerial(oid, serial2))
>>> p = conn._reader.getState(p) And load the pickle:
>>> sorted(p), p['a'] is a, p['b'] is b
>>> conn2 = db.open()
>>> P = P_aside
>>> p = conn2._reader.getState(p)
>>> sorted(p), p['a'] is conn2.get(aid), p['b'] is conn2.root.x.b
(['a', 'b'], True, True) (['a', 'b'], True, True)
>>> isinstance(p['a'], P) and isinstance(p['b'], P)
True
Oooooof course, this won't work if the subobjects aren't persistent: Oooooof course, this won't work if the subobjects aren't persistent:
>>> class NP: >>> class NP:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment