[Zope3-checkins] CVS: Zope3/src/zodb/code - patch.py:1.4.2.2
Jeremy Hylton
jeremy@zope.com
Fri, 24 Jan 2003 13:22:00 -0500
Update of /cvs-repository/Zope3/src/zodb/code
In directory cvs.zope.org:/tmp/cvs-serv3194/zodb/code
Modified Files:
Tag: new-pickle-branch
patch.py
Log Message:
Make sure patch preserves object identity by using the pickle memo.
=== Zope3/src/zodb/code/patch.py 1.4.2.1 => 1.4.2.2 ===
--- Zope3/src/zodb/code/patch.py:1.4.2.1 Tue Jan 21 18:10:33 2003
+++ Zope3/src/zodb/code/patch.py Fri Jan 24 13:21:28 2003
@@ -41,6 +41,14 @@
possible to use the copy module, because it isn't possible to extend
the copy module in a safe way. The copy module depends on module globals.
+The pickler uses a Wrapper object that creates the appropriate new
+object or updates an old one when it is unpickled. The wrapper also
+causes parts of the wrapped object's state to be traversed by the
+pickler, for example the func_defaults of a function object. This
+traversal is necessary because references to convertable objects could
+be contained in the state and must be updated to refer to the new
+objects.
+
What semantics do we want for update-in-place in the presence of aliases?
Semantics based on per-namespace updates don't work in the presence of
@@ -151,8 +159,9 @@
dispatch.update(pickle.Pickler.dispatch)
def __init__(self, file, module, memo, replacements):
- pickle.Pickler.__init__(self, file, bin=True)
+ pickle.Pickler.__init__(self, file)#, bin=True)
self._pmemo = memo
+ self._wrapped = {} # set of objects already wrapped
self._module = module
self._repl = replacements
self._builtins = module.__builtins__
@@ -187,15 +196,23 @@
if atype.__module__ == "__builtin__":
self.save_global(atype)
else:
+ d = id(atype)
self.save_reduce(self.wrap(TypeWrapper, atype),
(atype.__bases__, atype.__dict__))
+ memo_len = len(self.memo)
+ self.write(self.put(memo_len))
+ self.memo[d] = memo_len, atype
dispatch[TypeType] = save_type
dispatch[ClassType] = save_type
def save_function(self, func):
+ d = id(func)
self.save_reduce(self.wrap(FunctionWrapper, func),
(func.func_defaults, func.func_dict))
+ memo_len = len(self.memo)
+ self.write(self.put(memo_len))
+ self.memo[d] = memo_len, func
dispatch[FunctionType] = save_function
@@ -291,7 +308,7 @@
self._pmemo = pmemo
def persistent_load(self, oid):
- return self._pmemo[oid]
+ return self._pmemo[int(oid)]
class NameFinder:
"""Find a canonical name for each update-able object."""
@@ -365,7 +382,7 @@
p = Pickler(f, module, memo, replacements)
moddict = module.__dict__
p.dump(moddict)
- f.reset()
+ f.seek(0)
u = Unpickler(f, memo)
newdict = u.load()
module.__dict__.clear()