"Tim Peters" <tim@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.