[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