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

Jeremy Hylton jeremy@zope.com
Tue, 21 Jan 2003 18:10:35 -0500


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

Modified Files:
      Tag: new-pickle-branch
	patch.py 
Log Message:
Fix persistent_id() used for patching.

If a persistent object has been newly created it's _p_oid will be
None.  So the getattr() default value of None isn't a good test.  Use
an explicit object() for the default instead and make up an
unforgeable oid for the object.


=== Zope3/src/zodb/code/patch.py 1.4 => 1.4.2.1 ===
--- Zope3/src/zodb/code/patch.py:1.4	Mon Dec 30 19:15:58 2002
+++ Zope3/src/zodb/code/patch.py	Tue Jan 21 18:10:33 2003
@@ -143,6 +143,8 @@
 
         return PersistentClassMetaClass(self._obj.__name__, newbases, dict)
 
+marker = object()
+
 class Pickler(pickle.Pickler):
 
     dispatch = {}
@@ -155,13 +157,13 @@
         self._repl = replacements
         self._builtins = module.__builtins__
 
-    def wrap(self, wrapperclass, object):
-        return wrapperclass(object, self._module, self._repl.get(id(object)))
+    def wrap(self, wrapperclass, obj):
+        return wrapperclass(obj, self._module, self._repl.get(id(obj)))
 
-    def persistent_id(self, object, force=False):
-        if isinstance(object, Wrapper) or object is self._builtins or force:
-            oid = id(object)
-            self._pmemo[oid] = object
+    def persistent_id(self, obj, force=False):
+        if isinstance(obj, Wrapper) or obj is self._builtins or force:
+            oid = id(obj)
+            self._pmemo[oid] = obj
             return oid
         else:
             # If the object is a real persistent object, patch it by
@@ -172,10 +174,13 @@
             # doesn't use sys.modules.
             
             # XXX Is this safe in all cases?
-            oid = getattr(object, "_p_oid", None)
-            if oid is None:
+            oid = getattr(obj, "_p_oid", marker)
+            if oid is marker:
                 return None
-            self._pmemo[oid] = object
+            elif oid is None:
+                # It's a persistent object, but it's newly created.
+                oid = object()
+            self._pmemo[oid] = obj
             return oid
 
     def save_type(self, atype):
@@ -199,7 +204,7 @@
     # to get it by using type() on an example.
     dispatch[type(Wrapper.__dict__)] = pickle.Pickler.save_dict
 
-    def save(self, object, ignore=None):
+    def save(self, obj, ignore=None):
         # Override the save() implementation from pickle.py, because
         # we don't ever want to invoke __reduce__() on builtin types
         # that aren't picklable.  Instead, we'd like to pickle all of
@@ -209,18 +214,18 @@
 
         # The ignored parameter is for compatible with Python 2.2,
         # which has the old inst_persistent_id feature.
-        pid = self.persistent_id(object)
+        pid = self.persistent_id(obj)
         if pid is not None:
             self.save_pers(pid)
             return
 
-        d = id(object)
-        t = type(object)
-        if (t is TupleType) and (len(object) == 0):
+        d = id(obj)
+        t = type(obj)
+        if (t is TupleType) and (len(obj) == 0):
             if self.bin:
-                self.save_empty_tuple(object)
+                self.save_empty_tuple(obj)
             else:
-                self.save_tuple(object)
+                self.save_tuple(obj)
             return
 
         if d in self.memo:
@@ -235,19 +240,19 @@
             except TypeError: # t is not a class
                 issc = 0
             if issc:
-                self.save_global(object)
+                self.save_global(obj)
                 return
 
             try:
                 reduce = dispatch_table[t]
             except KeyError:
-                self.save_pers(self.persistent_id(object, True))
+                self.save_pers(self.persistent_id(obj, True))
                 return
             else:
-                tup = reduce(object)
+                tup = reduce(obj)
 
             if type(tup) is StringType:
-                self.save_global(object, tup)
+                self.save_global(obj, tup)
                 return
             if type(tup) is not TupleType:
                 raise pickle.PicklingError("Value returned by %s must be a "
@@ -274,10 +279,10 @@
             self.save_reduce(callable, arg_tup, state)
             memo_len = len(self.memo)
             self.write(self.put(memo_len))
-            self.memo[d] = (memo_len, object)
+            self.memo[d] = (memo_len, obj)
             return
 
-        f(self, object)
+        f(self, obj)
 
 class Unpickler(pickle.Unpickler):