I'm in the process of doing practice run migrations for several of our sites from Plone 4.1.6 to Plone 5.0.5. Many of these sites have been around since Plone 3 or maybe even earlier, which means they've acquired some vestigial components that might not have uninstalled completely. The problem does not always materialize until later when the package of antiquated modules is finally removed, causing them to break. That's what I think I am dealing with in this transition - lots of problems with the wicked package, and to my knowledge we never even used it. This post will maybe serve as a reference to others that might have this problem, but I hope also to pick the brains of people that have a good knowledge of low level zope component architecture.
Ordinarily I believe the preferred means of removing problem components is to reinstall the removed package and use its uninstall methods. That doesn't really work here - for one thing, wicked 1.1.9 doesn't even have an install method, just zcml, and I don't know what junk was put in the site from previous versions. So I'm attempting to solve this the hard way, by directly manipulating some zope component architecture elements.
First, let me give a quick overview of my setup. My production sites in 4.1.6 remain untouched, I just make a zexp of them and download them locally. I have two environments set up on my local machine: 4.1.6 and 5.0.5.
- Plone 4 - run custom update to clean up some things
- move filestorage and blobstorage dirs to Plone 5 environment
- Plone 5 - run custom update for more clean up, that relies on Plone 5 eggs
- Plone 5 - run Plone's normal migration
- Plone 5 - run custom update to apply all of our custom configurations and run AT->Dexterity conversion for our custom content (installing plone.app.contenttypes and migrating base content from AT->Dexterity is also baked into this)
The wicked package has caused me the most headaches, with the worst offender being trying to access just the root of the portal in the ZMI after starting up Plone 5. I originally got this error:
Traceback (innermost last): Module ZPublisher.Publish, line 249, in publish_module_standard Module ZPublisher.Publish, line 197, in publish Module zope.event, line 31, in notify Module zope.component.event, line 24, in dispatch Module zope.component._api, line 136, in subscribers Module zope.component.registry, line 320, in subscribers Module ZODB.Connection, line 860, in setstate Module ZODB.Connection, line 914, in _setstate Module ZODB.serialize, line 613, in setGhostState Module zope.component.persistentregistry, line 40, in __setstate__ Module zope.interface.adapter, line 91, in _createLookup Module zope.interface.adapter, line 439, in __init__ Module zope.interface.adapter, line 476, in init_extendors Module zope.interface.adapter, line 480, in add_extendor AttributeError: type object 'IFieldValueSetter' has no attribute '__iro__'
As I said, I think the origin of the problem was a bad cleanup of wicked from an earlier Plone version that left some orphans. Plone 5 no longer has the wicked package, and the leftover pieces cause the whole thing to crash. I could reproduce the same error message in Plone 4.1.6 by removing wicked from the buildout and starting up. To fix this I added the following to my custom update in Plone 4:
from zope.component import getSiteManager from wicked.fieldevent.interfaces import IFieldValueSetter adapter_registry = getSiteManager().adapters if IFieldValueSetter in adapter_registry._provided: del adapter_registry._provided[IFieldValueSetter] adapter_registry._v_lookup.remove_extendor(IFieldValueSetter) adapter_registry.changed(adapter_registry)
Ideally I would have run adapter_registry.unregister or even better, unregister it through a profile step with an XML file. i did not have success for either of these approaches, so I did my best to approximate what is happening in adapter_registry.unregister. If anyone has better knowledge here and can provide insight that would be very helpful.
I had one other issue when trying to reimport it back into a Plone 5 environment on a dev server: it told me it was unable to find WickedSettings when unpickling. I always find these errors frustrating because I don't know where in the portal it supposedly is. With a broken content object I can see it in the ZMI, but not with this. I eventually found it was an annotation and removed it.
bad_annotations = ('plone.app.controlpanel.wicked',) for bad_annotation in bad_annotations: if bad_annotation in IAnnotations(portal): del IAnnotations(portal)[bad_annotation]
I'm still in the process of testing that these practice runs do everything we expect of them, but for now things are looking good again. Apologies if you were a contributor to wicked