[Zodb-checkins] CVS: ZODB3/ZODB - serialize.py:1.2.10.4

Jim Fulton jim at zope.com
Mon Jan 26 15:37:13 EST 2004


Update of /cvs-repository/ZODB3/ZODB
In directory cvs.zope.org:/tmp/cvs-serv23204/src/ZODB

Modified Files:
      Tag: zope3-zodb3-devel-branch
	serialize.py 
Log Message:
Updated to support persistent weak references.

Reimplemented persistent_id in Python to support persistent
references.


=== ZODB3/ZODB/serialize.py 1.2.10.3 => 1.2.10.4 ===
--- ZODB3/ZODB/serialize.py:1.2.10.3	Fri Jan 16 10:43:27 2004
+++ ZODB3/ZODB/serialize.py	Mon Jan 26 15:37:12 2004
@@ -58,7 +58,12 @@
 import cPickle
 import cStringIO
 
-from ZODB.coptimizations import new_persistent_id
+from persistent import Persistent
+from persistence.wref import WeakRefMarker, WeakRef
+from ZODB.POSException import InvalidObjectReference
+
+# Might to update or redo to reflect weakrefs
+# from ZODB.coptimizations import new_persistent_id
 
 
 def myhasattr(obj, name, _marker=object()):
@@ -101,11 +106,84 @@
         self._file = cStringIO.StringIO()
         self._p = cPickle.Pickler(self._file, 1)
         self._stack = []
-        self._p.persistent_id = new_persistent_id(jar, self._stack)
+        self._p.persistent_id = self.persistent_id
         if jar is not None:
             assert myhasattr(jar, "new_oid")
         self._jar = jar
 
+
+    def persistent_id(self, obj):
+
+        # Most objects are not persistent. The following cheap test
+        # identifies most of them.  For these, we return None,
+        # signalling that the object should be pickled normally.
+        if not isinstance(obj, (Persistent, type, WeakRef)):
+            # Not persistent, pickle normally
+            return None
+
+        # Any persistent object mosy have an oid:
+        try:
+            oid = obj._p_oid
+        except AttributeError:
+            # Not persistent, pickle normally
+            return None
+
+        if not (oid is None or isinstance(oid, str)):
+            # Deserves a closer look:
+
+            # Make sure it's not a descr
+            if hasattr(oid, '__get__'):
+                # The oid is a decriptor.  That means obj is a non-persistent
+                # class whose instances are persistent, so ...
+                # Not persistent, pickle normally
+                return None
+
+            if oid is WeakRefMarker:
+                # we have a weakref, see weakref.py
+
+                oid = obj.oid
+                if oid is None:
+                    obj = obj() # get the referenced object
+                    oid = obj._p_oid
+                    if oid is None:
+                        # Here we are causing the object to be saved in
+                        # the database. One could argue that we shouldn't
+                        # do this, because a wekref should not cause an object
+                        # to be added.  We'll be optimistic, though, and
+                        # assume that the object will be added eventually.
+                        
+                        oid = self._jar.new_oid()
+                        obj._p_jar = self._jar
+                        obj._p_oid = oid
+                        self._stack.append(obj)
+                return [oid]
+
+
+        # Since we have an oid, we have either a persistent instance
+        # (an instance of Persistent), or a persistent class.
+
+        # NOTE! Persistent classes don't (and can't) subclass persistent.
+
+        if oid is None:
+            oid = obj._p_oid = self._jar.new_oid()
+            obj._p_jar = self._jar
+            self._stack.append(obj)
+        elif obj._p_jar is not self._jar:
+            raise InvalidObjectReference(
+                "Attempt to store an object from a foreign "
+                "database connection"
+                )
+
+        klass = type(obj)
+        if hasattr(klass, '__getnewargs__'):
+            # We don't want to save newargs in object refs.
+            # It's possible that __getnewargs__ is degenerate and
+            # returns (), but we don't want to have to deghostify
+            # the object to find out.
+            return oid 
+
+        return oid, klass
+
     def serialize(self, obj):
         return self._dump(getClassMetadata(obj), obj.__getstate__())
 
@@ -266,6 +344,14 @@
             obj._p_changed = None
 
             self._cache[oid] = obj
+            return obj
+
+        elif isinstance(oid, list):
+            # see weakref.py
+            [oid] = oid
+            obj = WeakRef.__new__(WeakRef)
+            obj.oid = oid
+            obj.dm = self._conn
             return obj
 
         obj = self._cache.get(oid, None)




More information about the Zodb-checkins mailing list