I tried to upgrade my objects using __setstate__, but nothing happened. As far as I can tell, __setstate__ is not even called. Is there some other magic that needs to be done except creating the __setstate__ method?
From: "Lennart Regebro" <lennart@regebro.nu>
I tried to upgrade my objects using __setstate__, but nothing happened. As far as I can tell, __setstate__ is not even called. Is there some other magic that needs to be done except creating the __setstate__ method?
OK, I found the bug, stupid me. It was just that Persistant.__setstate__ was overriding my __setstate__ from a later subclass... :-) But still, I'm not able to upgrade things properly. __setstate__ is executed now, and it currently looks like this: def __setstate__(self, state): Persistent.__setstate__(self, state) if hasattr(self, '_object_workflow_version'): old_ver = self._object_workflow_version else: old_ver = '0.0' print "DEBUG, old version", old_ver if old_ver != '1.0': self._object_workflow_version = '1.0' #self.upgradeWorkflow() print self._object_workflow_version This always have the same effect. When restarting the server, no objects have the _object_workflow_version attribute. So I set it. After a server restart, they are all gone again. I can change _object_workflow_version without trouble if I do it somewhere else, but any changes to _object_workflow_version or any otehr attributes I do in __setstate__ doesn't persist after a restart of Zope. I don't get it.
Lennart Regebro writes:
.... I can change _object_workflow_version without trouble if I do it somewhere else, but any changes to _object_workflow_version or any otehr attributes I do in __setstate__ doesn't persist after a restart of Zope. Interesting...
As an optimization, Zope writes objects back to the storage only when it knows they have changed. "__setstate__" is called internally by the loading process. It is quite reasonable that Zope assumes that a freshly loaded object does not yet have changes. Thus, if there are no changes later, the object will not be written back, For the normal use, this should make no difference. When the objects are changed, they are written to the storage with the new attribute. When not, the new attributes are recreated the next time the object is loaded. This should make only a problem when you want to do more sophisticated actions (as you apparently do: --> upgradeWorkflow). Be aware, that what you can/should do inside "__setstate__" is very limited. Like in "__init__", "self" is not yet acquisition wrapped. It may, therefore, behave very different than is normal. You may also consider a class attribute for providing values for new attributes. Dieter
From: "Dieter Maurer" <dieter@handshake.de>
This should make only a problem when you want to do more sophisticated actions (as you apparently do: --> upgradeWorkflow).
Well, that part seemes to work much better than the non sofisticated part of it: self._object_workflow_version = '1.1' That never worked. The actual upgrade seemed to work sometimes. But only sometimes.
Be aware, that what you can/should do inside "__setstate__" is very limited.
But I don't do anything strange whatsoever. It's just that any changes I do to the objects attributes within __setstate__ is lost at restart. This of course completely defeats the upgrade purpose, although I don't do anything else then what for example Catalog does... Very strange.
You may also consider a class attribute for providing values for new attributes.
Sure, but in this case the internal structure of some data has changed. My current workaround is to simply make a python script that traverses the whole of the database an calls the upgradeWorkflow method, so it's not a big problem, but I feel it could be nice to use __setstate_ to upgrade these things, since that ment that our customers could just throw in a new version and restart the server.
participants (2)
-
Dieter Maurer -
Lennart Regebro