Tim Peters wrote:
To be clear, I'm interested in how the _p_jar happens on a new object
that's just been created. Basically if you do:
# folder is a persistent object that has a _p_jar
# folder.foo = Foo() # where Foo inherits from Persistent
# here folder.foo doesn't have a _p_jar
# here folder.foo has a _p_jar, how come ?
I think I've missed something in my code trawling ;)
Indeed, this will have you crawling on your belly for the next week <wink>.
In effect, it all happens as a side effect of pickling, via the
persistent_id() method of (in ZODB 3.4) class ZODB.serialize.ObjectWriter.
The class docstring is telling the truth:
"""Serializes objects for storage in the database.
The ObjectWriter creates object pickles in the ZODB format. It
also detects new persistent objects reachable from the current
but exactly how that happens requires tracing thru Python's C pickle code
too. Stick a print or a breakpoint here (inside persistent_id()) and you
can watch it happening:
if oid is None:
oid = obj._p_oid = self._jar.new_oid()
obj._p_jar = self._jar
Note that ObjectWriter is passed a single object, but
Connection._store_objects iterates over the ObjectWriter instance. In your
example, "folder.foo = Foo()" marks `folder` as changed, and the new object
bound to .foo is discovered while pickling the new state for `folder`.
Iterating over an ObjectWriter(obj) instance can end up discovering an
arbitrarily large and complex graph of new objects reachable from obj, as it
tries to pickle each in turn. That's what the `self._stack` in the above is
keeping track of.
Thanks, that's very helpful. I knew about pickling and persistent_id, but
I'd never realized the one serializing for the storage had the side effect
of adding the _p_jar to new objects.
Florent Guillaume, Nuxeo (Paris, France) CTO, Director of R&D
+33 1 40 33 71 59 http://nuxeo.com [EMAIL PROTECTED]
For more information about ZODB, see the ZODB Wiki:
ZODB-Dev mailing list - ZODB-Dev@zope.org