[Zope-dev] Help: __getstate__ overriding

Tim Peters tim at zope.com
Fri May 28 12:34:03 EDT 2004


[Syver Enstad]
> I have a Persistent derived class where I want to upgrade from using a
> PersistentList to a BTrees.IOBTree.IOBTree.
>
> _articleList is the old Persistent list
> _oidsToArticles is the new IOBTree.
>
>     def __setstate__(self, state):
>         articleList = state.get('_articleList')
>         if articleList:
>             oidsToArticles = self.makeBTree()
>             for each in articleList:
>                 oidsToArticles[each.oid()] = each
>             del state['_articleList']
>             state['_oidsToArticles'] = oidsToArticles
>         Persistent.__setstate__(self, state)
>
> This seems to work fine, and I am adding more objects to
> _oidsToArticles. The problem is that when I commit the transaction,
> nothing is saved.

Quick guess (untested, untried, just from eyeballing this snippet quickly):
nothing is marking self itself as being changed.  The only things getting
changed are the throw-away in-memory 'state' dict, the throw-away in-memory
self.__dict__, and a throw-away in-memory BTree.  The primary purpose of
p.__setstate__ is to activate a ghost, after which point p is in the
up-to-date state (i.e., not changed -- calling Persistent.__setstate__(self,
...) isn't going to mark self as changed, and nothing in the code above
modifies self itself).  If self doesn't look changed, its state in the DB
won't change during commit(), and the DB will still reference your old
PersistentList.

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.




More information about the Zope-Dev mailing list