[Zope-dev] Help: __getstate__ overriding

Tim Peters tim at zope.com
Fri May 28 14:51:39 EDT 2004


[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__()).

This appears to be one of those "severely underdocumented" minefields.  The
best older thread I found is here:

    http://mail.zope.org/pipermail/zodb-dev/2002-March/002442.html

but it doesn't actually spell out something "that works" in the way you
want.

One possibility is to use any of these __setstate__ implementations
temporarily, in a one-shot database conversion script:  load every object of
your subclass's type, and for each one "obj", after loading it do

    obj._p_changed = True
    get_transaction().commit()

Note again that setting _p_changed *inside* __setstate__ won't do any good.

Note too that Jim Fulton has a recent proposal for Zope3 in this area:

    http://tinyurl.com/ypkhk

[Zope URLs are generally so long my mailer refuses to keep them on one line]




More information about the Zope-Dev mailing list