[Zodb-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()