[Zope-dev] Help: __getstate__ overriding
Syver Enstad
syver at inout.no
Tue Jun 1 04:25:39 EDT 2004
"Tim Peters" <tim at zope.com> writes:
> [Syver Enstad, wants to switch an attribute of a Persitent subclass
> From PersistentList to an IOBTree]
>
> [Tim, guessing]
> > Quick guess (untested, untried, ...
> ...
> > Perhaps shuffling the code around would work, a la:
> >
> > Persistent.__setstate__(self, state)
> > articleList = state.get('_articleList')
> > if articleList is not None:
> > # make the BTree in local oidsToArticles as above, then
> > del self._articlelist
> > self._oidsToArticles = oidsToArticles
> >
> > The thinking there is that then you've truly modified self, after self has
> > been activated.
>
> Nope, sorry, not a chance. You have truly modified self then, but
> __setstate__ is called by magic as part of activation (unghostifying), and
> the activation machinery resets self._p_changed after it calls __setstate__.
> So same result as your code: the in-memory version of self has the BTree,
> but commit() doesn't change anything about self in the database (again
> because self._p_changed is false -- and will be no matter what you try to do
> in __setstate__()).
I was aware that __setstate__ doesn't allow me to commit my changes
after only loading the object into memory (__setstate__ is called). I
may have explained myself unclearly (not a native english
speaker/writer), the problem is that it won't save my changes when I
add more items to the _oidsToArticles BTree long after
__setstate__ time.
Example code:
# articleDb is an ArticleDb and has the __setstate__ method
articleDb = connection.root()['articledb']
for each in articleDb.articles() # loop through all article
print each
computer = Computer(1030)
articleDb.addArticle(computer)
connection.commit() # nothing is saved
Everything works smoothly until connection.commit(). The __setstate__
method correctly converts to using the BTree and the addArticle method
adds a new computer to ArticleDb.
If I instead create a new ArticleDb instance with the BTree instead of
using __setstate__ the new computer is saved as it should. In none of
the cases is articleDb._p_changed == True, but when the ArticleDb is
created "cleanly" instead of upgraded, commit works anyway.
Since this works if the object that holds _oidsToArticles is created
from scratch, it seems that ZODB isn't properly aware of the
_oidsToArticles attribute since it was created in __setstate__ instead
of in __init__. I would really like to know exactly what happens here
as the reason I am utilizing an object database is to be able to
refactor the database with a minimum of fuss, and I would expect
__setstate__ to allow me to make additional attributes in my
instances.
More information about the Zope-Dev
mailing list