[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