From 1a20bba3c6ebb02132e61f44b20865c4bf66aa38 Mon Sep 17 00:00:00 2001 From: Maurits van Rees Date: Thu, 9 Nov 2023 14:45:48 +0100 Subject: [PATCH] Make finalizeSchema more robust by not handling behavior schema classes. Backported from version 2.0. This fixes test failures on Plone 5.2 Python 3 when used together with https://github.com/plone/plone.dexterity/pull/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 "", line 1, in 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 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 "", line 1, in TypeError: '<' not supported between instances of 'Provides' and 'Implements' ``` --- news/186.feature | 3 +++ plone/supermodel/model.py | 24 ++++++++++++++++++++++-- setup.py | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 news/186.feature diff --git a/news/186.feature b/news/186.feature new file mode 100644 index 0000000..2411b81 --- /dev/null +++ b/news/186.feature @@ -0,0 +1,3 @@ +Make finalizeSchema more robust by not handling behavior schema classes. +Backported from version 2.0. +[maurits] diff --git a/plone/supermodel/model.py b/plone/supermodel/model.py index 6353f4a..175daed 100644 --- a/plone/supermodel/model.py +++ b/plone/supermodel/model.py @@ -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 diff --git a/setup.py b/setup.py index 5f2a2c0..160c0b9 100644 --- a/setup.py +++ b/setup.py @@ -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' +