diff --git a/last_commit.txt b/last_commit.txt index 5b0f2efa18..4151653688 100644 --- a/last_commit.txt +++ b/last_commit.txt @@ -1,34 +1,66 @@ -Repository: plone.app.z3cform +Repository: plone.schema Branch: refs/heads/master -Date: 2023-03-24T12:03:17+01:00 +Date: 2023-03-24T11:52:53+01:00 Author: Jens W. Klein (jensens) -Commit: https://github.com/plone/plone.app.z3cform/commit/63a71ae8f5ae2230e786fed940e7a622f5d7113b +Commit: https://github.com/plone/plone.schema/commit/eaeafd602d0d198cf6fd53827483ba660f157e10 -Inherit from new plone.schema formlayer to avoid transitive circular dependencies +fixes #12, isort, black, pyupgrade, dependency cleanup Files changed: -A news/163.bugfix -M plone/app/z3cform/interfaces.py +A news/12.bugfix +A news/17.breaking +A plone/schema/interfaces.py +M README.rst +M plone/__init__.py +M plone/schema/__init__.py +M plone/schema/browser/configure.zcml +M plone/schema/browser/email.py +M plone/schema/browser/jsonfield.py +M plone/schema/browser/uri.py +M plone/schema/configure.zcml +M plone/schema/editor.py +M plone/schema/email.py +M plone/schema/handler.py +M plone/schema/jsonfield.py +M plone/schema/tests/test_doctests.py +M setup.cfg +M setup.py -b'diff --git a/news/163.bugfix b/news/163.bugfix\nnew file mode 100644\nindex 00000000..d79fa908\n--- /dev/null\n+++ b/news/163.bugfix\n@@ -0,0 +1,3 @@\n+Fixes transitive circular dependency to plone.schema.\n+Inherit own Browserlayer from new intermediate browserlayer in plone.schema.\n+[jensens]\ndiff --git a/plone/app/z3cform/interfaces.py b/plone/app/z3cform/interfaces.py\nindex 1db3ad36..c48fe2e6 100644\n--- a/plone/app/z3cform/interfaces.py\n+++ b/plone/app/z3cform/interfaces.py\n@@ -1,5 +1,5 @@\n from plone.app.textfield.widget import IRichTextWidget as patextfield_IRichTextWidget\n-from z3c.form.interfaces import IFormLayer\n+from plone.schema.interfaces import IFormLayer\n from z3c.form.interfaces import IRadioWidget\n from z3c.form.interfaces import ISelectWidget as IBaseSelectWidget\n from z3c.form.interfaces import ISingleCheckBoxWidget\n' +b'diff --git a/README.rst b/README.rst\nindex 9ef1893..8f2594c 100644\n--- a/README.rst\n+++ b/README.rst\n@@ -1 +1,17 @@\n-Plone specific extensions and fields for zope schematas.\n+Provides additional fields and widgets for z3c.form and optional integration with Plone.\n+\n+- Email Field and Widget\n+- JSON Field and Widget\n+- URI Field and Widget\n+- IPath as IChoice derivative (and implementation)\n+- integration with plone.supermodel, optional (extra "supermodel")\n+- integration with plone.schemaeditor, optional (extra "schemaeditor")\n+\n+\n+Source Code\n+===========\n+\n+Contributors please read the document `Process for Plone core\'s development `_\n+\n+Sources are at the `Plone code repository hosted at Github `_.\n+\ndiff --git a/news/12.bugfix b/news/12.bugfix\nnew file mode 100644\nindex 0000000..e79657e\n--- /dev/null\n+++ b/news/12.bugfix\n@@ -0,0 +1,3 @@\n+Fix #12: no transitive circular dependency over `plone.app.z3c.form` anymore.\n+This removes the registration on `IPloneFormLayer` and uses the base layer of z3c.form `IFormLayer`.\n+[jensens]\n\\ No newline at end of file\ndiff --git a/news/17.breaking b/news/17.breaking\nnew file mode 100644\nindex 0000000..735e2f5\n--- /dev/null\n+++ b/news/17.breaking\n@@ -0,0 +1,5 @@\n+Drop Python 2 support.\n+Housecleaning: pyupgrade, isort, black.\n+Introduce extras `plone.schema[supermodel]` and `plone.schema[schemaeditor]`.\n+The package works in its vanilla installation as an addon for z3c.form, without any other plone dependencies.\n+[jensens]\n\\ No newline at end of file\ndiff --git a/plone/__init__.py b/plone/__init__.py\nindex f48ad10..05f0beb 100644\n--- a/plone/__init__.py\n+++ b/plone/__init__.py\n@@ -1,6 +1,7 @@\n # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages\n try:\n- __import__(\'pkg_resources\').declare_namespace(__name__)\n+ __import__("pkg_resources").declare_namespace(__name__)\n except ImportError:\n from pkgutil import extend_path\n+\n __path__ = extend_path(__path__, __name__)\ndiff --git a/plone/schema/__init__.py b/plone/schema/__init__.py\nindex 2cf35ac..4f6c1af 100644\n--- a/plone/schema/__init__.py\n+++ b/plone/schema/__init__.py\n@@ -1,15 +1,9 @@\n-from zope.i18nmessageid import MessageFactory\n-_ = MessageFactory(\'plone\')\n-\n-\n from .email import Email\n from .email import IEmail\n-\n-from .path import Path\n-from .path import IPath\n-\n-from .jsonfield import JSONField\n from .jsonfield import IJSONField\n+from .jsonfield import JSONField\n+from .path import IPath\n+from .path import Path\n \n # zope.schema convenience imports\n from zope.schema._field import ASCII\ndiff --git a/plone/schema/browser/configure.zcml b/plone/schema/browser/configure.zcml\nindex 8f3f15e..f0e211f 100644\n--- a/plone/schema/browser/configure.zcml\n+++ b/plone/schema/browser/configure.zcml\n@@ -1,30 +1,34 @@\n \n+ xmlns:z3c="http://namespaces.zope.org/z3c"\n+ i18n_domain="plone"\n+ >\n \n- \n- \n+ \n+ \n \n- \n- \n- \n+ \n+ \n+ \n \n- \n \n- \n \n- \n+ \n \n \ndiff --git a/plone/schema/browser/email.py b/plone/schema/browser/email.py\nindex 4a548ba..9b758e2 100644\n--- a/plone/schema/browser/email.py\n+++ b/plone/schema/browser/email.py\n@@ -1,26 +1,28 @@\n-from zope.component import adapter\n-from zope.interface import implementer\n-from z3c.form.interfaces import ITextWidget\n-from z3c.form.interfaces import IFieldWidget\n+from ..email import IEmail\n+from ..interfaces import IFormLayer\n from z3c.form.browser.text import TextWidget\n+from z3c.form.interfaces import IFieldWidget\n+from z3c.form.interfaces import ITextWidget\n from z3c.form.widget import FieldWidget\n+from zope.component import adapter\n+from zope.i18nmessageid import MessageFactory\n+from zope.interface import implementer\n \n-from plone.app.z3cform.interfaces import IPloneFormLayer\n \n-from plone.schema.email import IEmail\n+_ = MessageFactory("plone")\n \n \n class IEmailWidget(ITextWidget):\n- """ Email Widget """\n+ """Email Widget"""\n \n \n @implementer(IEmailWidget)\n class EmailWidget(TextWidget):\n- klass = u\'email-widget\'\n+ klass = "email-widget"\n value = None\n \n \n-@adapter(IEmail, IPloneFormLayer)\n+@adapter(IEmail, IFormLayer)\n @implementer(IFieldWidget)\n def EmailFieldWidget(field, request):\n return FieldWidget(field, EmailWidget(request))\ndiff --git a/plone/schema/browser/jsonfield.py b/plone/schema/browser/jsonfield.py\nindex 9d2a8a6..3c2cba2 100644\n--- a/plone/schema/browser/jsonfield.py\n+++ b/plone/schema/browser/jsonfield.py\n@@ -1,36 +1,40 @@\n-from zope.component import adapter\n-from zope.interface import implementer\n-from z3c.form.interfaces import ITextAreaWidget\n-from z3c.form.interfaces import IFieldWidget\n+from ..interfaces import IFormLayer\n+from ..jsonfield import IJSONField\n from z3c.form.browser.textarea import TextAreaWidget\n-from z3c.form.widget import FieldWidget\n from z3c.form.interfaces import IDataConverter\n+from z3c.form.interfaces import IFieldWidget\n+from z3c.form.interfaces import ITextAreaWidget\n from z3c.form.interfaces import IWidget\n-from plone.app.z3cform.interfaces import IPloneFormLayer\n+from z3c.form.widget import FieldWidget\n+from zope.component import adapter\n from zope.component import adapts\n-from plone.schema.jsonfield import IJSONField\n+from zope.i18nmessageid import MessageFactory\n+from zope.interface import implementer\n \n import json\n \n \n+_ = MessageFactory("plone")\n+\n+\n class IJSONFieldWidget(ITextAreaWidget):\n- """ JSON Widget """\n+ """JSON Widget"""\n \n \n @implementer(IJSONFieldWidget)\n class JSONWidget(TextAreaWidget):\n- klass = u\'json-widget\'\n+ klass = "json-widget"\n value = None\n \n \n-@adapter(IJSONField, IPloneFormLayer)\n+@adapter(IJSONField, IFormLayer)\n @implementer(IFieldWidget)\n def JSONFieldWidget(field, request):\n return FieldWidget(field, JSONWidget(request))\n \n \n @implementer(IDataConverter)\n-class JSONDataConverter(object):\n+class JSONDataConverter:\n """A JSON data converter."""\n \n adapts(IJSONField, IWidget)\n@@ -42,13 +46,13 @@ def __init__(self, field, widget):\n def toWidgetValue(self, value):\n """See interfaces.IDataConverter"""\n if value is self.field.missing_value:\n- return u\'\'\n+ return ""\n return json.dumps(value, indent=True)\n \n def toFieldValue(self, value):\n """See interfaces.IDataConverter"""\n \n- if value == u\'\':\n+ if value == "":\n return self.field.missing_value\n \n return self.field.fromUnicode(value)\ndiff --git a/plone/schema/browser/uri.py b/plone/schema/browser/uri.py\nindex 0fd13a3..b7bd6e2 100644\n--- a/plone/schema/browser/uri.py\n+++ b/plone/schema/browser/uri.py\n@@ -1,3 +1,4 @@\n+from ..interfaces import IFormLayer\n from z3c.form.browser.text import TextWidget\n from z3c.form.interfaces import IFieldWidget\n from z3c.form.interfaces import ITextWidget\n@@ -6,20 +7,18 @@\n from zope.interface import implementer\n from zope.schema.interfaces import IURI\n \n-from plone.app.z3cform.interfaces import IPloneFormLayer\n-\n \n class IURIWidget(ITextWidget):\n- """ URI Widget """\n+ """URI Widget"""\n \n \n @implementer(IURIWidget)\n class URIWidget(TextWidget):\n- klass = u\'uri-widget\'\n+ klass = "uri-widget"\n value = None\n \n \n-@adapter(IURI, IPloneFormLayer)\n+@adapter(IURI, IFormLayer)\n @implementer(IFieldWidget)\n def URIFieldWidget(field, request):\n return FieldWidget(field, URIWidget(request))\ndiff --git a/plone/schema/configure.zcml b/plone/schema/configure.zcml\nindex 3fc87cd..d84a8c4 100644\n--- a/plone/schema/configure.zcml\n+++ b/plone/schema/configure.zcml\n@@ -3,59 +3,62 @@\n xmlns:five="http://namespaces.zope.org/five"\n xmlns:i18n="http://namespaces.zope.org/i18n"\n xmlns:zcml="http://namespaces.zope.org/zcml"\n- i18n_domain="plone">\n-\n- \n- \n-\n- \n- \n- \n-\n- \n-\n- \n-\n- \n-\n- \n- \n- \n- \n- \n-\n- \n- \n- \n-\n- \n- \n- \n-\n- \n-\n- \n-\n- \n-\n- \n+ i18n_domain="plone"\n+ >\n+\n+ \n+ \n+\n+ \n+ \n+ \n+\n+ \n+\n+ \n+\n+ \n+\n+ \n+ \n+ \n+ \n+ \n+\n+ \n+ \n+ \n+\n+ \n+ \n+ \n+\n+ \n+\n+ \n+\n+ \n+\n+ \n \n \ndiff --git a/plone/schema/editor.py b/plone/schema/editor.py\nindex 1df264f..e7bd3fa 100644\n--- a/plone/schema/editor.py\n+++ b/plone/schema/editor.py\n@@ -1,30 +1,32 @@\n-from plone.schema import _\n-from plone.schema.email import Email, IEmail\n+from .email import Email\n+from .email import IEmail\n+from .jsonfield import IJSONField\n+from .jsonfield import JSONField\n from plone.schemaeditor.fields import FieldFactory\n+from zope.i18nmessageid import MessageFactory\n from zope.interface import Attribute\n from zope.schema import URI\n from zope.schema.interfaces import IURI\n-from plone.schema.jsonfield import IJSONField\n-from plone.schema.jsonfield import JSONField\n \n \n-class IURI(IURI):\n+_ = MessageFactory("plone")\n+\n \n+class IURI(IURI):\n # prevent some settings from being included in the field edit form\n- default = Attribute(\'\')\n+ default = Attribute("")\n \n \n class IEmail(IEmail):\n-\n # prevent some settings from being included in the field edit form\n- default = Attribute(\'\')\n+ default = Attribute("")\n \n \n class IJSON(IJSONField):\n # prevent some settings from being included in the field edit form\n- default = Attribute(\'\')\n+ default = Attribute("")\n \n \n-URIFactory = FieldFactory(URI, _(u\'URL\'))\n-EmailFactory = FieldFactory(Email, _(u\'Email\'))\n-JSONFactory = FieldFactory(JSONField, _(u\'JSONField\'))\n+URIFactory = FieldFactory(URI, _("URL"))\n+EmailFactory = FieldFactory(Email, _("Email"))\n+JSONFactory = FieldFactory(JSONField, _("JSONField"))\ndiff --git a/plone/schema/email.py b/plone/schema/email.py\nindex 378fb07..962f863 100644\n--- a/plone/schema/email.py\n+++ b/plone/schema/email.py\n@@ -1,19 +1,22 @@\n-from plone.schema import _\n+from zope.i18nmessageid import MessageFactory\n from zope.interface import implementer\n from zope.schema import NativeStringLine\n from zope.schema.interfaces import IFromUnicode\n from zope.schema.interfaces import INativeStringLine\n from zope.schema.interfaces import ValidationError\n+\n import re\n \n+\n+_ = MessageFactory("plone")\n+\n # Taken from http://www.regular-expressions.info/email.html\n _isemail = r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"\n _isemail = re.compile(_isemail).match\n \n \n class IEmail(INativeStringLine):\n- """A field containing an email address\n- """\n+ """A field containing an email address"""\n \n \n class InvalidEmail(ValidationError):\n@@ -22,11 +25,10 @@ class InvalidEmail(ValidationError):\n \n @implementer(IEmail, IFromUnicode)\n class Email(NativeStringLine):\n- """Email schema field\n- """\n+ """Email schema field"""\n \n def _validate(self, value):\n- super(Email, self)._validate(value)\n+ super()._validate(value)\n if _isemail(value):\n return\n \ndiff --git a/plone/schema/handler.py b/plone/schema/handler.py\nindex e743191..06bca34 100644\n--- a/plone/schema/handler.py\n+++ b/plone/schema/handler.py\n@@ -1,7 +1,8 @@\n+from .email import Email\n+from .jsonfield import JSONField\n from plone.supermodel.exportimport import BaseHandler\n from zope.schema import URI\n-from plone.schema.email import Email\n-from plone.schema.jsonfield import JSONField\n+\n \n URIHandler = BaseHandler(URI)\n EmailHandler = BaseHandler(Email)\ndiff --git a/plone/schema/interfaces.py b/plone/schema/interfaces.py\nnew file mode 100644\nindex 0000000..43671c8\n--- /dev/null\n+++ b/plone/schema/interfaces.py\n@@ -0,0 +1,5 @@\n+from z3c.form.interfaces import IFormLayer as IBaseFormLayer\n+\n+\n+class IFormLayer(IBaseFormLayer):\n+ """Request layer. Must be enabled to activate widgets"""\ndiff --git a/plone/schema/jsonfield.py b/plone/schema/jsonfield.py\nindex 1c92b9f..636f60b 100644\n--- a/plone/schema/jsonfield.py\n+++ b/plone/schema/jsonfield.py\n@@ -1,20 +1,19 @@\n-import ast\n-import json\n-import jsonschema\n-from plone.schema import _\n+from json import JSONDecodeError\n+from zope.i18nmessageid import MessageFactory\n from zope.interface import Attribute\n from zope.interface import implementer\n from zope.schema import Field\n from zope.schema._bootstrapinterfaces import WrongType\n from zope.schema.interfaces import IField\n-from zope.schema.interfaces import WrongContainedType\n from zope.schema.interfaces import IFromUnicode\n+from zope.schema.interfaces import WrongContainedType\n+\n+import ast\n+import json\n+import jsonschema\n+\n \n-try:\n- from json import JSONDecodeError\n-except ImportError:\n- # Python 2\n- JSONDecodeError = ValueError\n+_ = MessageFactory("plone")\n \n \n DEFAULT_JSON_SCHEMA = json.dumps({"type": "object", "properties": {}})\n@@ -40,10 +39,10 @@ def __init__(self, schema=DEFAULT_JSON_SCHEMA, widget=None, **kw):\n self.json_schema = json.loads(schema)\n except ValueError:\n raise WrongType\n- super(JSONField, self).__init__(**kw)\n+ super().__init__(**kw)\n \n def _validate(self, value):\n- super(JSONField, self)._validate(value)\n+ super()._validate(value)\n \n try:\n jsonschema.validate(value, self.json_schema)\ndiff --git a/plone/schema/tests/test_doctests.py b/plone/schema/tests/test_doctests.py\nindex 9e4dbb2..15fe80c 100644\n--- a/plone/schema/tests/test_doctests.py\n+++ b/plone/schema/tests/test_doctests.py\n@@ -1,23 +1,8 @@\n """ Tests\n """\n-import re\n-import six\n-import unittest\n import doctest\n-\n-class Py23DocChecker(doctest.OutputChecker):\n- def check_output(self, want, got, optionflags):\n- if six.PY2:\n- got = re.sub("u\'(.*?)\'", "\'\\\\1\'", want)\n- got = re.sub(\' encoding="utf-8"\', \'\', want)\n- # want = re.sub("b\'(.*?)\'", "\'\\\\1\'", want)\n- return doctest.OutputChecker.check_output(self, want, got, optionflags)\n+import unittest\n \n \n def test_suite():\n- return unittest.TestSuite((\n- doctest.DocTestSuite(\n- \'plone.schema.jsonfield\',\n- checker=Py23DocChecker()\n- ),\n- ))\n+ return unittest.TestSuite((doctest.DocTestSuite("plone.schema.jsonfield"),))\ndiff --git a/setup.cfg b/setup.cfg\nindex a76531e..3972628 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -5,4 +5,7 @@ ignore =\n \n \n [bdist_wheel]\n-universal = 1\n+universal = 0\n+\n+[isort]\n+profile = plone\ndiff --git a/setup.py b/setup.py\nindex 42256a7..81a67a8 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,53 +1,49 @@\n-from setuptools import setup, find_packages\n+from setuptools import find_packages\n+from setuptools import setup\n \n-version = \'1.4.1.dev0\'\n \n-long_description = open("README.rst").read() + "\\n" + \\\n- open("CHANGES.rst").read()\n+version = "2.0.0.dev0"\n+\n+long_description = open("README.rst").read() + "\\n" + open("CHANGES.rst").read()\n \n setup(\n- name=\'plone.schema\',\n+ name="plone.schema",\n version=version,\n- description=\'Plone specific extensions and fields for zope schematas\',\n+ description="Plone specific extensions and fields for zope schematas",\n long_description=long_description,\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n- "Framework :: Zope2",\n- "Framework :: Zope :: 4",\n+ "Framework :: Zope :: 5",\n "Framework :: Plone",\n- "Framework :: Plone :: 5.0",\n- "Framework :: Plone :: 5.1",\n- "Framework :: Plone :: 5.2",\n+ "Framework :: Plone :: 6.0",\n "Framework :: Plone :: Core",\n "Programming Language :: Python",\n- "Programming Language :: Python :: 2.7",\n- "Programming Language :: Python :: 3.6",\n- "Programming Language :: Python :: 3.7",\n "Programming Language :: Python :: 3.8",\n+ "Programming Language :: Python :: 3.9",\n+ "Programming Language :: Python :: 3.10",\n+ "Programming Language :: Python :: 3.11",\n "Topic :: Software Development :: Libraries :: Python Modules",\n "License :: OSI Approved :: BSD License",\n ],\n- keywords=\'plone schema\',\n- author=\'Plone Foundation\',\n- author_email=\'plone-developers@lists.sourceforge.net\',\n- url=\'https://github.com/plone/plone.schema\',\n- license=\'BSD\',\n+ keywords="schema z3cform email uri json field widget",\n+ author="Plone Foundation",\n+ author_email="plone-developers@lists.sourceforge.net",\n+ url="https://github.com/plone/plone.schema",\n+ license="BSD",\n packages=find_packages(),\n- namespace_packages=[\'plone\'],\n+ namespace_packages=["plone"],\n include_package_data=True,\n zip_safe=False,\n install_requires=[\n- \'setuptools\',\n- \'plone.app.z3cform\',\n- \'jsonschema\',\n- \'z3c.form\',\n- \'zope.component\',\n- \'zope.i18nmessageid\',\n- \'zope.interface\',\n- \'zope.schema\',\n+ "jsonschema",\n+ "setuptools",\n+ "z3c.form",\n+ "zope.deprecation",\n+ "zope.i18nmessageid",\n ],\n- extras_require={\'test\': [\n- \'six\',\n- \'plone.app.testing\'\n- ]},\n+ extras_require={\n+ "test": ["plone.app.testing"],\n+ "schemaeditor": ["plone.schemaeditor"],\n+ "supermodel": ["plone.supermodel"],\n+ },\n )\n' -Repository: plone.app.z3cform +Repository: plone.schema Branch: refs/heads/master -Date: 2023-03-25T15:35:45+01:00 +Date: 2023-03-25T15:35:59+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.z3cform/commit/21cf1f3b554a7cfe527186307b54e99bd5e3b30b +Commit: https://github.com/plone/plone.schema/commit/5c63531aae55ae60e8b9f922c2af14a09d87c318 -Merge pull request #163 from plone/formlayer-cleanup +Merge pull request #17 from plone/housecleaning -Inherit from new plone.schema formlayer to avoid transitive circular … +fixes #12, isort, black, pyupgrade, dependency cleanup Files changed: -A news/163.bugfix -M plone/app/z3cform/interfaces.py +A news/12.bugfix +A news/17.breaking +A plone/schema/interfaces.py +M README.rst +M plone/__init__.py +M plone/schema/__init__.py +M plone/schema/browser/configure.zcml +M plone/schema/browser/email.py +M plone/schema/browser/jsonfield.py +M plone/schema/browser/uri.py +M plone/schema/configure.zcml +M plone/schema/editor.py +M plone/schema/email.py +M plone/schema/handler.py +M plone/schema/jsonfield.py +M plone/schema/tests/test_doctests.py +M setup.cfg +M setup.py -b'diff --git a/news/163.bugfix b/news/163.bugfix\nnew file mode 100644\nindex 00000000..d79fa908\n--- /dev/null\n+++ b/news/163.bugfix\n@@ -0,0 +1,3 @@\n+Fixes transitive circular dependency to plone.schema.\n+Inherit own Browserlayer from new intermediate browserlayer in plone.schema.\n+[jensens]\ndiff --git a/plone/app/z3cform/interfaces.py b/plone/app/z3cform/interfaces.py\nindex 1db3ad36..c48fe2e6 100644\n--- a/plone/app/z3cform/interfaces.py\n+++ b/plone/app/z3cform/interfaces.py\n@@ -1,5 +1,5 @@\n from plone.app.textfield.widget import IRichTextWidget as patextfield_IRichTextWidget\n-from z3c.form.interfaces import IFormLayer\n+from plone.schema.interfaces import IFormLayer\n from z3c.form.interfaces import IRadioWidget\n from z3c.form.interfaces import ISelectWidget as IBaseSelectWidget\n from z3c.form.interfaces import ISingleCheckBoxWidget\n' +b'diff --git a/README.rst b/README.rst\nindex 9ef1893..8f2594c 100644\n--- a/README.rst\n+++ b/README.rst\n@@ -1 +1,17 @@\n-Plone specific extensions and fields for zope schematas.\n+Provides additional fields and widgets for z3c.form and optional integration with Plone.\n+\n+- Email Field and Widget\n+- JSON Field and Widget\n+- URI Field and Widget\n+- IPath as IChoice derivative (and implementation)\n+- integration with plone.supermodel, optional (extra "supermodel")\n+- integration with plone.schemaeditor, optional (extra "schemaeditor")\n+\n+\n+Source Code\n+===========\n+\n+Contributors please read the document `Process for Plone core\'s development `_\n+\n+Sources are at the `Plone code repository hosted at Github `_.\n+\ndiff --git a/news/12.bugfix b/news/12.bugfix\nnew file mode 100644\nindex 0000000..e79657e\n--- /dev/null\n+++ b/news/12.bugfix\n@@ -0,0 +1,3 @@\n+Fix #12: no transitive circular dependency over `plone.app.z3c.form` anymore.\n+This removes the registration on `IPloneFormLayer` and uses the base layer of z3c.form `IFormLayer`.\n+[jensens]\n\\ No newline at end of file\ndiff --git a/news/17.breaking b/news/17.breaking\nnew file mode 100644\nindex 0000000..735e2f5\n--- /dev/null\n+++ b/news/17.breaking\n@@ -0,0 +1,5 @@\n+Drop Python 2 support.\n+Housecleaning: pyupgrade, isort, black.\n+Introduce extras `plone.schema[supermodel]` and `plone.schema[schemaeditor]`.\n+The package works in its vanilla installation as an addon for z3c.form, without any other plone dependencies.\n+[jensens]\n\\ No newline at end of file\ndiff --git a/plone/__init__.py b/plone/__init__.py\nindex f48ad10..05f0beb 100644\n--- a/plone/__init__.py\n+++ b/plone/__init__.py\n@@ -1,6 +1,7 @@\n # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages\n try:\n- __import__(\'pkg_resources\').declare_namespace(__name__)\n+ __import__("pkg_resources").declare_namespace(__name__)\n except ImportError:\n from pkgutil import extend_path\n+\n __path__ = extend_path(__path__, __name__)\ndiff --git a/plone/schema/__init__.py b/plone/schema/__init__.py\nindex 2cf35ac..4f6c1af 100644\n--- a/plone/schema/__init__.py\n+++ b/plone/schema/__init__.py\n@@ -1,15 +1,9 @@\n-from zope.i18nmessageid import MessageFactory\n-_ = MessageFactory(\'plone\')\n-\n-\n from .email import Email\n from .email import IEmail\n-\n-from .path import Path\n-from .path import IPath\n-\n-from .jsonfield import JSONField\n from .jsonfield import IJSONField\n+from .jsonfield import JSONField\n+from .path import IPath\n+from .path import Path\n \n # zope.schema convenience imports\n from zope.schema._field import ASCII\ndiff --git a/plone/schema/browser/configure.zcml b/plone/schema/browser/configure.zcml\nindex 8f3f15e..f0e211f 100644\n--- a/plone/schema/browser/configure.zcml\n+++ b/plone/schema/browser/configure.zcml\n@@ -1,30 +1,34 @@\n \n+ xmlns:z3c="http://namespaces.zope.org/z3c"\n+ i18n_domain="plone"\n+ >\n \n- \n- \n+ \n+ \n \n- \n- \n- \n+ \n+ \n+ \n \n- \n \n- \n \n- \n+ \n \n \ndiff --git a/plone/schema/browser/email.py b/plone/schema/browser/email.py\nindex 4a548ba..9b758e2 100644\n--- a/plone/schema/browser/email.py\n+++ b/plone/schema/browser/email.py\n@@ -1,26 +1,28 @@\n-from zope.component import adapter\n-from zope.interface import implementer\n-from z3c.form.interfaces import ITextWidget\n-from z3c.form.interfaces import IFieldWidget\n+from ..email import IEmail\n+from ..interfaces import IFormLayer\n from z3c.form.browser.text import TextWidget\n+from z3c.form.interfaces import IFieldWidget\n+from z3c.form.interfaces import ITextWidget\n from z3c.form.widget import FieldWidget\n+from zope.component import adapter\n+from zope.i18nmessageid import MessageFactory\n+from zope.interface import implementer\n \n-from plone.app.z3cform.interfaces import IPloneFormLayer\n \n-from plone.schema.email import IEmail\n+_ = MessageFactory("plone")\n \n \n class IEmailWidget(ITextWidget):\n- """ Email Widget """\n+ """Email Widget"""\n \n \n @implementer(IEmailWidget)\n class EmailWidget(TextWidget):\n- klass = u\'email-widget\'\n+ klass = "email-widget"\n value = None\n \n \n-@adapter(IEmail, IPloneFormLayer)\n+@adapter(IEmail, IFormLayer)\n @implementer(IFieldWidget)\n def EmailFieldWidget(field, request):\n return FieldWidget(field, EmailWidget(request))\ndiff --git a/plone/schema/browser/jsonfield.py b/plone/schema/browser/jsonfield.py\nindex 9d2a8a6..3c2cba2 100644\n--- a/plone/schema/browser/jsonfield.py\n+++ b/plone/schema/browser/jsonfield.py\n@@ -1,36 +1,40 @@\n-from zope.component import adapter\n-from zope.interface import implementer\n-from z3c.form.interfaces import ITextAreaWidget\n-from z3c.form.interfaces import IFieldWidget\n+from ..interfaces import IFormLayer\n+from ..jsonfield import IJSONField\n from z3c.form.browser.textarea import TextAreaWidget\n-from z3c.form.widget import FieldWidget\n from z3c.form.interfaces import IDataConverter\n+from z3c.form.interfaces import IFieldWidget\n+from z3c.form.interfaces import ITextAreaWidget\n from z3c.form.interfaces import IWidget\n-from plone.app.z3cform.interfaces import IPloneFormLayer\n+from z3c.form.widget import FieldWidget\n+from zope.component import adapter\n from zope.component import adapts\n-from plone.schema.jsonfield import IJSONField\n+from zope.i18nmessageid import MessageFactory\n+from zope.interface import implementer\n \n import json\n \n \n+_ = MessageFactory("plone")\n+\n+\n class IJSONFieldWidget(ITextAreaWidget):\n- """ JSON Widget """\n+ """JSON Widget"""\n \n \n @implementer(IJSONFieldWidget)\n class JSONWidget(TextAreaWidget):\n- klass = u\'json-widget\'\n+ klass = "json-widget"\n value = None\n \n \n-@adapter(IJSONField, IPloneFormLayer)\n+@adapter(IJSONField, IFormLayer)\n @implementer(IFieldWidget)\n def JSONFieldWidget(field, request):\n return FieldWidget(field, JSONWidget(request))\n \n \n @implementer(IDataConverter)\n-class JSONDataConverter(object):\n+class JSONDataConverter:\n """A JSON data converter."""\n \n adapts(IJSONField, IWidget)\n@@ -42,13 +46,13 @@ def __init__(self, field, widget):\n def toWidgetValue(self, value):\n """See interfaces.IDataConverter"""\n if value is self.field.missing_value:\n- return u\'\'\n+ return ""\n return json.dumps(value, indent=True)\n \n def toFieldValue(self, value):\n """See interfaces.IDataConverter"""\n \n- if value == u\'\':\n+ if value == "":\n return self.field.missing_value\n \n return self.field.fromUnicode(value)\ndiff --git a/plone/schema/browser/uri.py b/plone/schema/browser/uri.py\nindex 0fd13a3..b7bd6e2 100644\n--- a/plone/schema/browser/uri.py\n+++ b/plone/schema/browser/uri.py\n@@ -1,3 +1,4 @@\n+from ..interfaces import IFormLayer\n from z3c.form.browser.text import TextWidget\n from z3c.form.interfaces import IFieldWidget\n from z3c.form.interfaces import ITextWidget\n@@ -6,20 +7,18 @@\n from zope.interface import implementer\n from zope.schema.interfaces import IURI\n \n-from plone.app.z3cform.interfaces import IPloneFormLayer\n-\n \n class IURIWidget(ITextWidget):\n- """ URI Widget """\n+ """URI Widget"""\n \n \n @implementer(IURIWidget)\n class URIWidget(TextWidget):\n- klass = u\'uri-widget\'\n+ klass = "uri-widget"\n value = None\n \n \n-@adapter(IURI, IPloneFormLayer)\n+@adapter(IURI, IFormLayer)\n @implementer(IFieldWidget)\n def URIFieldWidget(field, request):\n return FieldWidget(field, URIWidget(request))\ndiff --git a/plone/schema/configure.zcml b/plone/schema/configure.zcml\nindex 3fc87cd..d84a8c4 100644\n--- a/plone/schema/configure.zcml\n+++ b/plone/schema/configure.zcml\n@@ -3,59 +3,62 @@\n xmlns:five="http://namespaces.zope.org/five"\n xmlns:i18n="http://namespaces.zope.org/i18n"\n xmlns:zcml="http://namespaces.zope.org/zcml"\n- i18n_domain="plone">\n-\n- \n- \n-\n- \n- \n- \n-\n- \n-\n- \n-\n- \n-\n- \n- \n- \n- \n- \n-\n- \n- \n- \n-\n- \n- \n- \n-\n- \n-\n- \n-\n- \n-\n- \n+ i18n_domain="plone"\n+ >\n+\n+ \n+ \n+\n+ \n+ \n+ \n+\n+ \n+\n+ \n+\n+ \n+\n+ \n+ \n+ \n+ \n+ \n+\n+ \n+ \n+ \n+\n+ \n+ \n+ \n+\n+ \n+\n+ \n+\n+ \n+\n+ \n \n \ndiff --git a/plone/schema/editor.py b/plone/schema/editor.py\nindex 1df264f..e7bd3fa 100644\n--- a/plone/schema/editor.py\n+++ b/plone/schema/editor.py\n@@ -1,30 +1,32 @@\n-from plone.schema import _\n-from plone.schema.email import Email, IEmail\n+from .email import Email\n+from .email import IEmail\n+from .jsonfield import IJSONField\n+from .jsonfield import JSONField\n from plone.schemaeditor.fields import FieldFactory\n+from zope.i18nmessageid import MessageFactory\n from zope.interface import Attribute\n from zope.schema import URI\n from zope.schema.interfaces import IURI\n-from plone.schema.jsonfield import IJSONField\n-from plone.schema.jsonfield import JSONField\n \n \n-class IURI(IURI):\n+_ = MessageFactory("plone")\n+\n \n+class IURI(IURI):\n # prevent some settings from being included in the field edit form\n- default = Attribute(\'\')\n+ default = Attribute("")\n \n \n class IEmail(IEmail):\n-\n # prevent some settings from being included in the field edit form\n- default = Attribute(\'\')\n+ default = Attribute("")\n \n \n class IJSON(IJSONField):\n # prevent some settings from being included in the field edit form\n- default = Attribute(\'\')\n+ default = Attribute("")\n \n \n-URIFactory = FieldFactory(URI, _(u\'URL\'))\n-EmailFactory = FieldFactory(Email, _(u\'Email\'))\n-JSONFactory = FieldFactory(JSONField, _(u\'JSONField\'))\n+URIFactory = FieldFactory(URI, _("URL"))\n+EmailFactory = FieldFactory(Email, _("Email"))\n+JSONFactory = FieldFactory(JSONField, _("JSONField"))\ndiff --git a/plone/schema/email.py b/plone/schema/email.py\nindex 378fb07..962f863 100644\n--- a/plone/schema/email.py\n+++ b/plone/schema/email.py\n@@ -1,19 +1,22 @@\n-from plone.schema import _\n+from zope.i18nmessageid import MessageFactory\n from zope.interface import implementer\n from zope.schema import NativeStringLine\n from zope.schema.interfaces import IFromUnicode\n from zope.schema.interfaces import INativeStringLine\n from zope.schema.interfaces import ValidationError\n+\n import re\n \n+\n+_ = MessageFactory("plone")\n+\n # Taken from http://www.regular-expressions.info/email.html\n _isemail = r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"\n _isemail = re.compile(_isemail).match\n \n \n class IEmail(INativeStringLine):\n- """A field containing an email address\n- """\n+ """A field containing an email address"""\n \n \n class InvalidEmail(ValidationError):\n@@ -22,11 +25,10 @@ class InvalidEmail(ValidationError):\n \n @implementer(IEmail, IFromUnicode)\n class Email(NativeStringLine):\n- """Email schema field\n- """\n+ """Email schema field"""\n \n def _validate(self, value):\n- super(Email, self)._validate(value)\n+ super()._validate(value)\n if _isemail(value):\n return\n \ndiff --git a/plone/schema/handler.py b/plone/schema/handler.py\nindex e743191..06bca34 100644\n--- a/plone/schema/handler.py\n+++ b/plone/schema/handler.py\n@@ -1,7 +1,8 @@\n+from .email import Email\n+from .jsonfield import JSONField\n from plone.supermodel.exportimport import BaseHandler\n from zope.schema import URI\n-from plone.schema.email import Email\n-from plone.schema.jsonfield import JSONField\n+\n \n URIHandler = BaseHandler(URI)\n EmailHandler = BaseHandler(Email)\ndiff --git a/plone/schema/interfaces.py b/plone/schema/interfaces.py\nnew file mode 100644\nindex 0000000..43671c8\n--- /dev/null\n+++ b/plone/schema/interfaces.py\n@@ -0,0 +1,5 @@\n+from z3c.form.interfaces import IFormLayer as IBaseFormLayer\n+\n+\n+class IFormLayer(IBaseFormLayer):\n+ """Request layer. Must be enabled to activate widgets"""\ndiff --git a/plone/schema/jsonfield.py b/plone/schema/jsonfield.py\nindex 1c92b9f..636f60b 100644\n--- a/plone/schema/jsonfield.py\n+++ b/plone/schema/jsonfield.py\n@@ -1,20 +1,19 @@\n-import ast\n-import json\n-import jsonschema\n-from plone.schema import _\n+from json import JSONDecodeError\n+from zope.i18nmessageid import MessageFactory\n from zope.interface import Attribute\n from zope.interface import implementer\n from zope.schema import Field\n from zope.schema._bootstrapinterfaces import WrongType\n from zope.schema.interfaces import IField\n-from zope.schema.interfaces import WrongContainedType\n from zope.schema.interfaces import IFromUnicode\n+from zope.schema.interfaces import WrongContainedType\n+\n+import ast\n+import json\n+import jsonschema\n+\n \n-try:\n- from json import JSONDecodeError\n-except ImportError:\n- # Python 2\n- JSONDecodeError = ValueError\n+_ = MessageFactory("plone")\n \n \n DEFAULT_JSON_SCHEMA = json.dumps({"type": "object", "properties": {}})\n@@ -40,10 +39,10 @@ def __init__(self, schema=DEFAULT_JSON_SCHEMA, widget=None, **kw):\n self.json_schema = json.loads(schema)\n except ValueError:\n raise WrongType\n- super(JSONField, self).__init__(**kw)\n+ super().__init__(**kw)\n \n def _validate(self, value):\n- super(JSONField, self)._validate(value)\n+ super()._validate(value)\n \n try:\n jsonschema.validate(value, self.json_schema)\ndiff --git a/plone/schema/tests/test_doctests.py b/plone/schema/tests/test_doctests.py\nindex 9e4dbb2..15fe80c 100644\n--- a/plone/schema/tests/test_doctests.py\n+++ b/plone/schema/tests/test_doctests.py\n@@ -1,23 +1,8 @@\n """ Tests\n """\n-import re\n-import six\n-import unittest\n import doctest\n-\n-class Py23DocChecker(doctest.OutputChecker):\n- def check_output(self, want, got, optionflags):\n- if six.PY2:\n- got = re.sub("u\'(.*?)\'", "\'\\\\1\'", want)\n- got = re.sub(\' encoding="utf-8"\', \'\', want)\n- # want = re.sub("b\'(.*?)\'", "\'\\\\1\'", want)\n- return doctest.OutputChecker.check_output(self, want, got, optionflags)\n+import unittest\n \n \n def test_suite():\n- return unittest.TestSuite((\n- doctest.DocTestSuite(\n- \'plone.schema.jsonfield\',\n- checker=Py23DocChecker()\n- ),\n- ))\n+ return unittest.TestSuite((doctest.DocTestSuite("plone.schema.jsonfield"),))\ndiff --git a/setup.cfg b/setup.cfg\nindex a76531e..3972628 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -5,4 +5,7 @@ ignore =\n \n \n [bdist_wheel]\n-universal = 1\n+universal = 0\n+\n+[isort]\n+profile = plone\ndiff --git a/setup.py b/setup.py\nindex 42256a7..81a67a8 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,53 +1,49 @@\n-from setuptools import setup, find_packages\n+from setuptools import find_packages\n+from setuptools import setup\n \n-version = \'1.4.1.dev0\'\n \n-long_description = open("README.rst").read() + "\\n" + \\\n- open("CHANGES.rst").read()\n+version = "2.0.0.dev0"\n+\n+long_description = open("README.rst").read() + "\\n" + open("CHANGES.rst").read()\n \n setup(\n- name=\'plone.schema\',\n+ name="plone.schema",\n version=version,\n- description=\'Plone specific extensions and fields for zope schematas\',\n+ description="Plone specific extensions and fields for zope schematas",\n long_description=long_description,\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n- "Framework :: Zope2",\n- "Framework :: Zope :: 4",\n+ "Framework :: Zope :: 5",\n "Framework :: Plone",\n- "Framework :: Plone :: 5.0",\n- "Framework :: Plone :: 5.1",\n- "Framework :: Plone :: 5.2",\n+ "Framework :: Plone :: 6.0",\n "Framework :: Plone :: Core",\n "Programming Language :: Python",\n- "Programming Language :: Python :: 2.7",\n- "Programming Language :: Python :: 3.6",\n- "Programming Language :: Python :: 3.7",\n "Programming Language :: Python :: 3.8",\n+ "Programming Language :: Python :: 3.9",\n+ "Programming Language :: Python :: 3.10",\n+ "Programming Language :: Python :: 3.11",\n "Topic :: Software Development :: Libraries :: Python Modules",\n "License :: OSI Approved :: BSD License",\n ],\n- keywords=\'plone schema\',\n- author=\'Plone Foundation\',\n- author_email=\'plone-developers@lists.sourceforge.net\',\n- url=\'https://github.com/plone/plone.schema\',\n- license=\'BSD\',\n+ keywords="schema z3cform email uri json field widget",\n+ author="Plone Foundation",\n+ author_email="plone-developers@lists.sourceforge.net",\n+ url="https://github.com/plone/plone.schema",\n+ license="BSD",\n packages=find_packages(),\n- namespace_packages=[\'plone\'],\n+ namespace_packages=["plone"],\n include_package_data=True,\n zip_safe=False,\n install_requires=[\n- \'setuptools\',\n- \'plone.app.z3cform\',\n- \'jsonschema\',\n- \'z3c.form\',\n- \'zope.component\',\n- \'zope.i18nmessageid\',\n- \'zope.interface\',\n- \'zope.schema\',\n+ "jsonschema",\n+ "setuptools",\n+ "z3c.form",\n+ "zope.deprecation",\n+ "zope.i18nmessageid",\n ],\n- extras_require={\'test\': [\n- \'six\',\n- \'plone.app.testing\'\n- ]},\n+ extras_require={\n+ "test": ["plone.app.testing"],\n+ "schemaeditor": ["plone.schemaeditor"],\n+ "supermodel": ["plone.supermodel"],\n+ },\n )\n'