[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