Changing your packagename
One day you think lets clean up my code and rename all my products to something useful
Use Plone for several years and you will always find some product you made years ago and still frequently use today.
Now I recently had such a product, it was called Products.MyClientAdres. The name was reffering to some client but had nothing to do with it anymore. It was used in a completley different site but still used the same old svn location and package name.
My new package
When decided to change the name, I just blindly copied the product, renamed all the MyClientAdres things to my new package name 'fourdigits.organisations' and put everything in my buildout.
The result was very easy to predict, all my objects where broken after deleting the old product from the instance. They where all looking for Products.MyClientAdres.content.organisations but that was gone.
Convert the objects
To get my products back alive we need to change the __class__ of every object we made with the old product. First thing to keep in mind, keep both you old and new product installed in your instance because you cannot call a broken object!
Make a script to convert all the __class__ to you new class. Get the new class name from you package, here its called Adressenbank and Organisatie.
from fourdigits.organisations.content.Adressenbank import Adressenbank
from fourdigits.organisations.content.Organisatie import Organisatie
Convert the old adressenbank folder to the new Adressenbank contenttype from my new package.
adressenbank = getSite().unrestrictedTraverse('adressenbank')
tmp = Adressenbank(self.context)
adressenbank.__class__ = tmp.__class__
Convert the +3000 organisations still in the folder above.
ct = getToolByName(self, 'portal_catalog')
query = {}
query['object_provides'] = 'Products.MyClientAdres.content.interfaces.IOrganisatie'
results = ct(query)
tmp = Organisatie(self.context)
for result in results:
obj = result.getObject()
obj.__class__ = tmp.__class__
transaction.commit()
Rebuild the catalog by hand after your finished running the script.
Restart you instance and use quickingstaller to uninstalled your old product. Restart again and smile, all your object are working using your new product.
~




zodbupdate
http://pypi.python.org/pypi/zodbupdate
Also, I don't think changing the __class__ attr is relevant other than making the ZODB machinery recognize that the object has been changed same as if you'd done "obj._p_changed = True". __class__ attributes are references to the class object which is the same object regardless of where it's imported from. I believe the ZODB gets the correct path for the __class__ object using the __class__.__module__ attribute. I think this is what zodbupdate does, walks the ZODB object graph looking for ZODB pickles whose __class__ path doesn't match the path of the real object as determined by it's __class__.__module__ and then simply marks those objects as "obj.p_changed = True".