[Zope3-checkins] CVS: Zope3/src/zodb/code - patch.py:1.10

Jim Fulton jim@zope.com
Sat, 3 May 2003 12:32:21 -0400


Update of /cvs-repository/Zope3/src/zodb/code
In directory cvs.zope.org:/tmp/cvs-serv23542/src/zodb/code

Modified Files:
	patch.py 
Log Message:
Fixed several bugs in the pickling code that were made apparent by the
new interface changes.



=== Zope3/src/zodb/code/patch.py 1.9 => 1.10 ===
--- Zope3/src/zodb/code/patch.py:1.9	Thu May  1 15:34:59 2003
+++ Zope3/src/zodb/code/patch.py	Sat May  3 12:32:21 2003
@@ -93,6 +93,7 @@
 
 from zodb.code.class_ import PersistentClassMetaClass, PersistentDescriptor
 from zodb.code.function import PersistentFunction
+from pickle import REDUCE, BUILD
 
 class Wrapper:
     """Implement pickling reduce protocol for update-able object.
@@ -134,10 +135,10 @@
     def unwrap(self, bases, dict):
         return PersistentClassMetaClass(self._obj.__name__, bases, dict)
 
-def registerWrapper(atype, wrapper, unwrap_thunk):
+def registerWrapper(atype, wrapper, unwrap_args, getstate=None):
     """Register a patch wrapper for an external object type."""
     Pickler.dispatch[atype] = Pickler.save_external
-    Pickler.external[atype] = wrapper, unwrap_thunk
+    Pickler.external[atype] = wrapper, unwrap_args, getstate
 
 marker = object()
 
@@ -222,10 +223,8 @@
     def save_type(self, atype):
         if atype.__module__ == self._module_name:
             self.save_reduce(self.wrap(TypeWrapper, atype),
-                             (atype.__bases__, atype.__dict__))
-            memo_len = len(self.memo)
-            self.write(self.put(memo_len))
-            self.memo[id(atype)] = memo_len, None
+                             (atype.__bases__, atype.__dict__),
+                             obj=atype)
         else:
             if isinstance(atype, PersistentClassMetaClass):
                 self.save_pers(self.persistent_id(atype, True))
@@ -240,10 +239,8 @@
         modname = whichmodule(func, func.__name__)
         if modname == self._module_name or modname == "__main__":
             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[id(func)] = memo_len, None
+                             (func.func_defaults, func.func_dict),
+                             obj=func)
         else:
             self.save_global(func)
 
@@ -256,11 +253,14 @@
         if obj.__module__ == self._module_name:
             # Save an external type registered through registerWrapper
             objtype = type(obj)
-            wrapper, unwrap_thunk = self.external[objtype]
-            self.save_reduce(self.wrap(wrapper, obj), unwrap_thunk(obj))
-            memo_len = len(self.memo)
-            self.write(self.put(memo_len))
-            self.memo[id(obj)] = memo_len, None
+            wrapper, unwrap_args, getstate = self.external[objtype]
+            if getstate is not None:
+                self.save_reduce(self.wrap(wrapper, obj), unwrap_args(obj),
+                                 getstate(obj),
+                                 obj=obj)
+            else:
+                self.save_reduce(self.wrap(wrapper, obj), unwrap_args(obj),
+                                 obj=obj)
         else:
             # In general, we don't know how to pickle this object,
             # so pickle it by reference to the original.
@@ -343,13 +343,28 @@
                                            "returned by %s must be a "
                                            "tuple" % reduce)
 
-            self.save_reduce(callable, arg_tup, state)
-            memo_len = len(self.memo)
-            self.write(self.put(memo_len))
-            self.memo[d] = (memo_len, obj)
+            self.save_reduce(callable, arg_tup, state, obj=obj)
             return
 
         f(self, obj)
+
+    def save_reduce(self, callable, arg_tup, state = None, obj = None):
+        write = self.write
+        save = self.save
+
+        save(callable)
+        save(arg_tup)
+        write(REDUCE)
+
+        if obj is not None:
+            memo_len = len(self.memo)
+            self.write(self.put(memo_len))
+            self.memo[id(obj)] = (memo_len, obj)
+            
+
+        if state is not None:
+            save(state)
+            write(BUILD)
 
 class Unpickler(pickle.Unpickler):