[ZODB-Dev] Re: Changes in _p_changed behaviour between Zope 2.7 and 2.9
Florent Guillaume wrote: base._p_activate() # make sure we're not a ghost base.__setstate__(state) # change the state base._p_changed = True # marke object as dirty OK, this is the code I went with. Well the C code is pretty clear, it does a PyDict_Clear before doing PyDict_Update on the __dict__. Dunno how it was at the time Evan made his comment. Well, there's tests now, so we should find out if this changes in the future... OFS.tests.testCopySupport was a good starting place, but it used DemoStorage which doesn't support history, so I had to swap in a real, live filestorage ;-) cheers, Chris -- Simplistix - Content Management, Zope Python Consulting - http://www.simplistix.co.uk ___ For more information about ZODB, see the ZODB Wiki: http://www.zope.org/Wikis/ZODB/ ZODB-Dev mailing list - ZODB-Dev@zope.org http://mail.zope.org/mailman/listinfo/zodb-dev
[ZODB-Dev] Re: Changes in _p_changed behaviour between Zope 2.7 and 2.9
Chris Withers wrote: Florent Guillaume wrote: base._p_changed=0 Marks the object not changed, to allow ghostifying. base._p_deactivate() Ghostifies the object. base.__setstate__(state) 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. Right, that's what I figured too, and I'm guessing ZODB now does the right thing, which breaks history copy because history copy has this bug ;-) base._p_activate() # make sure we're not a ghost Ah cool, never new that existed... 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. Okay, in that case we can loose everything funky before the __setstate__ call, right? How sure are you that __setstate__ will override everything? I see that Evan specifically added the code to do the scrubbing in revision 20478, sadly he didn't write tests or explain why it was necessary :-S Well the C code is pretty clear, it does a PyDict_Clear before doing PyDict_Update on the __dict__. Dunno how it was at the time Evan made his comment. For the rest, sorry, I don't have time to dig for examples. Florent You don't need any transactions to at least test this sequence, only the Persistent base class and a dummy connection can be involved. Hmmm, this smells like deep fu of which I am not capable ;-) Are there any examples of this? To really test the history yes of course you'll need a full database. Many tests do that. Oh, do you know of any examples I can look at? cheers, Chris -- Florent Guillaume, Nuxeo (Paris, France) Director of RD +33 1 40 33 71 59 http://nuxeo.com [EMAIL PROTECTED] ___ For more information about ZODB, see the ZODB Wiki: http://www.zope.org/Wikis/ZODB/ ZODB-Dev mailing list - ZODB-Dev@zope.org http://mail.zope.org/mailman/listinfo/zodb-dev
[ZODB-Dev] Re: Changes in _p_changed behaviour between Zope 2.7 and 2.9
Florent Guillaume wrote: base._p_changed=0 Marks the object not changed, to allow ghostifying. base._p_deactivate() Ghostifies the object. base.__setstate__(state) 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. Right, that's what I figured too, and I'm guessing ZODB now does the right thing, which breaks history copy because history copy has this bug ;-) base._p_activate() # make sure we're not a ghost Ah cool, never new that existed... 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. Okay, in that case we can loose everything funky before the __setstate__ call, right? How sure are you that __setstate__ will override everything? I see that Evan specifically added the code to do the scrubbing in revision 20478, sadly he didn't write tests or explain why it was necessary :-S You don't need any transactions to at least test this sequence, only the Persistent base class and a dummy connection can be involved. Hmmm, this smells like deep fu of which I am not capable ;-) Are there any examples of this? To really test the history yes of course you'll need a full database. Many tests do that. Oh, do you know of any examples I can look at? cheers, Chris -- Simplistix - Content Management, Zope Python Consulting - http://www.simplistix.co.uk ___ For more information about ZODB, see the ZODB Wiki: http://www.zope.org/Wikis/ZODB/ ZODB-Dev mailing list - ZODB-Dev@zope.org http://mail.zope.org/mailman/listinfo/zodb-dev
[ZODB-Dev] Re: Changes in _p_changed behaviour between Zope 2.7 and 2.9
Chris Withers wrote: Hi All, I'm trying to fix this bug: http://www.zope.org/Collectors/Zope/2062 And I've narrowed it down to the following lines in History.py: if serial != self._p_serial: self.manage_beforeHistoryCopy() state=self._p_jar.oldstate(self, serial) print '1:',state # Scrub the object before restoring the old state base = aq_base(self) base._p_changed=0 Marks the object not changed, to allow ghostifying. base._p_deactivate() Ghostifies the object. base.__setstate__(state) 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. base._p_changed=1 self.manage_afterHistoryCopy() 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 -- Florent Guillaume, Nuxeo (Paris, France) Director of RD +33 1 40 33 71 59 http://nuxeo.com [EMAIL PROTECTED] ___ For more information about ZODB, see the ZODB Wiki: http://www.zope.org/Wikis/ZODB/ ZODB-Dev mailing list - ZODB-Dev@zope.org http://mail.zope.org/mailman/listinfo/zodb-dev