Migration required when moving interface classes?

I've been working on an add-on that started with one interfaces.py in which I defined several classes for Dexterity content types.

I decided because that one file was getting unwieldy that I would split it up into several .py files, each containing just one class. And then to make things really interesting, I decided to put those files into a new "interfaces" subdirectory, so interfaces.py was replaced with interfaces/class1.py and interfaces/class2.py, and so on.

When I restarted the instance, things worked fine until I tried to view an existing content item of the type whose interface class I'd just moved, when I got a recursion depth exceeded error: RuntimeError: maximum recursion depth exceeded while calling a Python object

What kind of migration would I need to do in an upgrade step to fix this?

  Module ZPublisher.Publish, line 138, in publish
  Module ZPublisher.mapply, line 44, in mapply
  Module zope.publisher.publish, line 42, in unwrapMethod
  Module plone.dexterity.content, line 321, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 64, in decorator
  Module plone.dexterity.schema, line 112, in get
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
  Module plone.dexterity.schema, line 355, in __call__
  Module plone.dexterity.fti, line 265, in lookupModel
  Module plone.dexterity.fti, line 253, in lookupSchema
  Module plone.alterego.dynamic, line 25, in __getattr__
  Module plone.synchronize.decorator, line 9, in synchronized_function
RuntimeError: maximum recursion depth exceeded while calling a Python object
> /usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/traceback.py(222)_some_str()
-> return '<unprintable %s object>' % type(value).__name__

Did you also update the FTI?

-aj

If the problem isn't that you haven't updated the FTI to reference the new location of the schema, then you can probably work around it by adding interfaces/init.py which imports the interfaces from the new submodules.

Another wild guess: aren‘t interfaces indexed somewhere in portal_catalog?

-aj

I could kiss you both! :slight_smile:

I had indeed forgotten to update the FTI

:kiss: :kiss:

In case anyone lands here, for reference, when I hit this problem again I did have to add explicit imports into the new interfaces folder's __init__.py, like this: