Skip to content

Commit

Permalink
Make finalizeSchema more robust by not handling behavior schema classes.
Browse files Browse the repository at this point in the history
Backported from version 2.0.

This fixes test failures on Plone 5.2 Python 3 when used together with plone/plone.dexterity#189, which is a backport of a memory leak fix.
Failures are like this:

```
File "/home/jenkins/.buildout/eggs/cp38/plone.autoform-1.9.1-py3.8.egg/plone/autoform/tests/../autoform.rst", line 50, in autoform.rst
Failed example:
    xmlconfig.xmlconfig(StringIO(configuration))
Exception raised:
    Traceback (most recent call last):
      File "/srv/python3.8/lib/python3.8/doctest.py", line 1336, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest autoform.rst[11]>", line 1, in <module>
        xmlconfig.xmlconfig(StringIO(configuration))
      File "/home/jenkins/.buildout/eggs/cp38/zope.configuration-4.4.1-py3.8.egg/zope/configuration/xmlconfig.py", line 732, in xmlconfig
        context.execute_actions(testing=testing)
      File "/home/jenkins/.buildout/eggs/cp38/zope.configuration-4.4.1-py3.8.egg/zope/configuration/config.py", line 799, in execute_actions
        reraise(
      File "/home/jenkins/.buildout/eggs/cp38/zope.configuration-4.4.1-py3.8.egg/zope/configuration/_compat.py", line 31, in reraise
        raise value.with_traceback(tb)
      File "/home/jenkins/.buildout/eggs/cp38/zope.configuration-4.4.1-py3.8.egg/zope/configuration/config.py", line 791, in execute_actions
        callable(*args, **kw)
      File "/home/jenkins/.buildout/eggs/cp38/plone.supermodel-1.6.5-py3.8.egg/plone/supermodel/model.py", line 116, in finalizeSchemas
        for schema in sorted(schemas):
    zope.configuration.config.ConfigurationExecutionError: File "/home/jenkins/.buildout/eggs/cp38/plone.supermodel-1.6.5-py3.8.egg/plone/supermodel/configure.zcml", line 9.4-12.10
          <zcml:customAction
              handler=".model.finalizeSchemas"
              order="9999999"
              />

        TypeError: '<' not supported between instances of 'Provides' and 'InterfaceClass'
```

The test failures are mostly in `plone.autoform` and in `plone.app.registry`, but strangely you do not get the error when you run only the tests for one of those packages.
You really need to run the entire Plone test suite (`bin/test` in coredev, without options).  So there is likely some test leakage.

Python 2 does not have this problem: sorting on Python 3 is handled differently.
On Python 2:

```
>>> from zope.interface.declarations import Implements, Provides
>>> sorted([Implements(), Provides(object)])
[classImplements(?), directlyProvides(object)]
```

On Python 3:

```
>>> from zope.interface.declarations import Implements, Provides
>>> sorted([Implements(), Provides(object)])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: '<' not supported between instances of 'Provides' and 'Implements'
```
  • Loading branch information
mauritsvanrees committed Nov 9, 2023
1 parent b9638c5 commit 1a20bba
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
3 changes: 3 additions & 0 deletions news/186.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Make finalizeSchema more robust by not handling behavior schema classes.
Backported from version 2.0.
[maurits]
24 changes: 22 additions & 2 deletions plone/supermodel/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,28 @@ def finalizeSchemas(parent=Schema):
)

def walk(schema):
yield schema
for child in schema.dependents.keys():
# When we have behaviors on the Plone site root we got some schemas that
# are not SchemaClasses. Same is true on Plone 5.2 if we use a backported
# fix for plone.dexterity to use 'Provides' instead of 'Implements', which
# should fix a memory leak:
# https://github.com/plone/plone.dexterity/pull/189
# If we yield such a schema, then 'sorted(schemas)' below will fail on
# Python 3 with: TypeError: '<' not supported between instances of
# 'Provides' and 'InterfaceClass'.
if isinstance(schema, SchemaClass):
yield schema

# This try..except is to handle AttributeError:
# 'VerifyingAdapterLookup' object has no attribute 'dependents'.
# afaik this happens in tests only.
# We have issue https://github.com/plone/plone.supermodel/issues/14
# to find out why this is happening in the first place.
try:
children = schema.dependents.keys()
except AttributeError:
children = ()

for child in children:
for s in walk(child):
yield s

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()

version = '1.6.6.dev0'
version = '1.7.0.dev0'

long_description = (
read('README.rst') + '\n' +
Expand Down

0 comments on commit 1a20bba

Please sign in to comment.