Upgrade to 5.2 failing with 'IATCTTool' has no attribute '__iro__'

I'm trying to upgrade a site to 5.2 (still on Python 2.7). This site has basically no add-ons, except for Products.LoginLockout, so all the content types are the default ones. However, in its past history, it might have had some custom content types when it was on Plone 3 or earlier. It is currently running on Plone 4.x, and I've upgraded it to 5.0 and 5.1 by installing plone.app.contenttypes and running @@atct_migrator. There were 8 content items left that atct_migrator could not handle, so I deleted them by hand in the ZMI and reindexed everything. Now @@atct_migrator reports that there is nothing that needs to be migrated.

So, current state is that it works fine in 5.1.5.

When I try to load it in the ZMI in 5.2, I get

AttributeError: type object 'IATCTTool' has no attribute '__iro__'

so I can't even get to the upgrade page.

The full traceback is:

2019-08-07 13:50:13,238 ERROR   [waitress:363][waitress] Exception while serving /Plone/manage_workspace
Traceback (most recent call last):
  File "/usr/local/plone-5.2/buildout-cache/eggs/waitress-1.3.0-py2.7.egg/waitress/channel.py", line 356, in service
    task.service()
  File "/usr/local/plone-5.2/buildout-cache/eggs/waitress-1.3.0-py2.7.egg/waitress/task.py", line 176, in service
    self.execute()
  File "/usr/local/plone-5.2/buildout-cache/eggs/waitress-1.3.0-py2.7.egg/waitress/task.py", line 447, in execute
    app_iter = self.channel.server.application(env, start_response)
  File "/usr/local/plone-5.2/buildout-cache/eggs/Paste-3.0.8-py2.7.egg/paste/translogger.py", line 69, in __call__
    return self.application(environ, replacement_start_response)
  File "/usr/local/plone-5.2/buildout-cache/eggs/Zope-4.1.1-py2.7.egg/ZPublisher/httpexceptions.py", line 30, in __call__
    return self.application(environ, start_response)
  File "/usr/local/plone-5.2/buildout-cache/eggs/Zope-4.1.1-py2.7.egg/ZPublisher/WSGIPublisher.py", line 337, in publish_module
    response = _publish(request, new_mod_info)
  File "/usr/lib/python2.7/contextlib.py", line 35, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/plone-5.2/buildout-cache/eggs/Zope-4.1.1-py2.7.egg/ZPublisher/WSGIPublisher.py", line 207, in transaction_pubevents
    notify(pubevents.PubBeforeAbort(request, exc_info, retry))
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.event-4.4-py2.7.egg/zope/event/__init__.py", line 32, in notify
    subscriber(event)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.component-4.5-py2.7.egg/zope/component/event.py", line 27, in dispatch
    component_subscribers(event, None)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.component-4.5-py2.7.egg/zope/component/_api.py", line 124, in subscribers
    return sitemanager.subscribers(objects, interface)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.interface-4.6.0-py2.7-linux-x86_64.egg/zope/interface/registry.py", line 442, in subscribers
    return self.adapters.subscribers(objects, provided)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.interface-4.6.0-py2.7-linux-x86_64.egg/zope/interface/adapter.py", line 607, in subscribers
    subscription(*objects)
  File "/usr/local/plone-5.2/buildout-cache/eggs/plone.transformchain-2.0.1-py2.7.egg/plone/transformchain/zpublisher.py", line 121, in applyTransformOnFailure
    applyTransformOnSuccess(event)
  File "/usr/local/plone-5.2/buildout-cache/eggs/plone.transformchain-2.0.1-py2.7.egg/plone/transformchain/zpublisher.py", line 86, in applyTransformOnSuccess
    transformed = applyTransform(event.request)
  File "/usr/local/plone-5.2/buildout-cache/eggs/plone.transformchain-2.0.1-py2.7.egg/plone/transformchain/zpublisher.py", line 61, in applyTransform
    transformer = queryUtility(ITransformer)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.component-4.5-py2.7.egg/zope/component/_api.py", line 157, in queryUtility
    return getSiteManager(context).queryUtility(interface, name, default)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.interface-4.6.0-py2.7-linux-x86_64.egg/zope/interface/registry.py", line 281, in queryUtility
    return self.utilities.lookup((), provided, name, default)
  File "/usr/local/plone-5.2/buildout-cache/eggs/ZODB-5.5.1-py2.7.egg/ZODB/Connection.py", line 795, in setstate
    self._reader.setGhostState(obj, p)
  File "/usr/local/plone-5.2/buildout-cache/eggs/ZODB-5.5.1-py2.7.egg/ZODB/serialize.py", line 634, in setGhostState
    obj.__setstate__(state)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.component-4.5-py2.7.egg/zope/component/persistentregistry.py", line 39, in __setstate__
    self._createLookup()
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.interface-4.6.0-py2.7-linux-x86_64.egg/zope/interface/adapter.py", line 97, in _createLookup
    self._v_lookup = self.LookupClass(self)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.interface-4.6.0-py2.7-linux-x86_64.egg/zope/interface/adapter.py", line 458, in __init__
    self.init_extendors()
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.interface-4.6.0-py2.7-linux-x86_64.egg/zope/interface/adapter.py", line 495, in init_extendors
    self.add_extendor(p)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.interface-4.6.0-py2.7-linux-x86_64.egg/zope/interface/adapter.py", line 499, in add_extendor
    for i in provided.__iro__:
AttributeError: type object 'IATCTTool' has no attribute '__iro__'

I noticed that there is no Products.ATContentTypes in the bin/client1 script, so I added it to the buildout and tried again. Now it doesn't even start:

ImportError: No module named contentmigration.basemigrator.migrator

Tail of traceback:

...snip...
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.configuration-4.3.1-py2.7.egg/zope/configuration/fields.py", line 171, in fromUnicode
    value = self.context.resolve(name)
  File "/usr/local/plone-5.2/buildout-cache/eggs/zope.configuration-4.3.1-py2.7.egg/zope/configuration/config.py", line 225, in resolve
    __import__(mname)
  File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.contenttypes-2.1.2-py2.7.egg/plone/app/contenttypes/migration/dxmigration.py", line 10, in <module>
    from Products.contentmigration.basemigrator.migrator import CMFItemMigrator
zope.configuration.xmlconfig.ZopeXMLConfigurationError: File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.contenttypes-2.1.2-py2.7.egg/plone/app/contenttypes/upgrades.zcml", line 27.2-34.8
    File "/usr/local/plone-5.2/fivetwo/parts/client_reserved/etc/site.zcml", line 16.2-16.23
    File "/usr/local/plone-5.2/buildout-cache/eggs/Products.ATContentTypes-3.0.2-py2.7.egg/Products/ATContentTypes/configure.zcml", line 18.2-18.44
    File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.collection-1.2.7-py2.7.egg/plone/app/collection/configure.zcml", line 9.2-9.45
    File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.querystring-1.4.11-py2.7.egg/plone/app/querystring/configure.zcml", line 11.2-11.42
    File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.registry-1.7.5-py2.7.egg/plone/app/registry/configure.zcml", line 12.4-12.34
    File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.registry-1.7.5-py2.7.egg/plone/app/registry/browser/configure.zcml", line 6.4-6.43
    File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.z3cform-3.1.1-py2.7.egg/plone/app/z3cform/configure.zcml", line 10.2-10.41
    File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.widgets-3.0.2-py2.7.egg/plone/app/widgets/configure.zcml", line 6.2-6.41
    File "/usr/local/plone-5.2/buildout-cache/eggs/Products.CMFPlone-5.2.0-py2.7.egg/Products/CMFPlone/configure.zcml", line 14.2-14.46
    File "/usr/local/plone-5.2/buildout-cache/eggs/plone.app.contenttypes-2.1.2-py2.7.egg/plone/app/contenttypes/configure.zcml", line 20.2-20.34
    ImportError: No module named contentmigration.basemigrator.migrator

What am I missing that needs to be cleaned up before upgrading to 5.2?

Errors like this are an indication of a broken persistent utility. The easiest way to handle such problems is to use wildcard.fixpersistentutilities (to be found on PyPI) (read the documentation carefully, before you use it).

@fulv you still have some Archetypes-specific tools lying around in your instance but did not add Archetypes to your buildout. You need to add the archtypes-extra for Plone to get them to work again:

eggs +=
    Plone [archetypes]

This will only work in Python 2 though. Before migrating the DB to Python 3 you need to remove these. Most of these tools will be deleted when uninstalling Products.ATContentTypes and Archetypes. But my experience is that you will still have to delete at least portal_languages and portal_tinymce lying around.

I usually do this before migrating to Py3:

# remove obsolete AT tools
tools = [
    'portal_languages',
    'portal_tinymce',
    'kupu_library_tool',
    'portal_factory',
    'portal_atct',
]
for tool in tools:
    try:
        portal.manage_delObjects([tool])
        log.info('Deleted {}'.format(tool))
    except AttributeError:
        pass

Thanks, I will report back with my results.

I just migrated a site from 3.x to 5.2 and I did not manage to migrate Archetype content in 5.2

If I migrated the content to Dexterity in 5.1.5 and then migrated to 5.2 it worked.

Have you explicitly installed Archetypes in your 5.2 Plone? By default, Plone 5.2 no longer installs Archetypes (and the migration to Dexterity requires it).

@dieter are you responding to espen or to me?
I wrote above that I did add Products.ATContentTypes to the buildout, but then it wouldn't even start. I will try by adding the [archetypes] extra to Plone in the eggs, as suggested by @pbauer.

You should run Products.ATContenttype 's uninstall profile from ZMI ->"portal_setup" ->"advance import setup" before upgrade to Plone5.2.x .

With the above change to buildout I was able to complete the upgrade to 5.2, and it seems to work fine. The caveat is that no matter what I try to clean up, if I remove the [archetypes] extra from buildout, I still get the 'IATCTTool' has no attribute '__iro__' error.

In detail:

Happy path:

In 5.1:

  • Uninstall Products.Archetypes and plone.app.collections (Archetypes-based collections) from portal_quickinstaller (oddly, Products.Archetypes is listed both under installed products and under installable products, and I have to uninstall it twice before it's gone from installed products).
  • Delete portal_atct, portal_factory, portal_languages and portal_tinymce in the ZMI
  • Shut down 5.1 and copy filestorage and blobstorage over to 5.2

In 5.2:

  • In buildout, add the [archetypes] extra to the Plone egg. (It is not necessary to have Products.ATContentTypes egg). Re-run buildout.
  • Start the instance and run upgrade at @@plone-upgrade --> success

Now I have a working 5.2 site.

However:

  • portal_atct, portal_factory, portal_lanugages and portal_tinymce are back in the ZMI, even though I had explicitly deleted them before. I can delete them again, but that doesn't help.
  • @dieter: wildcard.fixpersistentutilities doesn't help. There is nothing it can do here.
  • @adam139: running the uninstall profile for Products.ATContentTypes seems to do the opposite of what it says, and definitely does not help.
  • all my content is Dexterity at this point, but something still needs to be cleaned up and I don't know what.
  • If I remove the [archetypes] extra from buildout, the site breaks again.

Please note that this is a very, very simple site without any customizations. The only complication is that it is quite old, upgraded over the years from who knows what old version of Plone, and at some point may have had some other content types present, later deleted.
So if it is difficult to upgrade this, I think we really don't have a good upgrade story yet.

I already mentioned wildcard.fixpersistentutilities (--> PyPI) in a previous response. Its primary aim is to fix up situations like yours.

  • You may have Archetypes and Products.Archetypes registered as installed products, thus you can uninstall it twice. I think I had the same issue with ATContentTypes and Products.ATContentTypes.

  • I had a case where I had to run Products.ATContentTypes:uninstall even after removing the tools. That helped:

      # remove obsolete AT tools
      tools = [
          'portal_languages',
          'portal_tinymce',
          'kupu_library_tool',
          'portal_factory',
          'portal_atct',
          'uid_catalog',
          'archetype_tool',
          'reference_catalog',
          'portal_metadata',
      ]
      for tool in tools:
          try:
              portal.manage_delObjects([tool])
              log.info('Deleted {}'.format(tool))
          except AttributeError:
              log.info('{} not found'.format(tool))
    
      # reapply uninstall to get rid of IATCTTool component
      try:
          loadMigrationProfile(
              setup,
              'profile-Products.ATContentTypes:uninstall',
          )
      except KeyError:
          pass
    

Also: plone.app.upgrade.utils.alias_module is your friend if there are interfaces or tools that are hard to remove. Check
https://github.com/plone/plone.app.upgrade/blob/master/plone/app/upgrade/init.py if you want to have you mind blown.

1 Like

Plone Foundation Code of Conduct