Reputation: 182
i am upgrading a Plone Site from 3.3.5 to 4.3.2 and have to deal with leftovers from packages which unfortunately did not uninstall cleanly and are not available for Plone 4.x.
The following links provide useful information in removing stale components from Plone:
Although i was able to remove about 70% of the unwanted stuff with the fixinterfaces.py script and run the migration from 3.3.5 to 4.0 successfully, there is still one persistent instance of a class dangeling around:
<persistent broken p4a.subtyper.submenu.SubtypesSubMenuItem instance None>
The error occures when Plone tries to render the contentmenu entries of the root document of the site. zope.app.publisher.BrowserMenu tries to generate the content menu entries when it comes to the dangling broken object which OFS.Unistalled.py cannot get its 'available' attribute from and raises an exception. This looks like new behaviour compared to 3.3.5 where it does not raise.
With the pdb debugger at the code point causing the exception i was able to find all this out. The very helpful documentation for using pdb within Plone was:
When zope.app.publisher.BrowserMenu tries to render the contentmenu, it calls getadapter on the document object with the request and another parameter. This returns a list with the dangling broken object in it with no available attribute beacuse it is broken:
def getMenuItems(self, object, request):
"""Return menu item entries in a TAL-friendly form."""
result = []
for name, item in getAdapters((object, request),
self.getMenuItemType()):
if item.available():
result.append(item)
When i list all the adapters of my site, there is no entry of the object in it:
site = app.Plone
sm = site.getSiteManager()
adapters = sm.utilities._adapters
for x in adapters[0].keys():
print x
<InterfaceClass zope.ramcache.interfaces.ram.IRAMCache>
<InterfaceClass plone.app.i18n.locales.interfaces.IContentLanguages>
<InterfaceClass Products.PortalTransforms.interfaces.IPortalTransformsTool>
<InterfaceClass Products.CMFPlone.interfaces.siteroot.IPloneSiteRoot>
<InterfaceClass Products.CMFCore.interfaces._tools.ISyndicationTool>
<InterfaceClass plone.portlets.interfaces.IPortletManager>
<InterfaceClass Products.CMFCore.interfaces._tools.IUndoTool>
<InterfaceClass plone.browserlayer.interfaces.ILocalBrowserLayerType>
<InterfaceClass plone.contentrules.engine.interfaces.IRuleStorage>
<InterfaceClass Products.CMFPlone.interfaces.migration.IMigrationTool>
<InterfaceClass plone.app.i18n.locales.interfaces.IMetadataLanguages>
<InterfaceClass Products.CMFUid.interfaces.IUniqueIdGenerator>
<InterfaceClass Products.TinyMCE.interfaces.utility.ITinyMCE>
<InterfaceClass Products.CMFUid.interfaces.IUniqueIdAnnotationManagement>
<InterfaceClass Products.CMFActionIcons.interfaces._tools.IActionIconsTool>
<InterfaceClass five.customerize.interfaces.IViewTemplateContainer>
<InterfaceClass plone.portlets.interfaces.IPortletType>
<InterfaceClass plone.app.redirector.interfaces.IRedirectionStorage>
<InterfaceClass Products.CMFPlone.interfaces.interface.IInterfaceTool>
<InterfaceClass Products.CMFDiffTool.interfaces.IDiffTool>
<InterfaceClass Products.MimetypesRegistry.interfaces.IMimetypesRegistryTool>
<InterfaceClass Products.CMFCore.interfaces._content.ISiteRoot>
<InterfaceClass Products.MailHost.interfaces.IMailHost>
<InterfaceClass plone.app.viewletmanager.interfaces.IViewletSettingsStorage>
<InterfaceClass Products.ATContentTypes.interfaces.interfaces.IATCTTool>
<InterfaceClass Products.CMFCore.interfaces._tools.IPropertiesTool>
<InterfaceClass plone.app.i18n.locales.interfaces.ICountries>
<InterfaceClass plone.keyring.interfaces.IKeyManager>
<InterfaceClass Products.CMFCore.interfaces._tools.IDiscussionTool>
<InterfaceClass Products.CMFCore.interfaces._tools.IMetadataTool>
Any clues where this resides so that i can delete it?
Edit: I found where it lives. But i don't know how to remove it.
>>> for x in sm._adapter_registrations.keys():
... print sm._adapter_registrations[x]
...
(<TTWViewTemplate at zope.interface.interface-plone.logo>, u'')
(<plone.portlets.manager.PortletManager object at 0xd15aeec>, u'')
(<plone.portlets.manager.PortletManager object at 0xd15af2c>, u'')
(<plone.portlets.manager.PortletManager object at 0xd15ae2c>, u'')
(<plone.portlets.manager.PortletManager object at 0xd15af6c>, u'')
(<TTWViewTemplate at zope.interface.interface-plone.nextprevious>, u'')
(<TTWViewTemplate at zope.interface.interface-plone.global_sections>, u'')
(<plone.portlets.manager.PortletManager object at 0xd15aeac>, u'')
(<plone.portlets.manager.PortletManager object at 0xd15ae6c>, u'')
(<TTWViewTemplate at zope.interface.interface-plone.searchbox>, u'')
(<class 'p4a.subtyper.submenu.SubtypesSubMenuItem'>, u'')
>>>
Edit: It looks like the offending entry comes from the content type registration, i.e. sitemanager.adapters.lookupAll returns which is stored in a variable called factory. So when removing p4a leftover stuff be sure to look in your content type registry also!
Upvotes: 1
Views: 492
Reputation: 21
adapter_regs = sm._adapter_registrations
for x in adapter_regs.keys():
if str(x).find("p4a") != -1 or str(adapter_regs[x]).find("p4a") != -1:
# log or print smth here
del adapter_regs[x]
sm._adapter_registrations = adapter_regs
from transaction import commit
commit()
PS. There is another place, not mentioned in the otherwise very useful fourdigits-blog, where your broken class can reside: sm.adapters._adapters. Loop over that one as well, just in case.
Upvotes: 0
Reputation: 6839
Have you tried to make the the p4a.subtyper available in your upgraded site? If this works, it should be possible to do a sm.unregisterAdapter(...)
btw. I just saw that the p4a.subtyper
has a clean uninstall profile.
Check: https://github.com/collective/p4a.subtyper/blob/master/p4a/subtyper/sitesetup.py#L58
It does exactly what you want "snipped":
sm = portal.getSiteManager()
if sm.adapters.lookup((Interface, Interface), IContentMenuItem, u'subtypes') is not None:
sm.unregisterAdapter(None, (Interface, Interface), IContentMenuItem, u'subtypes')
Upvotes: 0