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

Jeremy Hylton jeremy@zope.com
Fri, 24 Jan 2003 14:09:53 -0500


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

Modified Files:
      Tag: new-pickle-branch
	patch.py 
Log Message:
Add registry for external conversion wrappers.
Make sure pickler is opened in binary mode.


=== Zope3/src/zodb/code/patch.py 1.4.2.2 => 1.4.2.3 ===
--- Zope3/src/zodb/code/patch.py:1.4.2.2	Fri Jan 24 13:21:28 2003
+++ Zope3/src/zodb/code/patch.py	Fri Jan 24 14:09:50 2003
@@ -151,6 +151,11 @@
 
         return PersistentClassMetaClass(self._obj.__name__, newbases, dict)
 
+def registerWrapper(atype, wrapper, unwrap_thunk):
+    """Register a patch wrapper for an external object type."""
+    Pickler.dispatch[atype] = Pickler.save_external
+    Pickler.external[atype] = wrapper, unwrap_thunk
+
 marker = object()
 
 class Pickler(pickle.Pickler):
@@ -159,7 +164,14 @@
     dispatch.update(pickle.Pickler.dispatch)
 
     def __init__(self, file, module, memo, replacements):
-        pickle.Pickler.__init__(self, file)#, bin=True)
+        # The pickler must be created in binary mode, because
+        # it pickles instances using the OBJ code.  The text-mode
+        # pickler uses a different strategy that explicitly
+        # stores the name of the instance's class which defeats
+        # the desire to replace references to classes with
+        # persistent classes.
+        pickle.Pickler.__init__(self, file, bin=True)
+        
         self._pmemo = memo
         self._wrapped = {} # set of objects already wrapped
         self._module = module
@@ -201,7 +213,7 @@
                              (atype.__bases__, atype.__dict__))
             memo_len = len(self.memo)
             self.write(self.put(memo_len))
-            self.memo[d] = memo_len, atype
+            self.memo[d] = memo_len, None
 
     dispatch[TypeType] = save_type
     dispatch[ClassType] = save_type
@@ -212,9 +224,21 @@
                          (func.func_defaults, func.func_dict))
         memo_len = len(self.memo)
         self.write(self.put(memo_len))
-        self.memo[d] = memo_len, func
+        self.memo[d] = memo_len, None
 
     dispatch[FunctionType] = save_function
+
+    external = {}
+
+    def save_external(self, obj):
+        # Save an external type registered through registerWrapper
+        objtype = type(obj)
+        wrapper, unwrap_thunk = self.external[objtype]
+        d = id(obj)
+        self.save_reduce(self.wrap(wrapper, obj), unwrap_thunk(obj))
+        memo_len = len(self.memo)
+        self.write(self.put(memo_len))
+        self.memo[d] = memo_len, None
 
     # New-style classes don't have real dicts.  They have dictproxies.
     # There's no official way to spell the dictproxy type, so we have