Trying zodbupdate

By Maarten Kling | On Jan 22, 2010
After writing my last blog post Ross Patterson pointed me to zodbupdate. Why not give it a try and see how it works?

For this test lets create a instance having a broken contenttype. I set up a new buildout and fourdigits.testzodbupdate product having an interface, a portlet and a contenttype. Installed it, created objects and a portlet. Removed the product from my buildout, started my instance again and the instance is saying it has some broken objects. So far so good.

Time to add zodbupdate. Adding the zodbupdate package to my buildout was slightly different from what the documentation was telling. I had to add the extra-paths = ${zope2:location}/lib/python to get it working.

My buildout

[buildout]
parts += zodbupdate

[zodbupdate]
recipe = zc.recipe.egg
eggs =     
${instance:eggs}
extra-paths =
${zope2:location}/lib/python

Running zodbupdate is quit easy

/opt/test/bin/zodbupdate -f /opt/test/var/filestorage/Data.fs -i

-f FILE, --file=FILE  load FileStorage
-i, --ignore-missing  update database even if classes are missing

Use the -i command so the update is fully done and you see all the errors.

My results:

Missing factory: fourdigits.testzodbupdate.content.interfaces.ITest
Missing factory: fourdigits.testzodbupdate.browser.testportlet.Assignment
Missing factory: fourdigits.testzodbupdate.contenttypes.content.testtype.testtypeclass

Time to create my new package, this one is called fourdigits.newtestproduct (very original). I created the same contenttype, portlet and interface again but all with slightly different names, to see how everything works.

Started my instance again to see if my new product is working fine, and look if im still having broken objects, again so far so good.

Time to setup rename rules for zodbupdate. First change the setup.py and add [zodbupdate] like below.

entry_points="""
# -*- entry_points -*-
[zodbupdate]
renames=fourdigits.newtestproduct:rename_dict

Note: this is done in my new product called fourdigits.newtestproduct. you need to set the same name after renames=

Now edit the __init__.py in /fourdigits.newtestproduct/fourdigits/newtestproduct/. This is the __init__ where your probably doing: def initialize(context): etc.

Put the rename_dict at the very top of the file:

rename_dict = {
'fourdigits.testzodbupdate.content.testtype testtypeclass': \
'fourdigits.newtestproduct.content.newtype newclass',
'fourdigits.testzodbupdate.content.interfaces ITest': \
'fourdigits.newtestproduct.content.interfaces INewtest',
'fourdigits.testzodbupdate.browser.testportlet Assignment': \
'fourdigits.newtestproduct.browser.newtestportlet Assignment',
 }

What you see here is, I have made 3 rules. First: give the old location and classname (use a space in between). Secondly: set the new location and again classname. This should be done for your contenttype, interface and portlet.

Important note here. We now have set up our rename rules. To let zodbupdate know they exist, you must run buildout again!

./bin/buildout -vN

Zodbupdate will create a list of all products found in your instance and reads the setup.py for [zodbupdate]

Now it is time to run zodbupdate again:

/opt/test/bin/zodbupdate -f /opt/test/var/filestorage/Data.fs -i

The result:

Loaded 3 rules from fourdigits.newtestproduct:renames
Committing changes.

And all is done. My first impression after starting the instance again, was that all my products where working fine again!