Chris Withers wrote:
Hi All,

I'm trying to fix this bug:

And I've narrowed it down to the following lines in

        if serial != self._p_serial:
            state=self._p_jar.oldstate(self, serial)
            print '1:',state
            # Scrub the object before restoring the old state
            base = aq_base(self)

Marks the object not changed, to allow ghostifying.


Ghostifies the object.


Updates the object's dict directly. This really shouldn't be called on a
ghost object, I believe it's illegal but not checked. I'm not sure what
happens anyway.



If I comment out the base._p_changed=0 and base._p_deactivate() then history copy starts working again.

My theory now is that the _p_deactivate() causes the persistence mechanisms to miss the changes made by base.__setstate__(state) and so when base._p_changed=1, it takes what it thinks is a ghost and stomps over it with the old state.

Does this sound plausible? If so, what's the correct fix here? Why was the scrubbing process necessary?

The way I'd do it is:

  base._p_activate()       # make sure we're not a ghost
  base.__setstate__(state) # change the state
  base._p_changed = True   # marke object as dirty

The "scrubbing" is not necessary, it's done by the __setstate__ C
implementation of Persistent.

Also, just as importantly, how would someone suggest writing a test that excercises the above? The only thing I can thing of is creating a scratch filestorage somewhere and committing some transactions to it, but that seems a little heavyweight...

You don't need any transactions to at least test this sequence, only the
Persistent base class and a dummy connection can be involved.

To really test the history yes of course you'll need a full database. Many
tests do that.


Florent Guillaume, Nuxeo (Paris, France)   Director of R&D
+33 1 40 33 71 59   [EMAIL PROTECTED]

For more information about ZODB, see the ZODB Wiki:

ZODB-Dev mailing list  -

Reply via email to