diff --git a/last_commit.txt b/last_commit.txt index 26b67cf6c2..81e2e20413 100644 --- a/last_commit.txt +++ b/last_commit.txt @@ -1,10 +1,10 @@ -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-18T00:32:02+01:00 +Date: 2023-03-18T00:41:16+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/51439c756c798c5bb2bdbf1ad8cdf9f27e108b77 +Commit: https://github.com/plone/plone.app.textfield/commit/216c49d56e78de72a4c7051aa3066c1cd8b9374d Configuring with plone/meta @@ -12,142 +12,124 @@ Files changed: A .editorconfig A .meta.toml A .pre-commit-config.yaml -A news/b2d5d4a5.internal +A news/80cf330f.internal A tox.ini M pyproject.toml M setup.cfg -b'diff --git a/.editorconfig b/.editorconfig\nnew file mode 100644\nindex 0000000..b4158b8\n--- /dev/null\n+++ b/.editorconfig\n@@ -0,0 +1,39 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+#\n+# EditorConfig Configuration file, for more details see:\n+# http://EditorConfig.org\n+# EditorConfig is a convention description, that could be interpreted\n+# by multiple editors to enforce common coding conventions for specific\n+# file types\n+\n+# top-most EditorConfig file:\n+# Will ignore other EditorConfig files in Home directory or upper tree level.\n+root = true\n+\n+\n+[*] # For All Files\n+# Unix-style newlines with a newline ending every file\n+end_of_line = lf\n+insert_final_newline = true\n+trim_trailing_whitespace = true\n+# Set default charset\n+charset = utf-8\n+# Indent style default\n+indent_style = space\n+# Max Line Length - a hard line wrap, should be disabled\n+max_line_length = off\n+\n+[*.{py,cfg,ini}]\n+# 4 space indentation\n+indent_size = 4\n+\n+[*.{yml,zpt,pt,dtml,zcml}]\n+# 2 space indentation\n+indent_size = 2\n+\n+[{Makefile,.gitmodules}]\n+# Tab indentation (no size specified, but view as 4 spaces)\n+indent_style = tab\n+indent_size = unset\n+tab_width = unset\ndiff --git a/.meta.toml b/.meta.toml\nnew file mode 100644\nindex 0000000..d4a62f1\n--- /dev/null\n+++ b/.meta.toml\n@@ -0,0 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[meta]\n+template = "default"\n+commit-id = "b2d5d4a5"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..582f8ac\n--- /dev/null\n+++ b/.pre-commit-config.yaml\n@@ -0,0 +1,42 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+ci:\n+ autofix_prs: false\n+ autoupdate_schedule: monthly\n+\n+repos:\n+- repo: https://github.com/asottile/pyupgrade\n+ rev: v3.3.1\n+ hooks:\n+ - id: pyupgrade\n+ args: [--py38-plus]\n+- repo: https://github.com/pycqa/isort\n+ rev: 5.12.0\n+ hooks:\n+ - id: isort\n+- repo: https://github.com/psf/black\n+ rev: 23.1.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.2\n+ hooks:\n+ - id: zpretty\n+- repo: https://github.com/PyCQA/flake8\n+ rev: 6.0.0\n+ hooks:\n+ - id: flake8\n+- repo: https://github.com/codespell-project/codespell\n+ rev: v2.2.2\n+ hooks:\n+ - id: codespell\n+ additional_dependencies:\n+ - tomli\n+- repo: https://github.com/mgedmin/check-manifest\n+ rev: "0.49"\n+ hooks:\n+ - id: check-manifest\n+- repo: https://github.com/regebro/pyroma\n+ rev: "4.2"\n+ hooks:\n+ - id: pyroma\ndiff --git a/news/b2d5d4a5.internal b/news/b2d5d4a5.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/b2d5d4a5.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..9eb73f3 100644\n--- a/pyproject.toml\n+++ b/pyproject.toml\n@@ -1,3 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [tool.towncrier]\n filename = "CHANGES.rst"\n directory = "news/"\n@@ -18,3 +20,43 @@ showcontent = true\n directory = "bugfix"\n name = "Bug fixes:"\n showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "internal"\n+name = "Internal:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "documentation"\n+name = "Documentation:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "tests"\n+name = "Tests"\n+showcontent = true\n+\n+[tool.isort]\n+profile = "plone"\n+\n+[tool.black]\n+target-version = ["py38"]\n+\n+[tool.dependencychecker]\n+Zope = [\n+ # Zope own provided namespaces\n+ \'App\', \'OFS\', \'Products.Five\', \'Products.OFSP\', \'Products.PageTemplates\',\n+ \'Products.SiteAccess\', \'Shared\', \'Testing\', \'ZPublisher\', \'ZTUtils\',\n+ \'Zope2\', \'webdav\', \'zmi\',\n+ # Zope dependencies\n+ \'Acquisition\', \'DateTime\', \'transaction\', \'zExceptions\', \'ZODB\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.deferredimport\', \'zope.event\',\n+ \'zope.exceptions\', \'zope.globalrequest\', \'zope.i18n\', \'zope.i18nmessageid\',\n+ \'zope.interface\', \'zope.lifecycleevent\', \'zope.location\', \'zope.publisher\',\n+ \'zope.schema\', \'zope.security\', \'zope.site\', \'zope.traversing\', \'AccessControl\',\n+]\n+\'plone.base\' = [\n+ \'AccessControl\', \'Products.BTreeFolder2\', \'Products.CMFCore\',\n+ \'Products.CMFDynamicViewFTI\', \'zope.deprecation\',\n+]\n+python-dateutil = [\'dateutil\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 526aeb2..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,2 +1,23 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [bdist_wheel]\n universal = 0\n+\n+[flake8]\n+doctests = 1\n+ignore =\n+ # black takes care of line length\n+ E501,\n+ # black takes care of where to break lines\n+ W503,\n+ # black takes care of spaces within slicing (list[:])\n+ E203,\n+ # black takes care of spaces after commas\n+ E231,\n+\n+[check-manifest]\n+ignore =\n+ .editorconfig\n+ .meta.toml\n+ .pre-commit-config.yaml\n+ tox.ini\ndiff --git a/tox.ini b/tox.ini\nnew file mode 100644\nindex 0000000..74180d4\n--- /dev/null\n+++ b/tox.ini\n@@ -0,0 +1,50 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[tox]\n+envlist =\n+ format\n+ lint\n+ test\n+\n+[testenv]\n+allowlist_externals =\n+ sh\n+\n+[testenv:format]\n+description = automatically reformat code\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a pyupgrade\n+ pre-commit run -a isort\n+ pre-commit run -a black\n+ pre-commit run -a zpretty\n+\n+[testenv:lint]\n+description = run linters that will help improve the code style\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a\n+\n+[testenv:dependencies]\n+description = check if the package defines all its dependencies and generate a graph out of them\n+deps =\n+ z3c.dependencychecker==2.11\n+ pipdeptree==2.5.1\n+ graphviz # optional dependency of pipdeptree\n+commands =\n+ dependencychecker\n+ sh -c \'pipdeptree --exclude setuptools,wheel,pipdeptree,z3c.dependencychecker,zope.interface,zope.component --graph-output svg > dependencies.svg\'\n+\n+[testenv:test]\n+usedevelop = true\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --test-path={toxinidir} -s plone.app.uuid\n+extras =\n+ test\n' +b'diff --git a/.editorconfig b/.editorconfig\nnew file mode 100644\nindex 0000000..b4158b8\n--- /dev/null\n+++ b/.editorconfig\n@@ -0,0 +1,39 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+#\n+# EditorConfig Configuration file, for more details see:\n+# http://EditorConfig.org\n+# EditorConfig is a convention description, that could be interpreted\n+# by multiple editors to enforce common coding conventions for specific\n+# file types\n+\n+# top-most EditorConfig file:\n+# Will ignore other EditorConfig files in Home directory or upper tree level.\n+root = true\n+\n+\n+[*] # For All Files\n+# Unix-style newlines with a newline ending every file\n+end_of_line = lf\n+insert_final_newline = true\n+trim_trailing_whitespace = true\n+# Set default charset\n+charset = utf-8\n+# Indent style default\n+indent_style = space\n+# Max Line Length - a hard line wrap, should be disabled\n+max_line_length = off\n+\n+[*.{py,cfg,ini}]\n+# 4 space indentation\n+indent_size = 4\n+\n+[*.{yml,zpt,pt,dtml,zcml}]\n+# 2 space indentation\n+indent_size = 2\n+\n+[{Makefile,.gitmodules}]\n+# Tab indentation (no size specified, but view as 4 spaces)\n+indent_style = tab\n+indent_size = unset\n+tab_width = unset\ndiff --git a/.meta.toml b/.meta.toml\nnew file mode 100644\nindex 0000000..697a54c\n--- /dev/null\n+++ b/.meta.toml\n@@ -0,0 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[meta]\n+template = "default"\n+commit-id = "80cf330f"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..582f8ac\n--- /dev/null\n+++ b/.pre-commit-config.yaml\n@@ -0,0 +1,42 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+ci:\n+ autofix_prs: false\n+ autoupdate_schedule: monthly\n+\n+repos:\n+- repo: https://github.com/asottile/pyupgrade\n+ rev: v3.3.1\n+ hooks:\n+ - id: pyupgrade\n+ args: [--py38-plus]\n+- repo: https://github.com/pycqa/isort\n+ rev: 5.12.0\n+ hooks:\n+ - id: isort\n+- repo: https://github.com/psf/black\n+ rev: 23.1.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.2\n+ hooks:\n+ - id: zpretty\n+- repo: https://github.com/PyCQA/flake8\n+ rev: 6.0.0\n+ hooks:\n+ - id: flake8\n+- repo: https://github.com/codespell-project/codespell\n+ rev: v2.2.2\n+ hooks:\n+ - id: codespell\n+ additional_dependencies:\n+ - tomli\n+- repo: https://github.com/mgedmin/check-manifest\n+ rev: "0.49"\n+ hooks:\n+ - id: check-manifest\n+- repo: https://github.com/regebro/pyroma\n+ rev: "4.2"\n+ hooks:\n+ - id: pyroma\ndiff --git a/news/80cf330f.internal b/news/80cf330f.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/80cf330f.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..9eb73f3 100644\n--- a/pyproject.toml\n+++ b/pyproject.toml\n@@ -1,3 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [tool.towncrier]\n filename = "CHANGES.rst"\n directory = "news/"\n@@ -18,3 +20,43 @@ showcontent = true\n directory = "bugfix"\n name = "Bug fixes:"\n showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "internal"\n+name = "Internal:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "documentation"\n+name = "Documentation:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "tests"\n+name = "Tests"\n+showcontent = true\n+\n+[tool.isort]\n+profile = "plone"\n+\n+[tool.black]\n+target-version = ["py38"]\n+\n+[tool.dependencychecker]\n+Zope = [\n+ # Zope own provided namespaces\n+ \'App\', \'OFS\', \'Products.Five\', \'Products.OFSP\', \'Products.PageTemplates\',\n+ \'Products.SiteAccess\', \'Shared\', \'Testing\', \'ZPublisher\', \'ZTUtils\',\n+ \'Zope2\', \'webdav\', \'zmi\',\n+ # Zope dependencies\n+ \'Acquisition\', \'DateTime\', \'transaction\', \'zExceptions\', \'ZODB\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.deferredimport\', \'zope.event\',\n+ \'zope.exceptions\', \'zope.globalrequest\', \'zope.i18n\', \'zope.i18nmessageid\',\n+ \'zope.interface\', \'zope.lifecycleevent\', \'zope.location\', \'zope.publisher\',\n+ \'zope.schema\', \'zope.security\', \'zope.site\', \'zope.traversing\', \'AccessControl\',\n+]\n+\'plone.base\' = [\n+ \'AccessControl\', \'Products.BTreeFolder2\', \'Products.CMFCore\',\n+ \'Products.CMFDynamicViewFTI\', \'zope.deprecation\',\n+]\n+python-dateutil = [\'dateutil\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 000ba69..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,15 +1,23 @@\n-[check-manifest]\n-ignore =\n- *.cfg\n- bootstrap.py\n-\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [bdist_wheel]\n universal = 0\n \n-[isort]\n-# black compatible Plone isort rules:\n-profile = black\n-force_alphabetical_sort = True\n-force_single_line = True\n-lines_after_imports = 2\n+[flake8]\n+doctests = 1\n+ignore =\n+ # black takes care of line length\n+ E501,\n+ # black takes care of where to break lines\n+ W503,\n+ # black takes care of spaces within slicing (list[:])\n+ E203,\n+ # black takes care of spaces after commas\n+ E231,\n \n+[check-manifest]\n+ignore =\n+ .editorconfig\n+ .meta.toml\n+ .pre-commit-config.yaml\n+ tox.ini\ndiff --git a/tox.ini b/tox.ini\nnew file mode 100644\nindex 0000000..eca8603\n--- /dev/null\n+++ b/tox.ini\n@@ -0,0 +1,50 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[tox]\n+envlist =\n+ format\n+ lint\n+ test\n+\n+[testenv]\n+allowlist_externals =\n+ sh\n+\n+[testenv:format]\n+description = automatically reformat code\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a pyupgrade\n+ pre-commit run -a isort\n+ pre-commit run -a black\n+ pre-commit run -a zpretty\n+\n+[testenv:lint]\n+description = run linters that will help improve the code style\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a\n+\n+[testenv:dependencies]\n+description = check if the package defines all its dependencies and generate a graph out of them\n+deps =\n+ z3c.dependencychecker==2.11\n+ pipdeptree==2.5.1\n+ graphviz # optional dependency of pipdeptree\n+commands =\n+ dependencychecker\n+ sh -c \'pipdeptree --exclude setuptools,wheel,pipdeptree,z3c.dependencychecker,zope.interface,zope.component --graph-output svg > dependencies.svg\'\n+\n+[testenv:test]\n+usedevelop = true\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --test-path={toxinidir} -s plone.app.textfield\n+extras =\n+ test\n' -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-18T00:32:41+01:00 +Date: 2023-03-18T00:53:01+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/7f0b8970a28d62b1d8cbb468d1aa0a5f57774f7b +Commit: https://github.com/plone/plone.app.textfield/commit/8b2189e38b76475b03afd853f155ebcd48b761fa -chore: pyupgrade - -Files changed: -M plone/__init__.py -M plone/app/__init__.py -M plone/app/uuid/browser.py -M plone/app/uuid/indexer.py -M plone/app/uuid/testing.py -M plone/app/uuid/tests.py -M plone/app/uuid/utils.py -M setup.py - -b'diff --git a/plone/__init__.py b/plone/__init__.py\nindex 68c04af..de40ea7 100644\n--- a/plone/__init__.py\n+++ b/plone/__init__.py\n@@ -1,2 +1 @@\n-# -*- coding: utf-8 -*-\n __import__(\'pkg_resources\').declare_namespace(__name__)\ndiff --git a/plone/app/__init__.py b/plone/app/__init__.py\nindex 68c04af..de40ea7 100644\n--- a/plone/app/__init__.py\n+++ b/plone/app/__init__.py\n@@ -1,2 +1 @@\n-# -*- coding: utf-8 -*-\n __import__(\'pkg_resources\').declare_namespace(__name__)\ndiff --git a/plone/app/uuid/browser.py b/plone/app/uuid/browser.py\nindex 0f1bfec..897d922 100644\n--- a/plone/app/uuid/browser.py\n+++ b/plone/app/uuid/browser.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.app.uuid.utils import uuidToURL\n from zope.interface import implementer\n from zope.publisher.browser import BrowserView\n@@ -29,4 +28,4 @@ def __call__(self):\n raise NotFound(self, self.uuid)\n \n self.request.response.redirect(url)\n- return u\'\'\n+ return \'\'\ndiff --git a/plone/app/uuid/indexer.py b/plone/app/uuid/indexer.py\nindex ed7be46..7166a4f 100644\n--- a/plone/app/uuid/indexer.py\n+++ b/plone/app/uuid/indexer.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.indexer import indexer\n from plone.uuid.interfaces import IUUID\n from plone.uuid.interfaces import IUUIDAware\ndiff --git a/plone/app/uuid/testing.py b/plone/app/uuid/testing.py\nindex f3cc5f2..54a0501 100644\n--- a/plone/app/uuid/testing.py\n+++ b/plone/app/uuid/testing.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.app.testing import FunctionalTesting\n from plone.app.testing import IntegrationTesting\n from plone.app.testing import PLONE_FIXTURE\ndiff --git a/plone/app/uuid/tests.py b/plone/app/uuid/tests.py\nindex 4bf62b8..ffac569 100644\n--- a/plone/app/uuid/tests.py\n+++ b/plone/app/uuid/tests.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from AccessControl import Unauthorized\n from plone.app.testing import logout\n from plone.app.testing import setRoles\n@@ -88,12 +87,12 @@ def test_speed(self):\n if total:\n report = True\n total = int(total)\n- print("Creating {} documents...".format(total))\n+ print(f"Creating {total} documents...")\n else:\n report = False\n total = 40\n for i in range(total):\n- doc_id = portal.invokeFactory(\'Document\', \'d{}\'.format(i))\n+ doc_id = portal.invokeFactory(\'Document\', f\'d{i}\')\n doc = portal[doc_id]\n uuids[IUUID(doc)] = {\n \'path\': \'/\'.join(doc.getPhysicalPath()),\n@@ -102,7 +101,7 @@ def test_speed(self):\n }\n end = time.time()\n if report:\n- print("Time taken to create {} items: {}".format(total, end - start))\n+ print(f"Time taken to create {total} items: {end - start}")\n \n self.assertEqual(len(uuids), total)\n start = time.time()\n@@ -110,28 +109,28 @@ def test_speed(self):\n self.assertEqual(info[\'path\'], uuidToPhysicalPath(uuid))\n end = time.time()\n if report:\n- print("Time taken for uuidToPhysicalPath: {}".format(end - start))\n+ print(f"Time taken for uuidToPhysicalPath: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n self.assertEqual(info[\'url\'], uuidToURL(uuid))\n end = time.time()\n if report:\n- print("Time taken for uuidToURL: {}".format(end - start))\n+ print(f"Time taken for uuidToURL: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n self.assertEqual(info[\'obj\'], aq_base(uuidToObject(uuid)))\n end = time.time()\n if report:\n- print("Time taken for uuidToObject: {}".format(end - start))\n+ print(f"Time taken for uuidToObject: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n self.assertEqual(info[\'path\'], uuidToCatalogBrain(uuid).getPath())\n end = time.time()\n if report:\n- print("Time taken for uuidToCatalogBrain: {}".format(end - start))\n+ print(f"Time taken for uuidToCatalogBrain: {end - start}")\n \n def test_uuidToURL(self):\n from plone.uuid.interfaces import IUUID\n@@ -286,10 +285,10 @@ def test_uuid_view(self):\n browser = Browser(app)\n browser.addHeader(\n \'Authorization\',\n- \'Basic {0}:{1}\'.format(TEST_USER_ID, TEST_USER_PASSWORD, )\n+ f\'Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}\'\n )\n \n- browser.open(\'{0}/@@uuid\'.format(d1.absolute_url()))\n+ browser.open(f\'{d1.absolute_url()}/@@uuid\')\n self.assertEqual(uuid, browser.contents)\n \n def test_redirect_to_uuid_view(self):\n@@ -311,7 +310,7 @@ def test_redirect_to_uuid_view(self):\n browser = Browser(app)\n browser.addHeader(\n \'Authorization\',\n- \'Basic {0}:{1}\'.format(TEST_USER_ID, TEST_USER_PASSWORD,)\n+ f\'Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}\'\n )\n \n url = \'{0}/@@redirect-to-uuid/{1}\'\n@@ -330,10 +329,10 @@ def test_redirect_to_uuid_invalid_uuid(self):\n browser.handleErrors = False\n browser.addHeader(\n \'Authorization\',\n- \'Basic {0}:{1}\'.format(TEST_USER_ID, TEST_USER_PASSWORD, )\n+ f\'Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}\'\n )\n \n- url = \'{0}/@@redirect-to-uuid/gibberish\'.format(portal.absolute_url())\n+ url = f\'{portal.absolute_url()}/@@redirect-to-uuid/gibberish\'\n from zExceptions import NotFound\n with self.assertRaises(NotFound):\n browser.open(url)\ndiff --git a/plone/app/uuid/utils.py b/plone/app/uuid/utils.py\nindex 8201167..c188884 100644\n--- a/plone/app/uuid/utils.py\n+++ b/plone/app/uuid/utils.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from AccessControl import Unauthorized\n from Products.CMFCore.indexing import processQueue\n from Products.CMFCore.utils import getToolByName\ndiff --git a/setup.py b/setup.py\nindex ccb965e..b3c6df2 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,10 +1,9 @@\n-# -*- coding: utf-8 -*-\n from setuptools import find_packages\n from setuptools import setup\n \n version = \'2.2.2.dev0\'\n \n-long_description = \'{0}\\n{1}\'.format(\n+long_description = \'{}\\n{}\'.format(\n open(\'README.rst\').read(),\n open(\'CHANGES.rst\').read(),\n )\n' - -Repository: plone.app.uuid - - -Branch: refs/heads/master -Date: 2023-03-18T00:32:59+01:00 -Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/59d80a81f0108bdd4dbb0f8fbcf81d1cc2dac892 - -chore: isort +chore: black Files changed: -M plone/app/uuid/tests.py -M setup.py +M plone/app/textfield/__init__.py -b'diff --git a/plone/app/uuid/tests.py b/plone/app/uuid/tests.py\nindex ffac569..52c9436 100644\n--- a/plone/app/uuid/tests.py\n+++ b/plone/app/uuid/tests.py\n@@ -3,9 +3,9 @@\n from plone.app.testing import setRoles\n from plone.app.testing import TEST_USER_ID\n from plone.app.testing import TEST_USER_PASSWORD\n-from plone.testing.zope import Browser\n from plone.app.uuid.testing import PLONE_APP_UUID_FUNCTIONAL_TESTING\n from plone.app.uuid.testing import PLONE_APP_UUID_INTEGRATION_TESTING\n+from plone.testing.zope import Browser\n \n import os\n import time\n@@ -49,8 +49,8 @@ def test_search(self):\n self.assertEqual(\'/\'.join(d1.getPhysicalPath()), results[0].getPath())\n \n def test_uuidToPhysicalPath(self):\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToPhysicalPath\n+ from plone.uuid.interfaces import IUUID\n \n portal = self.layer[\'portal\']\n setRoles(portal, TEST_USER_ID, [\'Manager\'])\n@@ -69,11 +69,11 @@ def test_speed(self):\n # I updated some of the utility functions to be a bit faster.\n # In this function you can check the speed.\n from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n+ from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.app.uuid.utils import uuidToObject\n from plone.app.uuid.utils import uuidToPhysicalPath\n from plone.app.uuid.utils import uuidToURL\n- from plone.app.uuid.utils import uuidToObject\n- from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.uuid.interfaces import IUUID\n \n portal = self.layer[\'portal\']\n setRoles(portal, TEST_USER_ID, [\'Manager\'])\n@@ -133,8 +133,8 @@ def test_speed(self):\n print(f"Time taken for uuidToCatalogBrain: {end - start}")\n \n def test_uuidToURL(self):\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToURL\n+ from plone.uuid.interfaces import IUUID\n \n portal = self.layer[\'portal\']\n setRoles(portal, TEST_USER_ID, [\'Manager\'])\n@@ -150,8 +150,8 @@ def test_uuidToURL(self):\n \n def test_uuidToObject(self):\n from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToObject\n+ from plone.uuid.interfaces import IUUID\n \n portal = self.layer[\'portal\']\n setRoles(portal, TEST_USER_ID, [\'Manager\'])\n@@ -167,8 +167,8 @@ def test_uuidToObject(self):\n \n def test_uuidToCatalogBrain(self):\n from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.uuid.interfaces import IUUID\n \n portal = self.layer[\'portal\']\n setRoles(portal, TEST_USER_ID, [\'Manager\'])\n@@ -196,11 +196,11 @@ def test_access_private_published(self):\n \'restricted/unrestricted=True/False\'.\n """\n from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n+ from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.app.uuid.utils import uuidToObject\n from plone.app.uuid.utils import uuidToPhysicalPath\n from plone.app.uuid.utils import uuidToURL\n- from plone.app.uuid.utils import uuidToObject\n- from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.uuid.interfaces import IUUID\n \n portal = self.layer[\'portal\']\n setRoles(portal, TEST_USER_ID, [\'Manager\'])\ndiff --git a/setup.py b/setup.py\nindex b3c6df2..9b204b2 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,6 +1,7 @@\n from setuptools import find_packages\n from setuptools import setup\n \n+\n version = \'2.2.2.dev0\'\n \n long_description = \'{}\\n{}\'.format(\n' +b'diff --git a/plone/app/textfield/__init__.py b/plone/app/textfield/__init__.py\nindex e8e39e0..18a8735 100644\n--- a/plone/app/textfield/__init__.py\n+++ b/plone/app/textfield/__init__.py\n@@ -29,7 +29,7 @@ def __init__(\n allowed_mime_types=None,\n max_length=None,\n schema=IRichTextValue,\n- **kw\n+ **kw,\n ):\n self.default_mime_type = default_mime_type\n self.output_mime_type = output_mime_type\n' -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-18T00:33:47+01:00 +Date: 2023-03-18T00:53:28+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/abb3e8fdd60bf48cb37907102da416e3f7c534cf +Commit: https://github.com/plone/plone.app.textfield/commit/18305899b775b01aef375e77a84edd5aa7910dd8 -chore: black +chore: zpretty ZCML Files changed: -M plone/__init__.py -M plone/app/__init__.py -M plone/app/uuid/browser.py -M plone/app/uuid/testing.py -M plone/app/uuid/tests.py -M plone/app/uuid/utils.py -M setup.py +M plone/app/textfield/browser.zcml +M plone/app/textfield/configure.zcml +M plone/app/textfield/editor.zcml +M plone/app/textfield/handler.zcml +M plone/app/textfield/marshaler.zcml +M plone/app/textfield/transform.zcml +M plone/app/textfield/widget.zcml -b'diff --git a/plone/__init__.py b/plone/__init__.py\nindex de40ea7..5284146 100644\n--- a/plone/__init__.py\n+++ b/plone/__init__.py\n@@ -1 +1 @@\n-__import__(\'pkg_resources\').declare_namespace(__name__)\n+__import__("pkg_resources").declare_namespace(__name__)\ndiff --git a/plone/app/__init__.py b/plone/app/__init__.py\nindex de40ea7..5284146 100644\n--- a/plone/app/__init__.py\n+++ b/plone/app/__init__.py\n@@ -1 +1 @@\n-__import__(\'pkg_resources\').declare_namespace(__name__)\n+__import__("pkg_resources").declare_namespace(__name__)\ndiff --git a/plone/app/uuid/browser.py b/plone/app/uuid/browser.py\nindex 897d922..2ffa087 100644\n--- a/plone/app/uuid/browser.py\n+++ b/plone/app/uuid/browser.py\n@@ -20,7 +20,7 @@ def publishTraverse(self, request, name):\n def __call__(self):\n if self.uuid is None:\n raise KeyError(\n- \'No UUID given in sub-path. Use .../@@redirect-to-uuid/\'\n+ "No UUID given in sub-path. Use .../@@redirect-to-uuid/"\n )\n \n url = uuidToURL(self.uuid)\n@@ -28,4 +28,4 @@ def __call__(self):\n raise NotFound(self, self.uuid)\n \n self.request.response.redirect(url)\n- return \'\'\n+ return ""\ndiff --git a/plone/app/uuid/testing.py b/plone/app/uuid/testing.py\nindex 54a0501..e05804f 100644\n--- a/plone/app/uuid/testing.py\n+++ b/plone/app/uuid/testing.py\n@@ -8,31 +8,30 @@\n \n \n class PloneAppUUID(PloneSandboxLayer):\n-\n defaultBases = (PLONE_FIXTURE,)\n \n def setUpZope(self, app, configurationContext):\n # Load ZCML\n import plone.app.uuid\n- xmlconfig.file(\'configure.zcml\', plone.app.uuid,\n- context=configurationContext)\n+\n+ xmlconfig.file("configure.zcml", plone.app.uuid, context=configurationContext)\n \n def setUpPloneSite(self, portal):\n- types_tool = getToolByName(portal, \'portal_types\')\n+ types_tool = getToolByName(portal, "portal_types")\n # This test should work for both Plone 4.3 (with ATContentTypes) and\n # Plone 5.x (without any types). Therefore we can not make any\n # assumptions about an existing Document type.\n- if \'Document\' not in types_tool.objectIds():\n- fti = DexterityFTI(\'Document\')\n- types_tool._setObject(\'Document\', fti)\n+ if "Document" not in types_tool.objectIds():\n+ fti = DexterityFTI("Document")\n+ types_tool._setObject("Document", fti)\n \n \n PLONE_APP_UUID_FIXTURE = PloneAppUUID()\n PLONE_APP_UUID_INTEGRATION_TESTING = IntegrationTesting(\n- bases=(PLONE_APP_UUID_FIXTURE, ),\n- name=\'plone.app.uuid:Integration\',\n+ bases=(PLONE_APP_UUID_FIXTURE,),\n+ name="plone.app.uuid:Integration",\n )\n PLONE_APP_UUID_FUNCTIONAL_TESTING = FunctionalTesting(\n- bases=(PLONE_APP_UUID_FIXTURE, ),\n- name=\'plone.app.uuid:Functional\',\n+ bases=(PLONE_APP_UUID_FIXTURE,),\n+ name="plone.app.uuid:Functional",\n )\ndiff --git a/plone/app/uuid/tests.py b/plone/app/uuid/tests.py\nindex 52c9436..e86757f 100644\n--- a/plone/app/uuid/tests.py\n+++ b/plone/app/uuid/tests.py\n@@ -19,12 +19,12 @@ class IntegrationTestCase(unittest.TestCase):\n def test_assignment(self):\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n+ portal.invokeFactory("Document", "d1")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n self.assertTrue(isinstance(uuid, str))\n@@ -32,38 +32,37 @@ def test_assignment(self):\n def test_search(self):\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n- catalog = portal[\'portal_catalog\']\n+ catalog = portal["portal_catalog"]\n results = catalog(UID=uuid)\n \n self.assertEqual(1, len(results))\n self.assertEqual(uuid, results[0].UID)\n- self.assertEqual(\'/\'.join(d1.getPhysicalPath()), results[0].getPath())\n+ self.assertEqual("/".join(d1.getPhysicalPath()), results[0].getPath())\n \n def test_uuidToPhysicalPath(self):\n from plone.app.uuid.utils import uuidToPhysicalPath\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n- self.assertEqual(\'/\'.join(d1.getPhysicalPath()),\n- uuidToPhysicalPath(uuid))\n- self.assertIsNone(uuidToPhysicalPath(\'unknown\'))\n+ self.assertEqual("/".join(d1.getPhysicalPath()), uuidToPhysicalPath(uuid))\n+ self.assertIsNone(uuidToPhysicalPath("unknown"))\n \n def test_speed(self):\n # I updated some of the utility functions to be a bit faster.\n@@ -75,8 +74,8 @@ def test_speed(self):\n from plone.app.uuid.utils import uuidToURL\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n start = time.time()\n uuids = {}\n@@ -92,12 +91,12 @@ def test_speed(self):\n report = False\n total = 40\n for i in range(total):\n- doc_id = portal.invokeFactory(\'Document\', f\'d{i}\')\n+ doc_id = portal.invokeFactory("Document", f"d{i}")\n doc = portal[doc_id]\n uuids[IUUID(doc)] = {\n- \'path\': \'/\'.join(doc.getPhysicalPath()),\n- \'url\': doc.absolute_url(),\n- \'obj\': aq_base(doc),\n+ "path": "/".join(doc.getPhysicalPath()),\n+ "url": doc.absolute_url(),\n+ "obj": aq_base(doc),\n }\n end = time.time()\n if report:\n@@ -106,28 +105,28 @@ def test_speed(self):\n self.assertEqual(len(uuids), total)\n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'path\'], uuidToPhysicalPath(uuid))\n+ self.assertEqual(info["path"], uuidToPhysicalPath(uuid))\n end = time.time()\n if report:\n print(f"Time taken for uuidToPhysicalPath: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'url\'], uuidToURL(uuid))\n+ self.assertEqual(info["url"], uuidToURL(uuid))\n end = time.time()\n if report:\n print(f"Time taken for uuidToURL: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'obj\'], aq_base(uuidToObject(uuid)))\n+ self.assertEqual(info["obj"], aq_base(uuidToObject(uuid)))\n end = time.time()\n if report:\n print(f"Time taken for uuidToObject: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'path\'], uuidToCatalogBrain(uuid).getPath())\n+ self.assertEqual(info["path"], uuidToCatalogBrain(uuid).getPath())\n end = time.time()\n if report:\n print(f"Time taken for uuidToCatalogBrain: {end - start}")\n@@ -136,51 +135,53 @@ def test_uuidToURL(self):\n from plone.app.uuid.utils import uuidToURL\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n self.assertEqual(d1.absolute_url(), uuidToURL(uuid))\n- self.assertIsNone(uuidToURL(\'unknown\'))\n+ self.assertIsNone(uuidToURL("unknown"))\n \n def test_uuidToObject(self):\n from Acquisition import aq_base\n from plone.app.uuid.utils import uuidToObject\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n self.assertEqual(aq_base(d1), aq_base(uuidToObject(uuid)))\n- self.assertIsNone(uuidToObject(\'unknown\'))\n+ self.assertIsNone(uuidToObject("unknown"))\n \n def test_uuidToCatalogBrain(self):\n from Acquisition import aq_base\n from plone.app.uuid.utils import uuidToCatalogBrain\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n- self.assertEqual(\'/\'.join(d1.getPhysicalPath()), uuidToCatalogBrain(uuid).getPath())\n- self.assertIsNone(uuidToCatalogBrain(\'unknown\'))\n+ self.assertEqual(\n+ "/".join(d1.getPhysicalPath()), uuidToCatalogBrain(uuid).getPath()\n+ )\n+ self.assertIsNone(uuidToCatalogBrain("unknown"))\n \n def test_access_private_published(self):\n """Do the functions return both private and published items?\n@@ -202,29 +203,29 @@ def test_access_private_published(self):\n from plone.app.uuid.utils import uuidToURL\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n wftool = portal.portal_workflow\n wftool.setDefaultChain("simple_publication_workflow")\n \n # Create private folder.\n- portal.invokeFactory(\'Folder\', \'private\')\n+ portal.invokeFactory("Folder", "private")\n private = portal.private\n private_url = private.absolute_url()\n private_uuid = IUUID(private)\n- private_path = \'/\'.join(private.getPhysicalPath())\n+ private_path = "/".join(private.getPhysicalPath())\n \n # Create public document in private folder.\n- private.invokeFactory(\'Document\', \'published\')\n- wftool.doActionFor(portal.private.published, \'publish\')\n+ private.invokeFactory("Document", "published")\n+ wftool.doActionFor(portal.private.published, "publish")\n published = private.published\n published_url = published.absolute_url()\n published_uuid = IUUID(published)\n- published_path = \'/\'.join(published.getPhysicalPath())\n+ published_path = "/".join(published.getPhysicalPath())\n \n # Check that the review states are what we expect.\n- self.assertEqual(wftool.getInfoFor(private, \'review_state\'), \'private\')\n- self.assertEqual(wftool.getInfoFor(published, \'review_state\'), \'published\')\n+ self.assertEqual(wftool.getInfoFor(private, "review_state"), "private")\n+ self.assertEqual(wftool.getInfoFor(published, "review_state"), "published")\n \n # The test user can obviously see the published item.\n self.assertEqual(published_path, uuidToPhysicalPath(published_uuid))\n@@ -244,7 +245,6 @@ def test_access_private_published(self):\n self.assertEqual(published_url, uuidToURL(published_uuid))\n self.assertEqual(published_path, uuidToCatalogBrain(published_uuid).getPath())\n self.assertEqual(aq_base(published), aq_base(uuidToObject(published_uuid)))\n- \n \n # Currently, anonymous can also see the private item with most functions.\n # See the docstring of this test method.\n@@ -263,76 +263,71 @@ def test_access_private_published(self):\n \n \n class FunctionalTestCase(unittest.TestCase):\n-\n layer = PLONE_APP_UUID_FUNCTIONAL_TESTING\n \n def test_uuid_view(self):\n-\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- app = self.layer[\'app\']\n+ portal = self.layer["portal"]\n+ app = self.layer["app"]\n \n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n+ portal.invokeFactory("Document", "d1")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n transaction.commit()\n \n browser = Browser(app)\n- browser.addHeader(\n- \'Authorization\',\n- f\'Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}\'\n- )\n+ browser.addHeader("Authorization", f"Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}")\n \n- browser.open(f\'{d1.absolute_url()}/@@uuid\')\n+ browser.open(f"{d1.absolute_url()}/@@uuid")\n self.assertEqual(uuid, browser.contents)\n \n def test_redirect_to_uuid_view(self):\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- app = self.layer[\'app\']\n+ portal = self.layer["portal"]\n+ app = self.layer["app"]\n \n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n transaction.commit()\n \n browser = Browser(app)\n- browser.addHeader(\n- \'Authorization\',\n- f\'Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}\'\n+ browser.addHeader("Authorization", f"Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}")\n+\n+ url = "{0}/@@redirect-to-uuid/{1}"\n+ browser.open(\n+ url.format(\n+ portal.absolute_url(),\n+ uuid,\n+ )\n )\n-\n- url = \'{0}/@@redirect-to-uuid/{1}\'\n- browser.open(url.format(portal.absolute_url(), uuid,))\n self.assertEqual(d1.absolute_url(), browser.url)\n \n def test_redirect_to_uuid_invalid_uuid(self):\n- portal = self.layer[\'portal\']\n- app = self.layer[\'app\']\n+ portal = self.layer["portal"]\n+ app = self.layer["app"]\n \n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n transaction.commit()\n \n browser = Browser(app)\n browser.handleErrors = False\n- browser.addHeader(\n- \'Authorization\',\n- f\'Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}\'\n- )\n+ browser.addHeader("Authorization", f"Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}")\n \n- url = f\'{portal.absolute_url()}/@@redirect-to-uuid/gibberish\'\n+ url = f"{portal.absolute_url()}/@@redirect-to-uuid/gibberish"\n from zExceptions import NotFound\n+\n with self.assertRaises(NotFound):\n browser.open(url)\ndiff --git a/plone/app/uuid/utils.py b/plone/app/uuid/utils.py\nindex c188884..7da7279 100644\n--- a/plone/app/uuid/utils.py\n+++ b/plone/app/uuid/utils.py\n@@ -21,7 +21,7 @@ def _catalog():\n if request is not None:\n request._catalog = None\n return\n- catalog = getToolByName(site, \'portal_catalog\', None)\n+ catalog = getToolByName(site, "portal_catalog", None)\n if request is not None:\n request._catalog = catalog\n return catalog\n@@ -74,7 +74,7 @@ def uuidToURL(uuid):\n return brain.getURL()\n \n \n-def uuidToObject(uuid, unrestricted = False):\n+def uuidToObject(uuid, unrestricted=False):\n """Given a UUID, attempt to return a content object. Will return\n None if the UUID can\'t be found.\n \ndiff --git a/setup.py b/setup.py\nindex 9b204b2..f9e336d 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -2,52 +2,55 @@\n from setuptools import setup\n \n \n-version = \'2.2.2.dev0\'\n+version = "2.2.2.dev0"\n \n-long_description = \'{}\\n{}\'.format(\n- open(\'README.rst\').read(),\n- open(\'CHANGES.rst\').read(),\n+long_description = "{}\\n{}".format(\n+ open("README.rst").read(),\n+ open("CHANGES.rst").read(),\n )\n \n setup(\n- name=\'plone.app.uuid\',\n+ name="plone.app.uuid",\n version=version,\n- description=\'Plone integration for the basic plone.uuid package\',\n+ description="Plone integration for the basic plone.uuid package",\n long_description=long_description,\n # Get more strings from\n # https://pypi.org/classifiers/\n classifiers=[\n- \'Development Status :: 5 - Production/Stable\',\n- \'Framework :: Plone\',\n- \'Framework :: Plone :: 6.0\',\n- \'Framework :: Plone :: Core\',\n+ "Development Status :: 5 - Production/Stable",\n+ "Framework :: Plone",\n+ "Framework :: Plone :: 6.0",\n+ "Framework :: Plone :: Core",\n "License :: OSI Approved :: GNU General Public License (GPL)",\n- \'Programming Language :: Python\',\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+ "Programming Language :: Python",\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 ],\n- keywords=\'plone uuid\',\n- author=\'Martin Aspeli\',\n- author_email=\'optilude@gmail.com\',\n- url=\'http://plone.org\',\n- license=\'GPL\',\n+ keywords="plone uuid",\n+ author="Martin Aspeli",\n+ author_email="optilude@gmail.com",\n+ url="http://plone.org",\n+ license="GPL",\n packages=find_packages(),\n- namespace_packages=[\'plone\', \'plone.app\', ],\n+ namespace_packages=[\n+ "plone",\n+ "plone.app",\n+ ],\n include_package_data=True,\n zip_safe=False,\n install_requires=[\n- \'setuptools\',\n- \'plone.uuid\',\n- \'plone.indexer\',\n- \'zope.publisher\',\n- \'zope.interface\',\n+ "setuptools",\n+ "plone.uuid",\n+ "plone.indexer",\n+ "zope.publisher",\n+ "zope.interface",\n ],\n extras_require={\n- \'test\': [\n- \'plone.dexterity\',\n- \'plone.app.testing\',\n+ "test": [\n+ "plone.dexterity",\n+ "plone.app.testing",\n ]\n },\n entry_points="""\n' +b'diff --git a/plone/app/textfield/browser.zcml b/plone/app/textfield/browser.zcml\nindex 63727c8..1f20f39 100644\n--- a/plone/app/textfield/browser.zcml\n+++ b/plone/app/textfield/browser.zcml\n@@ -1,14 +1,15 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \n \n \ndiff --git a/plone/app/textfield/configure.zcml b/plone/app/textfield/configure.zcml\nindex e3bb0f6..eee27de 100644\n--- a/plone/app/textfield/configure.zcml\n+++ b/plone/app/textfield/configure.zcml\n@@ -1,31 +1,37 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n- \n \n \n- \n \n \n- \n \n \n- \n \n \n- \n \n \ndiff --git a/plone/app/textfield/editor.zcml b/plone/app/textfield/editor.zcml\nindex e5f54d6..8ea3a6d 100644\n--- a/plone/app/textfield/editor.zcml\n+++ b/plone/app/textfield/editor.zcml\n@@ -1,6 +1,7 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \ndiff --git a/plone/app/textfield/handler.zcml b/plone/app/textfield/handler.zcml\nindex d8a15c4..8a99d37 100644\n--- a/plone/app/textfield/handler.zcml\n+++ b/plone/app/textfield/handler.zcml\n@@ -1,14 +1,13 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \n- \n+ \n \n \ndiff --git a/plone/app/textfield/marshaler.zcml b/plone/app/textfield/marshaler.zcml\nindex 06f20c8..f014b26 100644\n--- a/plone/app/textfield/marshaler.zcml\n+++ b/plone/app/textfield/marshaler.zcml\n@@ -1,6 +1,7 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \ndiff --git a/plone/app/textfield/transform.zcml b/plone/app/textfield/transform.zcml\nindex f1d6cc1..82533f7 100644\n--- a/plone/app/textfield/transform.zcml\n+++ b/plone/app/textfield/transform.zcml\n@@ -1,6 +1,7 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n+ xmlns:zcml="http://namespaces.zope.org/zcml"\n+ i18n_domain="plone.app.textfield"\n+ >\n \n+ file="meta.zcml"\n+ />\n \n \n \n \n+ interface=".widget.IRichTextWidget"\n+ />\n \n \n+ />\n \n+ />\n \n \n \n \n+ widget="z3c.form.interfaces.ITextAreaWidget"\n+ template="widget_textarea_display.pt"\n+ layer="plone.app.z3cform.interfaces.IPloneFormLayer"\n+ mode="display"\n+ />\n \n+ widget=".widget.IRichTextWidget"\n+ template="widget_display.pt"\n+ layer="plone.app.z3cform.interfaces.IPloneFormLayer"\n+ mode="display"\n+ />\n \n \n' -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-18T00:34:00+01:00 +Date: 2023-03-18T00:53:45+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/a478843f341774309ad8cc147cc1e41145d9f7ae +Commit: https://github.com/plone/plone.app.textfield/commit/fc3367dff3ea3988029e859feae7e6e4df23cb21 -chore: zpretty +chore: zpretty PT Files changed: -M plone/app/uuid/configure.zcml +M plone/app/textfield/widget_display.pt +M plone/app/textfield/widget_input.pt +M plone/app/textfield/widget_textarea_display.pt -b'diff --git a/plone/app/uuid/configure.zcml b/plone/app/uuid/configure.zcml\nindex eedd55b..c377239 100644\n--- a/plone/app/uuid/configure.zcml\n+++ b/plone/app/uuid/configure.zcml\n@@ -1,20 +1,24 @@\n \n+ i18n_domain="plone.app.uuid"\n+ >\n \n- \n- \n+ \n+ \n \n- \n- \n+ \n+ \n \n- \n- \n+ \n+ \n \n \n' +b'diff --git a/plone/app/textfield/widget_display.pt b/plone/app/textfield/widget_display.pt\nindex e7c6911..3052ac8 100644\n--- a/plone/app/textfield/widget_display.pt\n+++ b/plone/app/textfield/widget_display.pt\n@@ -1,18 +1,25 @@\n-
\n+
\ndiff --git a/plone/app/textfield/widget_input.pt b/plone/app/textfield/widget_input.pt\nindex 9063160..640938d 100644\n--- a/plone/app/textfield/widget_input.pt\n+++ b/plone/app/textfield/widget_input.pt\n@@ -1,72 +1,90 @@\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 The WYSIWYG code\n-
\n-
\n+
\n+
\n \n
\ndiff --git a/plone/app/textfield/widget_textarea_display.pt b/plone/app/textfield/widget_textarea_display.pt\nindex 6298c41..ba5aa84 100644\n--- a/plone/app/textfield/widget_textarea_display.pt\n+++ b/plone/app/textfield/widget_textarea_display.pt\n@@ -1,28 +1,32 @@\n \n- \n+>\n+ \n \n' -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-18T00:34:38+01:00 +Date: 2023-03-18T00:54:31+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/302e29fdebe9c97d0771a5e44bee25eb71054fcd +Commit: https://github.com/plone/plone.app.textfield/commit/0994d3610e8715ba36115f8d10e3be62b4aac414 -feat: pyroma +feat: codespell Files changed: -M setup.py +M CHANGES.rst -b'diff --git a/setup.py b/setup.py\nindex f9e336d..4672fef 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -40,6 +40,7 @@\n ],\n include_package_data=True,\n zip_safe=False,\n+ python_requires=">=3.8",\n install_requires=[\n "setuptools",\n "plone.uuid",\n' +b"diff --git a/CHANGES.rst b/CHANGES.rst\nindex fc643d7..931499a 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -188,7 +188,7 @@ Fixes:\n while still supporting normal portal_properties access for Plone < 5.\n [thet]\n \n-- Resolved an interesting circular import case, which wasnt effective because\n+- Resolved an interesting circular import case, which wasn't effective because\n of sort order of imports\n [thet]\n \n" -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-18T00:35:56+01:00 +Date: 2023-03-18T01:18:06+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/2a0eb376aff7a576cceaff41f8f42956c6955f6b +Commit: https://github.com/plone/plone.app.textfield/commit/eded6f2ba84d398db232fc3026409b83e9004b21 -feat: flake8 +fix(tox): adapt extra name Files changed: -M plone/app/uuid/tests.py -M plone/app/uuid/utils.py +M tox.ini -b'diff --git a/plone/app/uuid/tests.py b/plone/app/uuid/tests.py\nindex e86757f..3fa39c7 100644\n--- a/plone/app/uuid/tests.py\n+++ b/plone/app/uuid/tests.py\n@@ -165,7 +165,6 @@ def test_uuidToObject(self):\n self.assertIsNone(uuidToObject("unknown"))\n \n def test_uuidToCatalogBrain(self):\n- from Acquisition import aq_base\n from plone.app.uuid.utils import uuidToCatalogBrain\n from plone.uuid.interfaces import IUUID\n \ndiff --git a/plone/app/uuid/utils.py b/plone/app/uuid/utils.py\nindex 7da7279..61b5339 100644\n--- a/plone/app/uuid/utils.py\n+++ b/plone/app/uuid/utils.py\n@@ -1,4 +1,3 @@\n-from AccessControl import Unauthorized\n from Products.CMFCore.indexing import processQueue\n from Products.CMFCore.utils import getToolByName\n from Products.ZCatalog.query import IndexQuery\n' +b'diff --git a/tox.ini b/tox.ini\nindex eca8603..ca6fe32 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -47,4 +47,4 @@ deps =\n commands =\n zope-testrunner --test-path={toxinidir} -s plone.app.textfield\n extras =\n- test\n+ tests\n' -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-18T00:38:00+01:00 +Date: 2023-03-18T01:23:19+01:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.app.uuid/commit/e106c53f041b673703da2dddfff7f82c04c980f0 +Commit: https://github.com/plone/plone.app.textfield/commit/4b167a2f67666681bb55e82487e2a180f823b7de -feat: declare dependencies +fix: adapt tests Files changed: -M setup.py +M plone/app/textfield/field.rst +M plone/app/textfield/handler.rst +M plone/app/textfield/marshaler.rst +M plone/app/textfield/richtext_widget.rst +M plone/app/textfield/tests.py -b'diff --git a/setup.py b/setup.py\nindex 4672fef..b6fe238 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -42,16 +42,19 @@\n zip_safe=False,\n python_requires=">=3.8",\n install_requires=[\n- "setuptools",\n+ "Products.CMFCore",\n+ "Products.ZCatalog",\n "plone.uuid",\n "plone.indexer",\n+ "setuptools",\n "zope.publisher",\n "zope.interface",\n ],\n extras_require={\n "test": [\n- "plone.dexterity",\n "plone.app.testing",\n+ "plone.dexterity",\n+ "plone.testing",\n ]\n },\n entry_points="""\n' +b'diff --git a/plone/app/textfield/field.rst b/plone/app/textfield/field.rst\nindex 5c70591..939f2cb 100644\n--- a/plone/app/textfield/field.rst\n+++ b/plone/app/textfield/field.rst\n@@ -101,12 +101,12 @@ Products.PortalTransforms, which in turn comes with Plone.\n Let\'s now access the output of our previously constructed value object again:\n \n >>> value.output\n- u\'SOME PLAIN TEXT\'\n+ \'SOME PLAIN TEXT\'\n \n It is of course possible to get the raw value:\n \n >>> value.raw\n- u\'Some plain text\'\n+ \'Some plain text\'\n \n Or to get the value encoded:\n \n@@ -151,11 +151,11 @@ default MIME types set on the field.\n >>> value.outputMimeType\n \'text/x-uppercase\'\n >>> value.raw\n- u\'A plain text string\'\n+ \'A plain text string\'\n >>> value.raw_encoded\n b\'A plain text string\'\n >>> value.output\n- u\'A PLAIN TEXT STRING\'\n+ \'A PLAIN TEXT STRING\'\n \n Validation\n ----------\n@@ -211,7 +211,7 @@ MIME types.\n RichTextValue object. (Did you mean .raw or .output?)\n \n >>> default_field.default.raw\n- u\'Default value\'\n+ \'Default value\'\n >>> default_field.default.outputMimeType\n \'text/x-uppercase\'\n >>> default_field.default.mimeType\ndiff --git a/plone/app/textfield/handler.rst b/plone/app/textfield/handler.rst\nindex ca8c17f..6680f04 100644\n--- a/plone/app/textfield/handler.rst\n+++ b/plone/app/textfield/handler.rst\n@@ -47,7 +47,7 @@ Then, let\'s test the field\n ... allowed_mime_types=(\'text/plain\', \'text/html\',))\n >>> fieldType = IFieldNameExtractor(field)()\n >>> handler = getUtility(IFieldExportImportHandler, name=fieldType)\n- >>> element = handler.write(field, u\'dummy\', fieldType) #doctest: +ELLIPSIS\n+ >>> element = handler.write(field, \'dummy\', fieldType) #doctest: +ELLIPSIS\n >>> print(prettyXML(element))\n \n \n@@ -90,15 +90,15 @@ To import:\n >>> reciprocal.__name__\n \'dummy\'\n >>> reciprocal.title\n- u\'Test\'\n+ \'Test\'\n >>> reciprocal.description\n- u\'Test desc\'\n+ \'Test desc\'\n >>> reciprocal.required\n False\n >>> reciprocal.readonly\n True\n >>> reciprocal.default.raw\n- u\'Test default\'\n+ \'Test default\'\n >>> reciprocal.missing_value is None\n True\n >>> reciprocal.default_mime_type\ndiff --git a/plone/app/textfield/marshaler.rst b/plone/app/textfield/marshaler.rst\nindex 4b6d694..e4b857e 100644\n--- a/plone/app/textfield/marshaler.rst\n+++ b/plone/app/textfield/marshaler.rst\n@@ -40,7 +40,7 @@ we\'ll simply provide the output value directly::\n >>> from zope.interface import implementer\n >>> @implementer(ITestContent)\n ... class TestContent(object):\n- ... _text = RichTextValue(u"Some \\xd8 plain text", \'text/plain\', \'text/html\', \'utf-8\', u\'

Some \\xd8 plain text

\')\n+ ... _text = RichTextValue(u"Some \\xd8 plain text", \'text/plain\', \'text/html\', \'utf-8\', \'

Some \\xd8 plain text

\')\n \n >>> t = TestContent()\n \n@@ -57,7 +57,7 @@ The other way around::\n \n >>> decoded = marshaler.decode(b\'Some nei\\xc3\\x9f plain text\', charset=\'utf-8\', contentType=\'text/plain\')\n >>> decoded.raw\n- u\'Some nei\\xdf plain text\'\n+ \'Some nei\\xdf plain text\'\n >>> decoded.mimeType\n \'text/plain\'\n >>> decoded.outputMimeType\n@@ -76,7 +76,7 @@ the field\'s default type is used::\n \n >>> decoded = marshaler.decode(b\'Some nei\\xc3\\x9f plain text\')\n >>> decoded.raw\n- u\'Some nei\\xdf plain text\'\n+ \'Some nei\\xdf plain text\'\n >>> decoded.mimeType\n \'text/plain\'\n >>> decoded.outputMimeType\n@@ -110,7 +110,7 @@ Let\'s now use this message to construct a new object::\n >>> from plone.rfc822 import initializeObjectFromSchema\n >>> initializeObjectFromSchema(newContent, ITestContent, inputMessage)\n >>> newContent._text.raw\n- u\'Some \\xd8 plain text\'\n+ \'Some \\xd8 plain text\'\n >>> newContent._text.mimeType\n \'text/plain\'\n >>> newContent._text.outputMimeType\ndiff --git a/plone/app/textfield/richtext_widget.rst b/plone/app/textfield/richtext_widget.rst\nindex ea12d85..18cf977 100644\n--- a/plone/app/textfield/richtext_widget.rst\n+++ b/plone/app/textfield/richtext_widget.rst\n@@ -48,12 +48,13 @@ We also need to register the template for at least the widget and request:\n If we render the widget we get the HTML:\n >>> widget.update()\n >>> print(widget.render())\n-
\n- \n-
\n- \n-
\n-
\n+
\n+ ...\n+ ...
\n+ ...\n+ ...
\n+ ...
\n+\n >>> from zope.component import getGlobalSiteManager\n >>> gsm = getGlobalSiteManager()\n >>> gsm.unregisterAdapter(factory,\ndiff --git a/plone/app/textfield/tests.py b/plone/app/textfield/tests.py\nindex 5fca07c..8fdbe53 100644\n--- a/plone/app/textfield/tests.py\n+++ b/plone/app/textfield/tests.py\n@@ -3,7 +3,6 @@\n \n import doctest\n import plone.app.textfield\n-import re\n import unittest\n \n \n@@ -346,14 +345,6 @@ def test_getSize(self):\n self.assertEqual(3, value.getSize())\n \n \n-class Py23DocChecker(doctest.OutputChecker):\n- def check_output(self, want, got, optionflags):\n- want = re.sub("u\'(.*?)\'", "\'\\\\1\'", want)\n- want = re.sub(\'u"(.*?)"\', \'"\\\\1"\', want)\n-\n- return doctest.OutputChecker.check_output(self, want, got, optionflags)\n-\n-\n class TestTextfield(unittest.TestCase):\n def test_getWysiwygEditor(self):\n from plone.app.textfield.utils import getWysiwygEditor\n@@ -380,7 +371,6 @@ def test_suite():\n doctest.DocFileSuite(\n doctestfile,\n optionflags=doctest.ELLIPSIS,\n- checker=Py23DocChecker(),\n ),\n layer=testing.PLONE_FIXTURE,\n )\n' -Repository: plone.app.uuid +Repository: plone.app.textfield Branch: refs/heads/master -Date: 2023-03-21T14:59:24+01:00 -Author: Maurits van Rees (mauritsvanrees) -Commit: https://github.com/plone/plone.app.uuid/commit/cadf37e832fa9aa0a307a6dec69201b2aa3a9391 +Date: 2023-03-21T16:15:43+01:00 +Author: Jens W. Klein (jensens) +Commit: https://github.com/plone/plone.app.textfield/commit/bed29990ec13a904d9ec80fe2b9b6cbdebd8fff9 -Merge pull request #17 from plone/config-with-default-template-22a75215 +Merge pull request #49 from plone/config-with-default-template-ac42cf74 Config with default template @@ -155,19 +137,27 @@ Files changed: A .editorconfig A .meta.toml A .pre-commit-config.yaml -A news/b2d5d4a5.internal +A news/80cf330f.internal A tox.ini -M plone/__init__.py -M plone/app/__init__.py -M plone/app/uuid/browser.py -M plone/app/uuid/configure.zcml -M plone/app/uuid/indexer.py -M plone/app/uuid/testing.py -M plone/app/uuid/tests.py -M plone/app/uuid/utils.py +M CHANGES.rst +M plone/app/textfield/__init__.py +M plone/app/textfield/browser.zcml +M plone/app/textfield/configure.zcml +M plone/app/textfield/editor.zcml +M plone/app/textfield/field.rst +M plone/app/textfield/handler.rst +M plone/app/textfield/handler.zcml +M plone/app/textfield/marshaler.rst +M plone/app/textfield/marshaler.zcml +M plone/app/textfield/richtext_widget.rst +M plone/app/textfield/tests.py +M plone/app/textfield/transform.zcml +M plone/app/textfield/widget.zcml +M plone/app/textfield/widget_display.pt +M plone/app/textfield/widget_input.pt +M plone/app/textfield/widget_textarea_display.pt M pyproject.toml M setup.cfg -M setup.py -b'diff --git a/.editorconfig b/.editorconfig\nnew file mode 100644\nindex 0000000..b4158b8\n--- /dev/null\n+++ b/.editorconfig\n@@ -0,0 +1,39 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+#\n+# EditorConfig Configuration file, for more details see:\n+# http://EditorConfig.org\n+# EditorConfig is a convention description, that could be interpreted\n+# by multiple editors to enforce common coding conventions for specific\n+# file types\n+\n+# top-most EditorConfig file:\n+# Will ignore other EditorConfig files in Home directory or upper tree level.\n+root = true\n+\n+\n+[*] # For All Files\n+# Unix-style newlines with a newline ending every file\n+end_of_line = lf\n+insert_final_newline = true\n+trim_trailing_whitespace = true\n+# Set default charset\n+charset = utf-8\n+# Indent style default\n+indent_style = space\n+# Max Line Length - a hard line wrap, should be disabled\n+max_line_length = off\n+\n+[*.{py,cfg,ini}]\n+# 4 space indentation\n+indent_size = 4\n+\n+[*.{yml,zpt,pt,dtml,zcml}]\n+# 2 space indentation\n+indent_size = 2\n+\n+[{Makefile,.gitmodules}]\n+# Tab indentation (no size specified, but view as 4 spaces)\n+indent_style = tab\n+indent_size = unset\n+tab_width = unset\ndiff --git a/.meta.toml b/.meta.toml\nnew file mode 100644\nindex 0000000..d4a62f1\n--- /dev/null\n+++ b/.meta.toml\n@@ -0,0 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[meta]\n+template = "default"\n+commit-id = "b2d5d4a5"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..582f8ac\n--- /dev/null\n+++ b/.pre-commit-config.yaml\n@@ -0,0 +1,42 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+ci:\n+ autofix_prs: false\n+ autoupdate_schedule: monthly\n+\n+repos:\n+- repo: https://github.com/asottile/pyupgrade\n+ rev: v3.3.1\n+ hooks:\n+ - id: pyupgrade\n+ args: [--py38-plus]\n+- repo: https://github.com/pycqa/isort\n+ rev: 5.12.0\n+ hooks:\n+ - id: isort\n+- repo: https://github.com/psf/black\n+ rev: 23.1.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.2\n+ hooks:\n+ - id: zpretty\n+- repo: https://github.com/PyCQA/flake8\n+ rev: 6.0.0\n+ hooks:\n+ - id: flake8\n+- repo: https://github.com/codespell-project/codespell\n+ rev: v2.2.2\n+ hooks:\n+ - id: codespell\n+ additional_dependencies:\n+ - tomli\n+- repo: https://github.com/mgedmin/check-manifest\n+ rev: "0.49"\n+ hooks:\n+ - id: check-manifest\n+- repo: https://github.com/regebro/pyroma\n+ rev: "4.2"\n+ hooks:\n+ - id: pyroma\ndiff --git a/news/b2d5d4a5.internal b/news/b2d5d4a5.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/b2d5d4a5.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/plone/__init__.py b/plone/__init__.py\nindex 68c04af..5284146 100644\n--- a/plone/__init__.py\n+++ b/plone/__init__.py\n@@ -1,2 +1 @@\n-# -*- coding: utf-8 -*-\n-__import__(\'pkg_resources\').declare_namespace(__name__)\n+__import__("pkg_resources").declare_namespace(__name__)\ndiff --git a/plone/app/__init__.py b/plone/app/__init__.py\nindex 68c04af..5284146 100644\n--- a/plone/app/__init__.py\n+++ b/plone/app/__init__.py\n@@ -1,2 +1 @@\n-# -*- coding: utf-8 -*-\n-__import__(\'pkg_resources\').declare_namespace(__name__)\n+__import__("pkg_resources").declare_namespace(__name__)\ndiff --git a/plone/app/uuid/browser.py b/plone/app/uuid/browser.py\nindex 0f1bfec..2ffa087 100644\n--- a/plone/app/uuid/browser.py\n+++ b/plone/app/uuid/browser.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.app.uuid.utils import uuidToURL\n from zope.interface import implementer\n from zope.publisher.browser import BrowserView\n@@ -21,7 +20,7 @@ def publishTraverse(self, request, name):\n def __call__(self):\n if self.uuid is None:\n raise KeyError(\n- \'No UUID given in sub-path. Use .../@@redirect-to-uuid/\'\n+ "No UUID given in sub-path. Use .../@@redirect-to-uuid/"\n )\n \n url = uuidToURL(self.uuid)\n@@ -29,4 +28,4 @@ def __call__(self):\n raise NotFound(self, self.uuid)\n \n self.request.response.redirect(url)\n- return u\'\'\n+ return ""\ndiff --git a/plone/app/uuid/configure.zcml b/plone/app/uuid/configure.zcml\nindex eedd55b..c377239 100644\n--- a/plone/app/uuid/configure.zcml\n+++ b/plone/app/uuid/configure.zcml\n@@ -1,20 +1,24 @@\n \n+ i18n_domain="plone.app.uuid"\n+ >\n \n- \n- \n+ \n+ \n \n- \n- \n+ \n+ \n \n- \n- \n+ \n+ \n \n \ndiff --git a/plone/app/uuid/indexer.py b/plone/app/uuid/indexer.py\nindex ed7be46..7166a4f 100644\n--- a/plone/app/uuid/indexer.py\n+++ b/plone/app/uuid/indexer.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.indexer import indexer\n from plone.uuid.interfaces import IUUID\n from plone.uuid.interfaces import IUUIDAware\ndiff --git a/plone/app/uuid/testing.py b/plone/app/uuid/testing.py\nindex f3cc5f2..e05804f 100644\n--- a/plone/app/uuid/testing.py\n+++ b/plone/app/uuid/testing.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.app.testing import FunctionalTesting\n from plone.app.testing import IntegrationTesting\n from plone.app.testing import PLONE_FIXTURE\n@@ -9,31 +8,30 @@\n \n \n class PloneAppUUID(PloneSandboxLayer):\n-\n defaultBases = (PLONE_FIXTURE,)\n \n def setUpZope(self, app, configurationContext):\n # Load ZCML\n import plone.app.uuid\n- xmlconfig.file(\'configure.zcml\', plone.app.uuid,\n- context=configurationContext)\n+\n+ xmlconfig.file("configure.zcml", plone.app.uuid, context=configurationContext)\n \n def setUpPloneSite(self, portal):\n- types_tool = getToolByName(portal, \'portal_types\')\n+ types_tool = getToolByName(portal, "portal_types")\n # This test should work for both Plone 4.3 (with ATContentTypes) and\n # Plone 5.x (without any types). Therefore we can not make any\n # assumptions about an existing Document type.\n- if \'Document\' not in types_tool.objectIds():\n- fti = DexterityFTI(\'Document\')\n- types_tool._setObject(\'Document\', fti)\n+ if "Document" not in types_tool.objectIds():\n+ fti = DexterityFTI("Document")\n+ types_tool._setObject("Document", fti)\n \n \n PLONE_APP_UUID_FIXTURE = PloneAppUUID()\n PLONE_APP_UUID_INTEGRATION_TESTING = IntegrationTesting(\n- bases=(PLONE_APP_UUID_FIXTURE, ),\n- name=\'plone.app.uuid:Integration\',\n+ bases=(PLONE_APP_UUID_FIXTURE,),\n+ name="plone.app.uuid:Integration",\n )\n PLONE_APP_UUID_FUNCTIONAL_TESTING = FunctionalTesting(\n- bases=(PLONE_APP_UUID_FIXTURE, ),\n- name=\'plone.app.uuid:Functional\',\n+ bases=(PLONE_APP_UUID_FIXTURE,),\n+ name="plone.app.uuid:Functional",\n )\ndiff --git a/plone/app/uuid/tests.py b/plone/app/uuid/tests.py\nindex 4bf62b8..3fa39c7 100644\n--- a/plone/app/uuid/tests.py\n+++ b/plone/app/uuid/tests.py\n@@ -1,12 +1,11 @@\n-# -*- coding: utf-8 -*-\n from AccessControl import Unauthorized\n from plone.app.testing import logout\n from plone.app.testing import setRoles\n from plone.app.testing import TEST_USER_ID\n from plone.app.testing import TEST_USER_PASSWORD\n-from plone.testing.zope import Browser\n from plone.app.uuid.testing import PLONE_APP_UUID_FUNCTIONAL_TESTING\n from plone.app.uuid.testing import PLONE_APP_UUID_INTEGRATION_TESTING\n+from plone.testing.zope import Browser\n \n import os\n import time\n@@ -20,12 +19,12 @@ class IntegrationTestCase(unittest.TestCase):\n def test_assignment(self):\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n+ portal.invokeFactory("Document", "d1")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n self.assertTrue(isinstance(uuid, str))\n@@ -33,51 +32,50 @@ def test_assignment(self):\n def test_search(self):\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n- catalog = portal[\'portal_catalog\']\n+ catalog = portal["portal_catalog"]\n results = catalog(UID=uuid)\n \n self.assertEqual(1, len(results))\n self.assertEqual(uuid, results[0].UID)\n- self.assertEqual(\'/\'.join(d1.getPhysicalPath()), results[0].getPath())\n+ self.assertEqual("/".join(d1.getPhysicalPath()), results[0].getPath())\n \n def test_uuidToPhysicalPath(self):\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToPhysicalPath\n+ from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n- self.assertEqual(\'/\'.join(d1.getPhysicalPath()),\n- uuidToPhysicalPath(uuid))\n- self.assertIsNone(uuidToPhysicalPath(\'unknown\'))\n+ self.assertEqual("/".join(d1.getPhysicalPath()), uuidToPhysicalPath(uuid))\n+ self.assertIsNone(uuidToPhysicalPath("unknown"))\n \n def test_speed(self):\n # I updated some of the utility functions to be a bit faster.\n # In this function you can check the speed.\n from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n+ from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.app.uuid.utils import uuidToObject\n from plone.app.uuid.utils import uuidToPhysicalPath\n from plone.app.uuid.utils import uuidToURL\n- from plone.app.uuid.utils import uuidToObject\n- from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n start = time.time()\n uuids = {}\n@@ -88,100 +86,101 @@ def test_speed(self):\n if total:\n report = True\n total = int(total)\n- print("Creating {} documents...".format(total))\n+ print(f"Creating {total} documents...")\n else:\n report = False\n total = 40\n for i in range(total):\n- doc_id = portal.invokeFactory(\'Document\', \'d{}\'.format(i))\n+ doc_id = portal.invokeFactory("Document", f"d{i}")\n doc = portal[doc_id]\n uuids[IUUID(doc)] = {\n- \'path\': \'/\'.join(doc.getPhysicalPath()),\n- \'url\': doc.absolute_url(),\n- \'obj\': aq_base(doc),\n+ "path": "/".join(doc.getPhysicalPath()),\n+ "url": doc.absolute_url(),\n+ "obj": aq_base(doc),\n }\n end = time.time()\n if report:\n- print("Time taken to create {} items: {}".format(total, end - start))\n+ print(f"Time taken to create {total} items: {end - start}")\n \n self.assertEqual(len(uuids), total)\n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'path\'], uuidToPhysicalPath(uuid))\n+ self.assertEqual(info["path"], uuidToPhysicalPath(uuid))\n end = time.time()\n if report:\n- print("Time taken for uuidToPhysicalPath: {}".format(end - start))\n+ print(f"Time taken for uuidToPhysicalPath: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'url\'], uuidToURL(uuid))\n+ self.assertEqual(info["url"], uuidToURL(uuid))\n end = time.time()\n if report:\n- print("Time taken for uuidToURL: {}".format(end - start))\n+ print(f"Time taken for uuidToURL: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'obj\'], aq_base(uuidToObject(uuid)))\n+ self.assertEqual(info["obj"], aq_base(uuidToObject(uuid)))\n end = time.time()\n if report:\n- print("Time taken for uuidToObject: {}".format(end - start))\n+ print(f"Time taken for uuidToObject: {end - start}")\n \n start = time.time()\n for uuid, info in uuids.items():\n- self.assertEqual(info[\'path\'], uuidToCatalogBrain(uuid).getPath())\n+ self.assertEqual(info["path"], uuidToCatalogBrain(uuid).getPath())\n end = time.time()\n if report:\n- print("Time taken for uuidToCatalogBrain: {}".format(end - start))\n+ print(f"Time taken for uuidToCatalogBrain: {end - start}")\n \n def test_uuidToURL(self):\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToURL\n+ from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n self.assertEqual(d1.absolute_url(), uuidToURL(uuid))\n- self.assertIsNone(uuidToURL(\'unknown\'))\n+ self.assertIsNone(uuidToURL("unknown"))\n \n def test_uuidToObject(self):\n from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToObject\n+ from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n self.assertEqual(aq_base(d1), aq_base(uuidToObject(uuid)))\n- self.assertIsNone(uuidToObject(\'unknown\'))\n+ self.assertIsNone(uuidToObject("unknown"))\n \n def test_uuidToCatalogBrain(self):\n- from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n- self.assertEqual(\'/\'.join(d1.getPhysicalPath()), uuidToCatalogBrain(uuid).getPath())\n- self.assertIsNone(uuidToCatalogBrain(\'unknown\'))\n+ self.assertEqual(\n+ "/".join(d1.getPhysicalPath()), uuidToCatalogBrain(uuid).getPath()\n+ )\n+ self.assertIsNone(uuidToCatalogBrain("unknown"))\n \n def test_access_private_published(self):\n """Do the functions return both private and published items?\n@@ -197,35 +196,35 @@ def test_access_private_published(self):\n \'restricted/unrestricted=True/False\'.\n """\n from Acquisition import aq_base\n- from plone.uuid.interfaces import IUUID\n+ from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.app.uuid.utils import uuidToObject\n from plone.app.uuid.utils import uuidToPhysicalPath\n from plone.app.uuid.utils import uuidToURL\n- from plone.app.uuid.utils import uuidToObject\n- from plone.app.uuid.utils import uuidToCatalogBrain\n+ from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ portal = self.layer["portal"]\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n wftool = portal.portal_workflow\n wftool.setDefaultChain("simple_publication_workflow")\n \n # Create private folder.\n- portal.invokeFactory(\'Folder\', \'private\')\n+ portal.invokeFactory("Folder", "private")\n private = portal.private\n private_url = private.absolute_url()\n private_uuid = IUUID(private)\n- private_path = \'/\'.join(private.getPhysicalPath())\n+ private_path = "/".join(private.getPhysicalPath())\n \n # Create public document in private folder.\n- private.invokeFactory(\'Document\', \'published\')\n- wftool.doActionFor(portal.private.published, \'publish\')\n+ private.invokeFactory("Document", "published")\n+ wftool.doActionFor(portal.private.published, "publish")\n published = private.published\n published_url = published.absolute_url()\n published_uuid = IUUID(published)\n- published_path = \'/\'.join(published.getPhysicalPath())\n+ published_path = "/".join(published.getPhysicalPath())\n \n # Check that the review states are what we expect.\n- self.assertEqual(wftool.getInfoFor(private, \'review_state\'), \'private\')\n- self.assertEqual(wftool.getInfoFor(published, \'review_state\'), \'published\')\n+ self.assertEqual(wftool.getInfoFor(private, "review_state"), "private")\n+ self.assertEqual(wftool.getInfoFor(published, "review_state"), "published")\n \n # The test user can obviously see the published item.\n self.assertEqual(published_path, uuidToPhysicalPath(published_uuid))\n@@ -245,7 +244,6 @@ def test_access_private_published(self):\n self.assertEqual(published_url, uuidToURL(published_uuid))\n self.assertEqual(published_path, uuidToCatalogBrain(published_uuid).getPath())\n self.assertEqual(aq_base(published), aq_base(uuidToObject(published_uuid)))\n- \n \n # Currently, anonymous can also see the private item with most functions.\n # See the docstring of this test method.\n@@ -264,76 +262,71 @@ def test_access_private_published(self):\n \n \n class FunctionalTestCase(unittest.TestCase):\n-\n layer = PLONE_APP_UUID_FUNCTIONAL_TESTING\n \n def test_uuid_view(self):\n-\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- app = self.layer[\'app\']\n+ portal = self.layer["portal"]\n+ app = self.layer["app"]\n \n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n+ portal.invokeFactory("Document", "d1")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n transaction.commit()\n \n browser = Browser(app)\n- browser.addHeader(\n- \'Authorization\',\n- \'Basic {0}:{1}\'.format(TEST_USER_ID, TEST_USER_PASSWORD, )\n- )\n+ browser.addHeader("Authorization", f"Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}")\n \n- browser.open(\'{0}/@@uuid\'.format(d1.absolute_url()))\n+ browser.open(f"{d1.absolute_url()}/@@uuid")\n self.assertEqual(uuid, browser.contents)\n \n def test_redirect_to_uuid_view(self):\n from plone.uuid.interfaces import IUUID\n \n- portal = self.layer[\'portal\']\n- app = self.layer[\'app\']\n+ portal = self.layer["portal"]\n+ app = self.layer["app"]\n \n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n- portal.invokeFactory(\'Document\', \'d1\')\n- portal.invokeFactory(\'Document\', \'d2\')\n+ portal.invokeFactory("Document", "d1")\n+ portal.invokeFactory("Document", "d2")\n \n- d1 = portal[\'d1\']\n+ d1 = portal["d1"]\n uuid = IUUID(d1)\n \n transaction.commit()\n \n browser = Browser(app)\n- browser.addHeader(\n- \'Authorization\',\n- \'Basic {0}:{1}\'.format(TEST_USER_ID, TEST_USER_PASSWORD,)\n+ browser.addHeader("Authorization", f"Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}")\n+\n+ url = "{0}/@@redirect-to-uuid/{1}"\n+ browser.open(\n+ url.format(\n+ portal.absolute_url(),\n+ uuid,\n+ )\n )\n-\n- url = \'{0}/@@redirect-to-uuid/{1}\'\n- browser.open(url.format(portal.absolute_url(), uuid,))\n self.assertEqual(d1.absolute_url(), browser.url)\n \n def test_redirect_to_uuid_invalid_uuid(self):\n- portal = self.layer[\'portal\']\n- app = self.layer[\'app\']\n+ portal = self.layer["portal"]\n+ app = self.layer["app"]\n \n- setRoles(portal, TEST_USER_ID, [\'Manager\'])\n+ setRoles(portal, TEST_USER_ID, ["Manager"])\n \n transaction.commit()\n \n browser = Browser(app)\n browser.handleErrors = False\n- browser.addHeader(\n- \'Authorization\',\n- \'Basic {0}:{1}\'.format(TEST_USER_ID, TEST_USER_PASSWORD, )\n- )\n+ browser.addHeader("Authorization", f"Basic {TEST_USER_ID}:{TEST_USER_PASSWORD}")\n \n- url = \'{0}/@@redirect-to-uuid/gibberish\'.format(portal.absolute_url())\n+ url = f"{portal.absolute_url()}/@@redirect-to-uuid/gibberish"\n from zExceptions import NotFound\n+\n with self.assertRaises(NotFound):\n browser.open(url)\ndiff --git a/plone/app/uuid/utils.py b/plone/app/uuid/utils.py\nindex 8201167..61b5339 100644\n--- a/plone/app/uuid/utils.py\n+++ b/plone/app/uuid/utils.py\n@@ -1,5 +1,3 @@\n-# -*- coding: utf-8 -*-\n-from AccessControl import Unauthorized\n from Products.CMFCore.indexing import processQueue\n from Products.CMFCore.utils import getToolByName\n from Products.ZCatalog.query import IndexQuery\n@@ -22,7 +20,7 @@ def _catalog():\n if request is not None:\n request._catalog = None\n return\n- catalog = getToolByName(site, \'portal_catalog\', None)\n+ catalog = getToolByName(site, "portal_catalog", None)\n if request is not None:\n request._catalog = catalog\n return catalog\n@@ -75,7 +73,7 @@ def uuidToURL(uuid):\n return brain.getURL()\n \n \n-def uuidToObject(uuid, unrestricted = False):\n+def uuidToObject(uuid, unrestricted=False):\n """Given a UUID, attempt to return a content object. Will return\n None if the UUID can\'t be found.\n \ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..9eb73f3 100644\n--- a/pyproject.toml\n+++ b/pyproject.toml\n@@ -1,3 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [tool.towncrier]\n filename = "CHANGES.rst"\n directory = "news/"\n@@ -18,3 +20,43 @@ showcontent = true\n directory = "bugfix"\n name = "Bug fixes:"\n showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "internal"\n+name = "Internal:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "documentation"\n+name = "Documentation:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "tests"\n+name = "Tests"\n+showcontent = true\n+\n+[tool.isort]\n+profile = "plone"\n+\n+[tool.black]\n+target-version = ["py38"]\n+\n+[tool.dependencychecker]\n+Zope = [\n+ # Zope own provided namespaces\n+ \'App\', \'OFS\', \'Products.Five\', \'Products.OFSP\', \'Products.PageTemplates\',\n+ \'Products.SiteAccess\', \'Shared\', \'Testing\', \'ZPublisher\', \'ZTUtils\',\n+ \'Zope2\', \'webdav\', \'zmi\',\n+ # Zope dependencies\n+ \'Acquisition\', \'DateTime\', \'transaction\', \'zExceptions\', \'ZODB\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.deferredimport\', \'zope.event\',\n+ \'zope.exceptions\', \'zope.globalrequest\', \'zope.i18n\', \'zope.i18nmessageid\',\n+ \'zope.interface\', \'zope.lifecycleevent\', \'zope.location\', \'zope.publisher\',\n+ \'zope.schema\', \'zope.security\', \'zope.site\', \'zope.traversing\', \'AccessControl\',\n+]\n+\'plone.base\' = [\n+ \'AccessControl\', \'Products.BTreeFolder2\', \'Products.CMFCore\',\n+ \'Products.CMFDynamicViewFTI\', \'zope.deprecation\',\n+]\n+python-dateutil = [\'dateutil\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 526aeb2..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,2 +1,23 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [bdist_wheel]\n universal = 0\n+\n+[flake8]\n+doctests = 1\n+ignore =\n+ # black takes care of line length\n+ E501,\n+ # black takes care of where to break lines\n+ W503,\n+ # black takes care of spaces within slicing (list[:])\n+ E203,\n+ # black takes care of spaces after commas\n+ E231,\n+\n+[check-manifest]\n+ignore =\n+ .editorconfig\n+ .meta.toml\n+ .pre-commit-config.yaml\n+ tox.ini\ndiff --git a/setup.py b/setup.py\nindex ccb965e..b6fe238 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,53 +1,60 @@\n-# -*- coding: utf-8 -*-\n from setuptools import find_packages\n from setuptools import setup\n \n-version = \'2.2.2.dev0\'\n \n-long_description = \'{0}\\n{1}\'.format(\n- open(\'README.rst\').read(),\n- open(\'CHANGES.rst\').read(),\n+version = "2.2.2.dev0"\n+\n+long_description = "{}\\n{}".format(\n+ open("README.rst").read(),\n+ open("CHANGES.rst").read(),\n )\n \n setup(\n- name=\'plone.app.uuid\',\n+ name="plone.app.uuid",\n version=version,\n- description=\'Plone integration for the basic plone.uuid package\',\n+ description="Plone integration for the basic plone.uuid package",\n long_description=long_description,\n # Get more strings from\n # https://pypi.org/classifiers/\n classifiers=[\n- \'Development Status :: 5 - Production/Stable\',\n- \'Framework :: Plone\',\n- \'Framework :: Plone :: 6.0\',\n- \'Framework :: Plone :: Core\',\n+ "Development Status :: 5 - Production/Stable",\n+ "Framework :: Plone",\n+ "Framework :: Plone :: 6.0",\n+ "Framework :: Plone :: Core",\n "License :: OSI Approved :: GNU General Public License (GPL)",\n- \'Programming Language :: Python\',\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+ "Programming Language :: Python",\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 ],\n- keywords=\'plone uuid\',\n- author=\'Martin Aspeli\',\n- author_email=\'optilude@gmail.com\',\n- url=\'http://plone.org\',\n- license=\'GPL\',\n+ keywords="plone uuid",\n+ author="Martin Aspeli",\n+ author_email="optilude@gmail.com",\n+ url="http://plone.org",\n+ license="GPL",\n packages=find_packages(),\n- namespace_packages=[\'plone\', \'plone.app\', ],\n+ namespace_packages=[\n+ "plone",\n+ "plone.app",\n+ ],\n include_package_data=True,\n zip_safe=False,\n+ python_requires=">=3.8",\n install_requires=[\n- \'setuptools\',\n- \'plone.uuid\',\n- \'plone.indexer\',\n- \'zope.publisher\',\n- \'zope.interface\',\n+ "Products.CMFCore",\n+ "Products.ZCatalog",\n+ "plone.uuid",\n+ "plone.indexer",\n+ "setuptools",\n+ "zope.publisher",\n+ "zope.interface",\n ],\n extras_require={\n- \'test\': [\n- \'plone.dexterity\',\n- \'plone.app.testing\',\n+ "test": [\n+ "plone.app.testing",\n+ "plone.dexterity",\n+ "plone.testing",\n ]\n },\n entry_points="""\ndiff --git a/tox.ini b/tox.ini\nnew file mode 100644\nindex 0000000..74180d4\n--- /dev/null\n+++ b/tox.ini\n@@ -0,0 +1,50 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[tox]\n+envlist =\n+ format\n+ lint\n+ test\n+\n+[testenv]\n+allowlist_externals =\n+ sh\n+\n+[testenv:format]\n+description = automatically reformat code\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a pyupgrade\n+ pre-commit run -a isort\n+ pre-commit run -a black\n+ pre-commit run -a zpretty\n+\n+[testenv:lint]\n+description = run linters that will help improve the code style\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a\n+\n+[testenv:dependencies]\n+description = check if the package defines all its dependencies and generate a graph out of them\n+deps =\n+ z3c.dependencychecker==2.11\n+ pipdeptree==2.5.1\n+ graphviz # optional dependency of pipdeptree\n+commands =\n+ dependencychecker\n+ sh -c \'pipdeptree --exclude setuptools,wheel,pipdeptree,z3c.dependencychecker,zope.interface,zope.component --graph-output svg > dependencies.svg\'\n+\n+[testenv:test]\n+usedevelop = true\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --test-path={toxinidir} -s plone.app.uuid\n+extras =\n+ test\n' +b'diff --git a/.editorconfig b/.editorconfig\nnew file mode 100644\nindex 0000000..b4158b8\n--- /dev/null\n+++ b/.editorconfig\n@@ -0,0 +1,39 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+#\n+# EditorConfig Configuration file, for more details see:\n+# http://EditorConfig.org\n+# EditorConfig is a convention description, that could be interpreted\n+# by multiple editors to enforce common coding conventions for specific\n+# file types\n+\n+# top-most EditorConfig file:\n+# Will ignore other EditorConfig files in Home directory or upper tree level.\n+root = true\n+\n+\n+[*] # For All Files\n+# Unix-style newlines with a newline ending every file\n+end_of_line = lf\n+insert_final_newline = true\n+trim_trailing_whitespace = true\n+# Set default charset\n+charset = utf-8\n+# Indent style default\n+indent_style = space\n+# Max Line Length - a hard line wrap, should be disabled\n+max_line_length = off\n+\n+[*.{py,cfg,ini}]\n+# 4 space indentation\n+indent_size = 4\n+\n+[*.{yml,zpt,pt,dtml,zcml}]\n+# 2 space indentation\n+indent_size = 2\n+\n+[{Makefile,.gitmodules}]\n+# Tab indentation (no size specified, but view as 4 spaces)\n+indent_style = tab\n+indent_size = unset\n+tab_width = unset\ndiff --git a/.meta.toml b/.meta.toml\nnew file mode 100644\nindex 0000000..697a54c\n--- /dev/null\n+++ b/.meta.toml\n@@ -0,0 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[meta]\n+template = "default"\n+commit-id = "80cf330f"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..582f8ac\n--- /dev/null\n+++ b/.pre-commit-config.yaml\n@@ -0,0 +1,42 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+ci:\n+ autofix_prs: false\n+ autoupdate_schedule: monthly\n+\n+repos:\n+- repo: https://github.com/asottile/pyupgrade\n+ rev: v3.3.1\n+ hooks:\n+ - id: pyupgrade\n+ args: [--py38-plus]\n+- repo: https://github.com/pycqa/isort\n+ rev: 5.12.0\n+ hooks:\n+ - id: isort\n+- repo: https://github.com/psf/black\n+ rev: 23.1.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.2\n+ hooks:\n+ - id: zpretty\n+- repo: https://github.com/PyCQA/flake8\n+ rev: 6.0.0\n+ hooks:\n+ - id: flake8\n+- repo: https://github.com/codespell-project/codespell\n+ rev: v2.2.2\n+ hooks:\n+ - id: codespell\n+ additional_dependencies:\n+ - tomli\n+- repo: https://github.com/mgedmin/check-manifest\n+ rev: "0.49"\n+ hooks:\n+ - id: check-manifest\n+- repo: https://github.com/regebro/pyroma\n+ rev: "4.2"\n+ hooks:\n+ - id: pyroma\ndiff --git a/CHANGES.rst b/CHANGES.rst\nindex fc643d7..931499a 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -188,7 +188,7 @@ Fixes:\n while still supporting normal portal_properties access for Plone < 5.\n [thet]\n \n-- Resolved an interesting circular import case, which wasnt effective because\n+- Resolved an interesting circular import case, which wasn\'t effective because\n of sort order of imports\n [thet]\n \ndiff --git a/news/80cf330f.internal b/news/80cf330f.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/80cf330f.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/plone/app/textfield/__init__.py b/plone/app/textfield/__init__.py\nindex e8e39e0..18a8735 100644\n--- a/plone/app/textfield/__init__.py\n+++ b/plone/app/textfield/__init__.py\n@@ -29,7 +29,7 @@ def __init__(\n allowed_mime_types=None,\n max_length=None,\n schema=IRichTextValue,\n- **kw\n+ **kw,\n ):\n self.default_mime_type = default_mime_type\n self.output_mime_type = output_mime_type\ndiff --git a/plone/app/textfield/browser.zcml b/plone/app/textfield/browser.zcml\nindex 63727c8..1f20f39 100644\n--- a/plone/app/textfield/browser.zcml\n+++ b/plone/app/textfield/browser.zcml\n@@ -1,14 +1,15 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \n \n \ndiff --git a/plone/app/textfield/configure.zcml b/plone/app/textfield/configure.zcml\nindex e3bb0f6..eee27de 100644\n--- a/plone/app/textfield/configure.zcml\n+++ b/plone/app/textfield/configure.zcml\n@@ -1,31 +1,37 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n- \n \n \n- \n \n \n- \n \n \n- \n \n \n- \n \n \ndiff --git a/plone/app/textfield/editor.zcml b/plone/app/textfield/editor.zcml\nindex e5f54d6..8ea3a6d 100644\n--- a/plone/app/textfield/editor.zcml\n+++ b/plone/app/textfield/editor.zcml\n@@ -1,6 +1,7 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \ndiff --git a/plone/app/textfield/field.rst b/plone/app/textfield/field.rst\nindex 5c70591..939f2cb 100644\n--- a/plone/app/textfield/field.rst\n+++ b/plone/app/textfield/field.rst\n@@ -101,12 +101,12 @@ Products.PortalTransforms, which in turn comes with Plone.\n Let\'s now access the output of our previously constructed value object again:\n \n >>> value.output\n- u\'SOME PLAIN TEXT\'\n+ \'SOME PLAIN TEXT\'\n \n It is of course possible to get the raw value:\n \n >>> value.raw\n- u\'Some plain text\'\n+ \'Some plain text\'\n \n Or to get the value encoded:\n \n@@ -151,11 +151,11 @@ default MIME types set on the field.\n >>> value.outputMimeType\n \'text/x-uppercase\'\n >>> value.raw\n- u\'A plain text string\'\n+ \'A plain text string\'\n >>> value.raw_encoded\n b\'A plain text string\'\n >>> value.output\n- u\'A PLAIN TEXT STRING\'\n+ \'A PLAIN TEXT STRING\'\n \n Validation\n ----------\n@@ -211,7 +211,7 @@ MIME types.\n RichTextValue object. (Did you mean .raw or .output?)\n \n >>> default_field.default.raw\n- u\'Default value\'\n+ \'Default value\'\n >>> default_field.default.outputMimeType\n \'text/x-uppercase\'\n >>> default_field.default.mimeType\ndiff --git a/plone/app/textfield/handler.rst b/plone/app/textfield/handler.rst\nindex ca8c17f..6680f04 100644\n--- a/plone/app/textfield/handler.rst\n+++ b/plone/app/textfield/handler.rst\n@@ -47,7 +47,7 @@ Then, let\'s test the field\n ... allowed_mime_types=(\'text/plain\', \'text/html\',))\n >>> fieldType = IFieldNameExtractor(field)()\n >>> handler = getUtility(IFieldExportImportHandler, name=fieldType)\n- >>> element = handler.write(field, u\'dummy\', fieldType) #doctest: +ELLIPSIS\n+ >>> element = handler.write(field, \'dummy\', fieldType) #doctest: +ELLIPSIS\n >>> print(prettyXML(element))\n \n \n@@ -90,15 +90,15 @@ To import:\n >>> reciprocal.__name__\n \'dummy\'\n >>> reciprocal.title\n- u\'Test\'\n+ \'Test\'\n >>> reciprocal.description\n- u\'Test desc\'\n+ \'Test desc\'\n >>> reciprocal.required\n False\n >>> reciprocal.readonly\n True\n >>> reciprocal.default.raw\n- u\'Test default\'\n+ \'Test default\'\n >>> reciprocal.missing_value is None\n True\n >>> reciprocal.default_mime_type\ndiff --git a/plone/app/textfield/handler.zcml b/plone/app/textfield/handler.zcml\nindex d8a15c4..8a99d37 100644\n--- a/plone/app/textfield/handler.zcml\n+++ b/plone/app/textfield/handler.zcml\n@@ -1,14 +1,13 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \n- \n+ \n \n \ndiff --git a/plone/app/textfield/marshaler.rst b/plone/app/textfield/marshaler.rst\nindex 4b6d694..e4b857e 100644\n--- a/plone/app/textfield/marshaler.rst\n+++ b/plone/app/textfield/marshaler.rst\n@@ -40,7 +40,7 @@ we\'ll simply provide the output value directly::\n >>> from zope.interface import implementer\n >>> @implementer(ITestContent)\n ... class TestContent(object):\n- ... _text = RichTextValue(u"Some \\xd8 plain text", \'text/plain\', \'text/html\', \'utf-8\', u\'

Some \\xd8 plain text

\')\n+ ... _text = RichTextValue(u"Some \\xd8 plain text", \'text/plain\', \'text/html\', \'utf-8\', \'

Some \\xd8 plain text

\')\n \n >>> t = TestContent()\n \n@@ -57,7 +57,7 @@ The other way around::\n \n >>> decoded = marshaler.decode(b\'Some nei\\xc3\\x9f plain text\', charset=\'utf-8\', contentType=\'text/plain\')\n >>> decoded.raw\n- u\'Some nei\\xdf plain text\'\n+ \'Some nei\\xdf plain text\'\n >>> decoded.mimeType\n \'text/plain\'\n >>> decoded.outputMimeType\n@@ -76,7 +76,7 @@ the field\'s default type is used::\n \n >>> decoded = marshaler.decode(b\'Some nei\\xc3\\x9f plain text\')\n >>> decoded.raw\n- u\'Some nei\\xdf plain text\'\n+ \'Some nei\\xdf plain text\'\n >>> decoded.mimeType\n \'text/plain\'\n >>> decoded.outputMimeType\n@@ -110,7 +110,7 @@ Let\'s now use this message to construct a new object::\n >>> from plone.rfc822 import initializeObjectFromSchema\n >>> initializeObjectFromSchema(newContent, ITestContent, inputMessage)\n >>> newContent._text.raw\n- u\'Some \\xd8 plain text\'\n+ \'Some \\xd8 plain text\'\n >>> newContent._text.mimeType\n \'text/plain\'\n >>> newContent._text.outputMimeType\ndiff --git a/plone/app/textfield/marshaler.zcml b/plone/app/textfield/marshaler.zcml\nindex 06f20c8..f014b26 100644\n--- a/plone/app/textfield/marshaler.zcml\n+++ b/plone/app/textfield/marshaler.zcml\n@@ -1,6 +1,7 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n \ndiff --git a/plone/app/textfield/richtext_widget.rst b/plone/app/textfield/richtext_widget.rst\nindex ea12d85..18cf977 100644\n--- a/plone/app/textfield/richtext_widget.rst\n+++ b/plone/app/textfield/richtext_widget.rst\n@@ -48,12 +48,13 @@ We also need to register the template for at least the widget and request:\n If we render the widget we get the HTML:\n >>> widget.update()\n >>> print(widget.render())\n-
\n- \n-
\n- \n-
\n-
\n+
\n+ ...\n+ ...
\n+ ...\n+ ...
\n+ ...
\n+\n >>> from zope.component import getGlobalSiteManager\n >>> gsm = getGlobalSiteManager()\n >>> gsm.unregisterAdapter(factory,\ndiff --git a/plone/app/textfield/tests.py b/plone/app/textfield/tests.py\nindex 5fca07c..8fdbe53 100644\n--- a/plone/app/textfield/tests.py\n+++ b/plone/app/textfield/tests.py\n@@ -3,7 +3,6 @@\n \n import doctest\n import plone.app.textfield\n-import re\n import unittest\n \n \n@@ -346,14 +345,6 @@ def test_getSize(self):\n self.assertEqual(3, value.getSize())\n \n \n-class Py23DocChecker(doctest.OutputChecker):\n- def check_output(self, want, got, optionflags):\n- want = re.sub("u\'(.*?)\'", "\'\\\\1\'", want)\n- want = re.sub(\'u"(.*?)"\', \'"\\\\1"\', want)\n-\n- return doctest.OutputChecker.check_output(self, want, got, optionflags)\n-\n-\n class TestTextfield(unittest.TestCase):\n def test_getWysiwygEditor(self):\n from plone.app.textfield.utils import getWysiwygEditor\n@@ -380,7 +371,6 @@ def test_suite():\n doctest.DocFileSuite(\n doctestfile,\n optionflags=doctest.ELLIPSIS,\n- checker=Py23DocChecker(),\n ),\n layer=testing.PLONE_FIXTURE,\n )\ndiff --git a/plone/app/textfield/transform.zcml b/plone/app/textfield/transform.zcml\nindex f1d6cc1..82533f7 100644\n--- a/plone/app/textfield/transform.zcml\n+++ b/plone/app/textfield/transform.zcml\n@@ -1,6 +1,7 @@\n \n+ i18n_domain="plone.app.textfield"\n+ >\n \n \n+ xmlns:zcml="http://namespaces.zope.org/zcml"\n+ i18n_domain="plone.app.textfield"\n+ >\n \n+ file="meta.zcml"\n+ />\n \n \n \n \n+ interface=".widget.IRichTextWidget"\n+ />\n \n \n+ />\n \n+ />\n \n \n \n \n+ widget="z3c.form.interfaces.ITextAreaWidget"\n+ template="widget_textarea_display.pt"\n+ layer="plone.app.z3cform.interfaces.IPloneFormLayer"\n+ mode="display"\n+ />\n \n+ widget=".widget.IRichTextWidget"\n+ template="widget_display.pt"\n+ layer="plone.app.z3cform.interfaces.IPloneFormLayer"\n+ mode="display"\n+ />\n \n \ndiff --git a/plone/app/textfield/widget_display.pt b/plone/app/textfield/widget_display.pt\nindex e7c6911..3052ac8 100644\n--- a/plone/app/textfield/widget_display.pt\n+++ b/plone/app/textfield/widget_display.pt\n@@ -1,18 +1,25 @@\n-
\n+
\ndiff --git a/plone/app/textfield/widget_input.pt b/plone/app/textfield/widget_input.pt\nindex 9063160..640938d 100644\n--- a/plone/app/textfield/widget_input.pt\n+++ b/plone/app/textfield/widget_input.pt\n@@ -1,72 +1,90 @@\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 The WYSIWYG code\n-
\n-
\n+
\n+
\n \n
\ndiff --git a/plone/app/textfield/widget_textarea_display.pt b/plone/app/textfield/widget_textarea_display.pt\nindex 6298c41..ba5aa84 100644\n--- a/plone/app/textfield/widget_textarea_display.pt\n+++ b/plone/app/textfield/widget_textarea_display.pt\n@@ -1,28 +1,32 @@\n \n- \n+>\n+ \n \ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..9eb73f3 100644\n--- a/pyproject.toml\n+++ b/pyproject.toml\n@@ -1,3 +1,5 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [tool.towncrier]\n filename = "CHANGES.rst"\n directory = "news/"\n@@ -18,3 +20,43 @@ showcontent = true\n directory = "bugfix"\n name = "Bug fixes:"\n showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "internal"\n+name = "Internal:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "documentation"\n+name = "Documentation:"\n+showcontent = true\n+\n+[[tool.towncrier.type]]\n+directory = "tests"\n+name = "Tests"\n+showcontent = true\n+\n+[tool.isort]\n+profile = "plone"\n+\n+[tool.black]\n+target-version = ["py38"]\n+\n+[tool.dependencychecker]\n+Zope = [\n+ # Zope own provided namespaces\n+ \'App\', \'OFS\', \'Products.Five\', \'Products.OFSP\', \'Products.PageTemplates\',\n+ \'Products.SiteAccess\', \'Shared\', \'Testing\', \'ZPublisher\', \'ZTUtils\',\n+ \'Zope2\', \'webdav\', \'zmi\',\n+ # Zope dependencies\n+ \'Acquisition\', \'DateTime\', \'transaction\', \'zExceptions\', \'ZODB\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.deferredimport\', \'zope.event\',\n+ \'zope.exceptions\', \'zope.globalrequest\', \'zope.i18n\', \'zope.i18nmessageid\',\n+ \'zope.interface\', \'zope.lifecycleevent\', \'zope.location\', \'zope.publisher\',\n+ \'zope.schema\', \'zope.security\', \'zope.site\', \'zope.traversing\', \'AccessControl\',\n+]\n+\'plone.base\' = [\n+ \'AccessControl\', \'Products.BTreeFolder2\', \'Products.CMFCore\',\n+ \'Products.CMFDynamicViewFTI\', \'zope.deprecation\',\n+]\n+python-dateutil = [\'dateutil\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 000ba69..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,15 +1,23 @@\n-[check-manifest]\n-ignore =\n- *.cfg\n- bootstrap.py\n-\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [bdist_wheel]\n universal = 0\n \n-[isort]\n-# black compatible Plone isort rules:\n-profile = black\n-force_alphabetical_sort = True\n-force_single_line = True\n-lines_after_imports = 2\n+[flake8]\n+doctests = 1\n+ignore =\n+ # black takes care of line length\n+ E501,\n+ # black takes care of where to break lines\n+ W503,\n+ # black takes care of spaces within slicing (list[:])\n+ E203,\n+ # black takes care of spaces after commas\n+ E231,\n \n+[check-manifest]\n+ignore =\n+ .editorconfig\n+ .meta.toml\n+ .pre-commit-config.yaml\n+ tox.ini\ndiff --git a/tox.ini b/tox.ini\nnew file mode 100644\nindex 0000000..ca6fe32\n--- /dev/null\n+++ b/tox.ini\n@@ -0,0 +1,50 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[tox]\n+envlist =\n+ format\n+ lint\n+ test\n+\n+[testenv]\n+allowlist_externals =\n+ sh\n+\n+[testenv:format]\n+description = automatically reformat code\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a pyupgrade\n+ pre-commit run -a isort\n+ pre-commit run -a black\n+ pre-commit run -a zpretty\n+\n+[testenv:lint]\n+description = run linters that will help improve the code style\n+skip_install = true\n+deps =\n+ pre-commit\n+commands =\n+ pre-commit run -a\n+\n+[testenv:dependencies]\n+description = check if the package defines all its dependencies and generate a graph out of them\n+deps =\n+ z3c.dependencychecker==2.11\n+ pipdeptree==2.5.1\n+ graphviz # optional dependency of pipdeptree\n+commands =\n+ dependencychecker\n+ sh -c \'pipdeptree --exclude setuptools,wheel,pipdeptree,z3c.dependencychecker,zope.interface,zope.component --graph-output svg > dependencies.svg\'\n+\n+[testenv:test]\n+usedevelop = true\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --test-path={toxinidir} -s plone.app.textfield\n+extras =\n+ tests\n'