From cfc529bf1b20368d6f356ec957dc26454dddf073 Mon Sep 17 00:00:00 2001 From: jensens Date: Mon, 17 Apr 2023 18:13:32 +0200 Subject: [PATCH] [fc] Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:29:38+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/217771ae7909de34f4d4c80403e0d8762ff2e827 Configuring with plone/meta Files changed: A .editorconfig A .meta.toml A .pre-commit-config.yaml A news/5cc689e5.internal A tox.ini M pyproject.toml M setup.cfg Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:31:01+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/3260c06331f8135ca96cf6aef60b6b4023ef3e0e chore: pyupgrade Files changed: M src/plone/__init__.py M src/plone/folder/__init__.py M src/plone/folder/default.py M src/plone/folder/interfaces.py M src/plone/folder/nogopip.py M src/plone/folder/ordered.py M src/plone/folder/partial.py M src/plone/folder/testing.py M src/plone/folder/tests/benchmarks.py M src/plone/folder/tests/test_dict_interface.py M src/plone/folder/tests/test_integration.py M src/plone/folder/tests/test_ordering_adapters.py M src/plone/folder/tests/test_ordersupport.py M src/plone/folder/tests/test_partialordering.py M src/plone/folder/tests/test_unorderedordering.py M src/plone/folder/tests/test_webdav.py M src/plone/folder/tests/utils.py M src/plone/folder/unordered.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:31:13+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/4aaab78b30affe5697faac86d99484f142b58420 chore: isort Files changed: M setup.py M src/plone/folder/nogopip.py M src/plone/folder/ordered.py M src/plone/folder/partial.py M src/plone/folder/tests/test_integration.py M src/plone/folder/tests/test_partialordering.py M src/plone/folder/tests/test_unorderedordering.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:32:10+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/1431f6969c98f198cd91c17005afd0346cf0934d chore: black Files changed: M setup.py M src/plone/__init__.py M src/plone/folder/default.py M src/plone/folder/interfaces.py M src/plone/folder/nogopip.py M src/plone/folder/ordered.py M src/plone/folder/partial.py M src/plone/folder/testing.py M src/plone/folder/tests/benchmarks.py M src/plone/folder/tests/test_dict_interface.py M src/plone/folder/tests/test_integration.py M src/plone/folder/tests/test_ordering_adapters.py M src/plone/folder/tests/test_ordersupport.py M src/plone/folder/tests/test_partialordering.py M src/plone/folder/tests/test_unorderedordering.py M src/plone/folder/tests/test_webdav.py M src/plone/folder/tests/utils.py M src/plone/folder/unordered.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:32:29+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/6d9d88b2dda1854e2754e816f4adb82b2177a23d chore: zpretty Files changed: M src/plone/folder/configure.zcml Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:34:44+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/2571b9c23d7f0498c18cc92a12666edaf86265d1 chore: update trove classifiers Files changed: M setup.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:34:54+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/4ab86311378d1697bd7338feaa840d97db973090 feat: pyroma Files changed: M setup.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:35:18+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/0757ce34e6ad31623a9393bfc09f2a2c99b63c25 feat: codespell Files changed: M CHANGES.rst Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:36:29+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/982386460b2fe90bbe67038afde6aa5eedf60831 feat: drop six usage Files changed: M setup.py M src/plone/folder/default.py M src/plone/folder/partial.py M src/plone/folder/tests/test_ordersupport.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:37:36+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/808d296c9bd724d20790c613c2d4a736d1a4a0f9 feat: flake8 Files changed: M src/plone/folder/partial.py M src/plone/folder/tests/test_webdav.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:45:57+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/7807a50a8a1cb005a84de76fe1f7596ce1d1c165 fix: code is inside src folder Files changed: M tox.ini Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T14:46:15+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/ba99db564bbc0200f7009c9c16e59f6894f7277a feat: declare dependencies Files changed: M pyproject.toml M setup.py Repository: plone.folder Branch: refs/heads/master Date: 2023-04-15T15:36:25+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.folder/commit/445178f54700342af5ba48bb639f08fae5c22361 Add news entry Files changed: A news/1.breaking Repository: plone.folder Branch: refs/heads/master Date: 2023-04-17T18:13:32+02:00 Author: Jens W. Klein (jensens) Commit: https://github.com/plone/plone.folder/commit/cc9eeed92f75a5bd0ffe9f1ae59e6fb32ed1dc76 Merge pull request #18 from plone/config-with-default-template-dc2e2aa0 Config with default template Files changed: A .editorconfig A .meta.toml A .pre-commit-config.yaml A news/1.breaking A news/5cc689e5.internal A tox.ini M CHANGES.rst M pyproject.toml M setup.cfg M setup.py M src/plone/__init__.py M src/plone/folder/__init__.py M src/plone/folder/configure.zcml M src/plone/folder/default.py M src/plone/folder/interfaces.py M src/plone/folder/nogopip.py M src/plone/folder/ordered.py M src/plone/folder/partial.py M src/plone/folder/testing.py M src/plone/folder/tests/benchmarks.py M src/plone/folder/tests/test_dict_interface.py M src/plone/folder/tests/test_integration.py M src/plone/folder/tests/test_ordering_adapters.py M src/plone/folder/tests/test_ordersupport.py M src/plone/folder/tests/test_partialordering.py M src/plone/folder/tests/test_unorderedordering.py M src/plone/folder/tests/test_webdav.py M src/plone/folder/tests/utils.py M src/plone/folder/unordered.py --- last_commit.txt | 269 ++++++++++++++++++++++++++++-------------------- 1 file changed, 158 insertions(+), 111 deletions(-) diff --git a/last_commit.txt b/last_commit.txt index b2dba92e07..e64efc6661 100644 --- a/last_commit.txt +++ b/last_commit.txt @@ -1,10 +1,10 @@ -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:10:11+02:00 +Date: 2023-04-15T14:29:38+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/4ffbbcab695ac0a508dfdfa650b3433be4960c1c +Commit: https://github.com/plone/plone.folder/commit/217771ae7909de34f4d4c80403e0d8762ff2e827 Configuring with plone/meta @@ -13,202 +13,246 @@ A .editorconfig A .meta.toml A .pre-commit-config.yaml A news/5cc689e5.internal +A tox.ini M pyproject.toml M setup.cfg -M tox.ini -D .travis.yml -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..1b2346d\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 = "5cc689e5"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..fdafec1\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.3.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.3\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.4\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/.travis.yml b/.travis.yml\ndeleted file mode 100644\nindex afff7e4..0000000\n--- a/.travis.yml\n+++ /dev/null\n@@ -1,12 +0,0 @@\n-language: python\n-python:\n- - 2.7\n- - 3.6\n- - 3.7\n- - 3.8\n-install:\n- - pip install tox-travis\n-script:\n- - tox\n-notifications:\n- email: false\ndiff --git a/news/5cc689e5.internal b/news/5cc689e5.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/5cc689e5.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..92c3af9 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,64 @@ 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+ # ExtensionClass own provided namespaces\n+ \'ExtensionClass\', \'ComputedAttribute\', \'MethodObject\',\n+ # Zope dependencies\n+ \'AccessControl\', \'Acquisition\', \'AuthEncoding\', \'beautifulsoup4\', \'BTrees\',\n+ \'cffi\', \'Chameleon\', \'DateTime\', \'DocumentTemplate\',\n+ \'MultiMapping\', \'multipart\', \'PasteDeploy\', \'Persistence\', \'persistent\',\n+ \'pycparser\', \'python-gettext\', \'pytz\', \'RestrictedPython\', \'roman\', \'six\',\n+ \'soupsieve\', \'transaction\', \'waitress\', \'WebOb\', \'WebTest\', \'WSGIProxy2\',\n+ \'z3c.pt\', \'zc.lockfile\', \'ZConfig\', \'zExceptions\', \'ZODB\', \'zodbpickle\',\n+ \'zope.annotation\', \'zope.browser\', \'zope.browsermenu\', \'zope.browserpage\',\n+ \'zope.browserresource\', \'zope.cachedescriptors\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.contentprovider\',\n+ \'zope.contenttype\', \'zope.datetime\', \'zope.deferredimport\',\n+ \'zope.deprecation\', \'zope.dottedname\', \'zope.event\', \'zope.exceptions\',\n+ \'zope.filerepresentation\', \'zope.globalrequest\', \'zope.hookable\',\n+ \'zope.i18n\', \'zope.i18nmessageid\', \'zope.interface\', \'zope.lifecycleevent\',\n+ \'zope.location\', \'zope.pagetemplate\', \'zope.processlifetime\', \'zope.proxy\',\n+ \'zope.ptresource\', \'zope.publisher\', \'zope.schema\', \'zope.security\',\n+ \'zope.sequencesort\', \'zope.site\', \'zope.size\', \'zope.structuredtext\',\n+ \'zope.tal\', \'zope.tales\', \'zope.testbrowser\', \'zope.testing\',\n+ \'zope.traversing\', \'zope.viewlet\'\n+]\n+\'Products.CMFCore\' = [\n+ \'docutils\', \'five.localsitemanager\', \'Missing\', \'Products.BTreeFolder2\',\n+ \'Products.GenericSetup\', \'Products.MailHost\', \'Products.PythonScripts\',\n+ \'Products.StandardCacheManagers\', \'Products.ZCatalog\', \'Record\',\n+ \'zope.sendmail\', \'Zope\'\n+]\n+\'plone.base\' = [\n+ \'plone.batching\', \'plone.registry\', \'plone.schema\',\'plone.z3cform\',\n+ \'Products.CMFCore\', \'Products.CMFDynamicViewFTI\',\n+]\n+python-dateutil = [\'dateutil\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 3ee2840..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,9 +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\n-\n-[bdist_wheel]\n-universal = 1\n-\n-[zest.releaser]\n-create-wheel = yes\ndiff --git a/tox.ini b/tox.ini\nindex 5b2fe14..c4521cf 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -1,10 +1,68 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [tox]\n+# We need 4.4.0 for constrain_package_deps.\n+min_version = 4.4.0\n envlist =\n- py27,py36,py37,py38\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+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --all --test-path={toxinidir} -s plone.event {posargs}\n+extras =\n+ test\n+\n+[testenv:coverage]\n+usedevelop = true\n+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n deps =\n+ coverage\n zope.testrunner\n- .[test]\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n commands =\n- zope-testrunner --test-path=. {posargs:-pvc}\n+ coverage run {envbindir}/zope-testrunner --all --test-path={toxinidir} -s plone.event {posargs}\n+ coverage report -m --format markdown\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..1b2346d\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 = "5cc689e5"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..fdafec1\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.3.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.3\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.4\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/5cc689e5.internal b/news/5cc689e5.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/5cc689e5.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..92c3af9 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,64 @@ 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+ # ExtensionClass own provided namespaces\n+ \'ExtensionClass\', \'ComputedAttribute\', \'MethodObject\',\n+ # Zope dependencies\n+ \'AccessControl\', \'Acquisition\', \'AuthEncoding\', \'beautifulsoup4\', \'BTrees\',\n+ \'cffi\', \'Chameleon\', \'DateTime\', \'DocumentTemplate\',\n+ \'MultiMapping\', \'multipart\', \'PasteDeploy\', \'Persistence\', \'persistent\',\n+ \'pycparser\', \'python-gettext\', \'pytz\', \'RestrictedPython\', \'roman\', \'six\',\n+ \'soupsieve\', \'transaction\', \'waitress\', \'WebOb\', \'WebTest\', \'WSGIProxy2\',\n+ \'z3c.pt\', \'zc.lockfile\', \'ZConfig\', \'zExceptions\', \'ZODB\', \'zodbpickle\',\n+ \'zope.annotation\', \'zope.browser\', \'zope.browsermenu\', \'zope.browserpage\',\n+ \'zope.browserresource\', \'zope.cachedescriptors\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.contentprovider\',\n+ \'zope.contenttype\', \'zope.datetime\', \'zope.deferredimport\',\n+ \'zope.deprecation\', \'zope.dottedname\', \'zope.event\', \'zope.exceptions\',\n+ \'zope.filerepresentation\', \'zope.globalrequest\', \'zope.hookable\',\n+ \'zope.i18n\', \'zope.i18nmessageid\', \'zope.interface\', \'zope.lifecycleevent\',\n+ \'zope.location\', \'zope.pagetemplate\', \'zope.processlifetime\', \'zope.proxy\',\n+ \'zope.ptresource\', \'zope.publisher\', \'zope.schema\', \'zope.security\',\n+ \'zope.sequencesort\', \'zope.site\', \'zope.size\', \'zope.structuredtext\',\n+ \'zope.tal\', \'zope.tales\', \'zope.testbrowser\', \'zope.testing\',\n+ \'zope.traversing\', \'zope.viewlet\'\n+]\n+\'Products.CMFCore\' = [\n+ \'docutils\', \'five.localsitemanager\', \'Missing\', \'Products.BTreeFolder2\',\n+ \'Products.GenericSetup\', \'Products.MailHost\', \'Products.PythonScripts\',\n+ \'Products.StandardCacheManagers\', \'Products.ZCatalog\', \'Record\',\n+ \'zope.sendmail\', \'Zope\'\n+]\n+\'plone.base\' = [\n+ \'plone.batching\', \'plone.registry\', \'plone.schema\',\'plone.z3cform\',\n+ \'Products.CMFCore\', \'Products.CMFDynamicViewFTI\',\n+]\n+python-dateutil = [\'dateutil\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 3e97765..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,9 +1,23 @@\n-[check-manifest]\n-ignore =\n- bootstrap.py\n- *.cfg\n-\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-[bdist_wheel]\n-universal = 1\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..c5e3f4f\n--- /dev/null\n+++ b/tox.ini\n@@ -0,0 +1,68 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[tox]\n+# We need 4.4.0 for constrain_package_deps.\n+min_version = 4.4.0\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+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --all --test-path={toxinidir} -s plone.folder {posargs}\n+extras =\n+ test\n+\n+[testenv:coverage]\n+usedevelop = true\n+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n+deps =\n+ coverage\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ coverage run {envbindir}/zope-testrunner --all --test-path={toxinidir} -s plone.folder {posargs}\n+ coverage report -m --format markdown\n+extras =\n+ test\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:12:15+02:00 +Date: 2023-04-15T14:31:01+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/4a341632aac6ac2cbd2cb5456013e3e2918de1ba +Commit: https://github.com/plone/plone.folder/commit/3260c06331f8135ca96cf6aef60b6b4023ef3e0e chore: pyupgrade Files changed: -M plone/__init__.py -M plone/event/adapters.py -M plone/event/interfaces.py -M plone/event/recurrence.py -M plone/event/tests/test_adapters.py -M plone/event/tests/test_doctest.py -M plone/event/tests/test_recurrence_int_sequence.py -M plone/event/tests/test_recurrence_sequence_ical.py -M plone/event/tests/test_recurrence_sequence_timedelta.py -M plone/event/tests/test_utils.py -M plone/event/utils.py +M src/plone/__init__.py +M src/plone/folder/__init__.py +M src/plone/folder/default.py +M src/plone/folder/interfaces.py +M src/plone/folder/nogopip.py +M src/plone/folder/ordered.py +M src/plone/folder/partial.py +M src/plone/folder/testing.py +M src/plone/folder/tests/benchmarks.py +M src/plone/folder/tests/test_dict_interface.py +M src/plone/folder/tests/test_integration.py +M src/plone/folder/tests/test_ordering_adapters.py +M src/plone/folder/tests/test_ordersupport.py +M src/plone/folder/tests/test_partialordering.py +M src/plone/folder/tests/test_unorderedordering.py +M src/plone/folder/tests/test_webdav.py +M src/plone/folder/tests/utils.py +M src/plone/folder/unordered.py + +b'diff --git a/src/plone/__init__.py b/src/plone/__init__.py\nindex 68c04af..de40ea7 100644\n--- a/src/plone/__init__.py\n+++ b/src/plone/__init__.py\n@@ -1,2 +1 @@\n-# -*- coding: utf-8 -*-\n __import__(\'pkg_resources\').declare_namespace(__name__)\ndiff --git a/src/plone/folder/__init__.py b/src/plone/folder/__init__.py\nindex 40a96af..e69de29 100644\n--- a/src/plone/folder/__init__.py\n+++ b/src/plone/folder/__init__.py\n@@ -1 +0,0 @@\n-# -*- coding: utf-8 -*-\ndiff --git a/src/plone/folder/default.py b/src/plone/folder/default.py\nindex 84d4c8d..7294f66 100644\n--- a/src/plone/folder/default.py\n+++ b/src/plone/folder/default.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from BTrees.OIBTree import OIBTree\n from persistent.list import PersistentList\n from plone.folder.interfaces import IExplicitOrdering\n@@ -13,7 +12,7 @@\n \n @implementer(IExplicitOrdering)\n @adapter(IOrderableFolder)\n-class DefaultOrdering(object):\n+class DefaultOrdering:\n """ This implementation uses annotations to store the order on the\n object, and supports explicit ordering. """\n \n@@ -55,7 +54,7 @@ def moveObjectsByDelta(\n order = self._order()\n pos = self._pos()\n min_position = 0\n- if isinstance(ids, six.string_types):\n+ if isinstance(ids, str):\n ids = [ids]\n if subset_ids is None:\n subset_ids = self.idsInOrder()\n@@ -95,7 +94,7 @@ def moveObjectsByDelta(\n idx += 1\n except KeyError:\n raise ValueError(\n- \'No object with id "{0:s}" exists.\'.format(obj_id)\n+ f\'No object with id "{obj_id:s}" exists.\'\n )\n if not suppress_events:\n notifyContainerModified(self.context)\n@@ -155,7 +154,7 @@ def getObjectPosition(self, obj_id):\n pos = self._pos()\n if obj_id in pos:\n return pos[obj_id]\n- raise ValueError(\'No object with id "{0:s}" exists in "{1:s}".\'.format(\n+ raise ValueError(\'No object with id "{:s}" exists in "{:s}".\'.format(\n obj_id, \'/\'.join(self.context.getPhysicalPath())))\n \n def idsInOrder(self):\ndiff --git a/src/plone/folder/interfaces.py b/src/plone/folder/interfaces.py\nindex 4f5fef4..2a73a21 100644\n--- a/src/plone/folder/interfaces.py\n+++ b/src/plone/folder/interfaces.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from zope.interface import Interface\n \n \n@@ -16,7 +15,7 @@ class IOrderableFolder(IFolder):\n def getOrdering():\n """ return the currently active ordering adapter for this folder """\n \n- def setOrdering(ordering=u\'\'):\n+ def setOrdering(ordering=\'\'):\n """ (re)set ordering adapter to be used for this folder """\n \n \ndiff --git a/src/plone/folder/nogopip.py b/src/plone/folder/nogopip.py\nindex 24d6d2d..e89eec2 100644\n--- a/src/plone/folder/nogopip.py\n+++ b/src/plone/folder/nogopip.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import aq_base\n from App.special_dtml import DTMLFile\n from inspect import currentframe\n@@ -72,7 +71,7 @@ class GopipIndex(StubIndex):\n keyForDocument = 42\n \n def __init__(self, id, extra=None, caller=None):\n- super(GopipIndex, self).__init__(id)\n+ super().__init__(id)\n self.catalog = aq_base(caller._catalog)\n \n def __len__(self):\ndiff --git a/src/plone/folder/ordered.py b/src/plone/folder/ordered.py\nindex fac2cd6..c7a7882 100644\n--- a/src/plone/folder/ordered.py\n+++ b/src/plone/folder/ordered.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from AccessControl import ClassSecurityInfo\n from AccessControl.Permissions import access_contents_information\n from AccessControl.Permissions import manage_properties\n@@ -33,7 +32,7 @@ class OrderedBTreeFolderBase(BTreeFolder2Base):\n is done by a named adapter (to IOrdering), which makes the policy\n changeable. """\n \n- _ordering = u\'\' # name of adapter defining ordering policy\n+ _ordering = \'\' # name of adapter defining ordering policy\n \n security = ClassSecurityInfo()\n \n@@ -50,7 +49,7 @@ def getOrdering(self):\n return adapter\n \n @security.protected(manage_properties)\n- def setOrdering(self, ordering=u\'\'):\n+ def setOrdering(self, ordering=\'\'):\n """ (re)set ordering adapter to be used for this folder """\n if ordering:\n # make sure the adapter exists...\n@@ -62,28 +61,28 @@ def setOrdering(self, ordering=u\'\'):\n def _getOb(self, id, default=_marker):\n """ Return the named object from the folder. """\n try:\n- return super(OrderedBTreeFolderBase, self)._getOb(id, default)\n+ return super()._getOb(id, default)\n except KeyError as e:\n raise AttributeError(e)\n \n def _setOb(self, id, object):\n """ Store the named object in the folder. """\n- super(OrderedBTreeFolderBase, self)._setOb(id, object)\n+ super()._setOb(id, object)\n self.getOrdering().notifyAdded(id) # notify the ordering adapter\n \n def _delOb(self, id):\n """ Remove the named object from the folder. """\n- super(OrderedBTreeFolderBase, self)._delOb(id)\n+ super()._delOb(id)\n self.getOrdering().notifyRemoved(id) # notify the ordering adapter\n \n def objectIds(self, spec=None, ordered=True):\n if not ordered:\n- return super(OrderedBTreeFolderBase, self).objectIds(spec)\n+ return super().objectIds(spec)\n ordering = self.getOrdering()\n if spec is None:\n return ordering.idsInOrder()\n else:\n- ids = super(OrderedBTreeFolderBase, self).objectIds(spec)\n+ ids = super().objectIds(spec)\n idxs = []\n for id in ids:\n idxs.append((ordering.getObjectPosition(id), id))\n@@ -196,7 +195,7 @@ def iterkeys(self):\n def manage_renameObject(self, id, new_id, REQUEST=None):\n """ Rename a particular sub-object without changing its position. """\n old_position = self.getObjectPosition(id)\n- result = super(OrderedBTreeFolderBase, self).manage_renameObject(\n+ result = super().manage_renameObject(\n id,\n new_id,\n REQUEST\ndiff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex 5ef625d..d4a59ff 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -14,7 +14,7 @@\n \n \n @implementer(IExplicitOrdering)\n-class PartialOrdering(object):\n+class PartialOrdering:\n """ this implementation uses a list to store order information on a\n regular attribute of the folderish object; explicit ordering\n is supported """\n@@ -70,7 +70,7 @@ def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n suppress_events=False):\n """ see interfaces.py """\n min_position = 0\n- if isinstance(ids, six.string_types):\n+ if isinstance(ids, str):\n ids = [ids]\n if subset_ids is None:\n subset_ids = self.idsInOrder(onlyOrderables=True)\ndiff --git a/src/plone/folder/testing.py b/src/plone/folder/testing.py\nindex b14476f..4afd1ac 100644\n--- a/src/plone/folder/testing.py\n+++ b/src/plone/folder/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/src/plone/folder/tests/benchmarks.py b/src/plone/folder/tests/benchmarks.py\nindex ab36afd..9ae703d 100644\n--- a/src/plone/folder/tests/benchmarks.py\n+++ b/src/plone/folder/tests/benchmarks.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n # simple benchmarking tests related to plip191\n # to run individual tests using:\n # $ bin/instance test -s plone.folder --tests-pattern=benchmarks -t \n@@ -8,7 +7,6 @@\n from plone.folder.tests.layer import PloneFolderLayer\n from plone.folder.tests.utils import DummyObject\n from profilehooks import timecall\n-from six.moves import range\n from unittest import defaultTestLoader\n from unittest import TestCase\n \ndiff --git a/src/plone/folder/tests/test_dict_interface.py b/src/plone/folder/tests/test_dict_interface.py\nindex 5917e88..d71a7a7 100644\n--- a/src/plone/folder/tests/test_dict_interface.py\n+++ b/src/plone/folder/tests/test_dict_interface.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import aq_base\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n@@ -37,19 +36,19 @@ def test_delitem(self):\n folder = OrderedBTreeFolderBase("f1")\n folder._setOb(\'foo\', DummyObject(\'foo\'))\n folder._setOb(\'bar\', DummyObject(\'bar\'))\n- self.assertEquals(len(folder.objectIds()), 2)\n+ self.assertEqual(len(folder.objectIds()), 2)\n del folder[\'foo\']\n del folder[\'bar\']\n- self.assertEquals(len(folder.objectIds()), 0)\n+ self.assertEqual(len(folder.objectIds()), 0)\n \n def test_len_empty_folder(self):\n folder = OrderedBTreeFolderBase("f1")\n- self.assertEquals(len(folder), 0)\n+ self.assertEqual(len(folder), 0)\n \n def test_len_one_child(self):\n folder = OrderedBTreeFolderBase("f1")\n folder[\'child\'] = DummyObject(\'child\')\n- self.assertEquals(len(folder), 1)\n+ self.assertEqual(len(folder), 1)\n \n def test_to_verify_ticket_9120(self):\n folder = OrderedBTreeFolderBase("f1")\n@@ -59,9 +58,9 @@ def test_to_verify_ticket_9120(self):\n folder[\'ob4\'] = ob4 = DummyObject(\'ob4\')\n del folder[\'ob2\']\n del folder[\'ob3\']\n- self.assertEquals(folder.keys(), [\'ob1\', \'ob4\'])\n- self.assertEquals(list(map(aq_base, folder.values())), [ob1, ob4])\n- self.assertEquals([key in folder for key in folder], [True, True])\n+ self.assertEqual(folder.keys(), [\'ob1\', \'ob4\'])\n+ self.assertEqual(list(map(aq_base, folder.values())), [ob1, ob4])\n+ self.assertEqual([key in folder for key in folder], [True, True])\n \n \n class RelatedToDictInterfaceTests(unittest.TestCase):\n@@ -79,9 +78,9 @@ def create(self):\n \n def testObjectIdsWithSpec(self):\n folder = self.create()\n- self.assertEquals([\'o1\', \'o3\'], folder.objectIds(spec=\'mt1\'))\n- self.assertEquals([\'o2\', \'o4\'], folder.objectIds(spec=\'mt2\'))\n+ self.assertEqual([\'o1\', \'o3\'], folder.objectIds(spec=\'mt1\'))\n+ self.assertEqual([\'o2\', \'o4\'], folder.objectIds(spec=\'mt2\'))\n folder.moveObjectsToTop([\'o3\'])\n folder.moveObjectsDown([\'o2\'])\n- self.assertEquals([\'o3\', \'o1\'], folder.objectIds(spec=\'mt1\'))\n- self.assertEquals([\'o4\', \'o2\'], folder.objectIds(spec=\'mt2\'))\n+ self.assertEqual([\'o3\', \'o1\'], folder.objectIds(spec=\'mt1\'))\n+ self.assertEqual([\'o4\', \'o2\'], folder.objectIds(spec=\'mt2\'))\ndiff --git a/src/plone/folder/tests/test_integration.py b/src/plone/folder/tests/test_integration.py\nindex 959c627..6bc4414 100644\n--- a/src/plone/folder/tests/test_integration.py\n+++ b/src/plone/folder/tests/test_integration.py\n@@ -1,9 +1,8 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import Implicit\n from plone.folder.interfaces import IOrderable\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_FUNCTIONAL_TESTING\n-from six import BytesIO\n+from io import BytesIO\n from transaction import savepoint\n from zope.interface import implementer\n \ndiff --git a/src/plone/folder/tests/test_ordering_adapters.py b/src/plone/folder/tests/test_ordering_adapters.py\nindex 3efe323..c12d7f7 100644\n--- a/src/plone/folder/tests/test_ordering_adapters.py\n+++ b/src/plone/folder/tests/test_ordering_adapters.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.folder.default import DefaultOrdering\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\ndiff --git a/src/plone/folder/tests/test_ordersupport.py b/src/plone/folder/tests/test_ordersupport.py\nindex 0808e1b..8a7208f 100644\n--- a/src/plone/folder/tests/test_ordersupport.py\n+++ b/src/plone/folder/tests/test_ordersupport.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from OFS.Traversable import Traversable\n from plone.folder.interfaces import IOrdering\n from plone.folder.ordered import OrderedBTreeFolderBase\n@@ -33,59 +32,59 @@ def create(self):\n \n def test_objectIdsOrdered(self):\n folder = self.create()\n- self.assertEquals(["o1", "o2", "o3", "o4"], folder.objectIds())\n+ self.assertEqual(["o1", "o2", "o3", "o4"], folder.objectIds())\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(["o2", "o1", "o3", "o4"], folder.objectIds())\n+ self.assertEqual(["o2", "o1", "o3", "o4"], folder.objectIds())\n \n def test_objectValuesOrdered(self):\n folder = self.create()\n- self.assertEquals(\n+ self.assertEqual(\n ["o1", "o2", "o3", "o4"],\n [x.id for x in folder.objectValues()]\n )\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(\n+ self.assertEqual(\n ["o2", "o1", "o3", "o4"],\n [x.id for x in folder.objectValues()]\n )\n \n def test_objectItemsOrdered(self):\n folder = self.create()\n- self.assertEquals(\n+ self.assertEqual(\n ["o1", "o2", "o3", "o4"],\n [x for x, y in folder.objectItems()]\n )\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(\n+ self.assertEqual(\n ["o2", "o1", "o3", "o4"],\n [x for x, y in folder.objectItems()]\n )\n \n def test_iterkeys(self):\n folder = self.create()\n- self.assertEquals(\n+ self.assertEqual(\n ["o1", "o2", "o3", "o4"],\n- [x for x in six.iterkeys(folder)]\n+ [x for x in folder.keys()]\n )\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(\n+ self.assertEqual(\n ["o2", "o1", "o3", "o4"],\n- [x for x in six.iterkeys(folder)]\n+ [x for x in folder.keys()]\n )\n \n def test_iter(self):\n folder = self.create()\n- self.assertEquals(["o1", "o2", "o3", "o4"], [x for x in folder])\n+ self.assertEqual(["o1", "o2", "o3", "o4"], [x for x in folder])\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(["o2", "o1", "o3", "o4"], [x for x in folder])\n+ self.assertEqual(["o2", "o1", "o3", "o4"], [x for x in folder])\n \n def test_getitem(self):\n ordering = IOrdering(self.create())\n- self.assertEquals(ordering[1], \'o2\')\n- self.assertEquals(ordering[-1], \'o4\')\n- self.assertEquals(ordering[1:2], [\'o2\'])\n- self.assertEquals(ordering[1:-1], [\'o2\', \'o3\'])\n- self.assertEquals(ordering[1:], [\'o2\', \'o3\', \'o4\'])\n+ self.assertEqual(ordering[1], \'o2\')\n+ self.assertEqual(ordering[-1], \'o4\')\n+ self.assertEqual(ordering[1:2], [\'o2\'])\n+ self.assertEqual(ordering[1:-1], [\'o2\', \'o3\'])\n+ self.assertEqual(ordering[1:], [\'o2\', \'o3\', \'o4\'])\n \n # Tests borrowed from OFS.tests.testsOrderSupport\n \ndiff --git a/src/plone/folder/tests/test_partialordering.py b/src/plone/folder/tests/test_partialordering.py\nindex 8468c63..fe0dba7 100644\n--- a/src/plone/folder/tests/test_partialordering.py\n+++ b/src/plone/folder/tests/test_partialordering.py\n@@ -18,7 +18,7 @@ class PartialOrderingTests(unittest.TestCase):\n \n def create(self):\n container = OrderedBTreeFolderBase()\n- container.setOrdering(u\'partial\')\n+ container.setOrdering(\'partial\')\n container[\'o1\'] = Orderable(\'o1\', \'mt1\')\n container[\'o2\'] = Orderable(\'o2\', \'mt2\')\n container[\'c1\'] = Chaoticle(\'c1\', \'mt3\')\n@@ -47,7 +47,7 @@ def testNotifyAdded(self):\n )\n self.assertEqual(\n set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\', \'o5\', \'c1\', \'c2\', \'c3\'])\n+ {\'o1\', \'o2\', \'o3\', \'o4\', \'o5\', \'c1\', \'c2\', \'c3\'}\n )\n \n def testNotifyRemoved(self):\n@@ -63,7 +63,7 @@ def testNotifyRemoved(self):\n )\n self.assertEqual(\n set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o4\', \'c1\', \'c2\', \'c3\'])\n+ {\'o1\', \'o2\', \'o4\', \'c1\', \'c2\', \'c3\'}\n )\n container._delOb(\'o1\')\n self.assertEqual(\n@@ -72,7 +72,7 @@ def testNotifyRemoved(self):\n )\n self.assertEqual(\n set(container.objectIds()),\n- set([\'o2\', \'o4\', \'c1\', \'c2\', \'c3\'])\n+ {\'o2\', \'o4\', \'c1\', \'c2\', \'c3\'}\n )\n \n def runTableTests(self, action, tests):\n@@ -194,7 +194,7 @@ class DummyFolder(OrderedBTreeFolderBase, Implicit):\n """ we need to mix in acquisition """\n \n meta_type = \'DummyFolder\'\n- _ordering = u\'partial\'\n+ _ordering = \'partial\'\n \n def dummy_method(self):\n return self.id\ndiff --git a/src/plone/folder/tests/test_unorderedordering.py b/src/plone/folder/tests/test_unorderedordering.py\nindex bfeb54e..9165b6f 100644\n--- a/src/plone/folder/tests/test_unorderedordering.py\n+++ b/src/plone/folder/tests/test_unorderedordering.py\n@@ -13,7 +13,7 @@ class UnorderedOrderingTests(unittest.TestCase):\n \n def create(self):\n container = OrderedBTreeFolderBase()\n- container._ordering = u\'unordered\'\n+ container._ordering = \'unordered\'\n container._setOb(\'o1\', DummyObject(\'o1\', \'mt1\'))\n container._setOb(\'o2\', DummyObject(\'o2\', \'mt2\'))\n container._setOb(\'o3\', DummyObject(\'o3\', \'mt1\'))\n@@ -29,24 +29,24 @@ def testNotifyAdded(self):\n container = self.create()\n self.assertEqual(\n set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\'])\n+ {\'o1\', \'o2\', \'o3\', \'o4\'}\n )\n container._setOb(\'o5\', DummyObject(\'o5\', \'mt1\'))\n self.assertEqual(\n set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\', \'o5\'])\n+ {\'o1\', \'o2\', \'o3\', \'o4\', \'o5\'}\n )\n \n def testNotifyRemoved(self):\n container = self.create()\n self.assertEqual(\n set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\'])\n+ {\'o1\', \'o2\', \'o3\', \'o4\'}\n )\n container._delOb(\'o3\')\n self.assertEqual(\n set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o4\'])\n+ {\'o1\', \'o2\', \'o4\'}\n )\n \n def testGetObjectPosition(self):\ndiff --git a/src/plone/folder/tests/test_webdav.py b/src/plone/folder/tests/test_webdav.py\nindex 05b8da0..7f2cb18 100644\n--- a/src/plone/folder/tests/test_webdav.py\n+++ b/src/plone/folder/tests/test_webdav.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import Explicit\n from plone.folder.ordered import CMFOrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n@@ -36,7 +35,7 @@ def test_getitem_not_dav_request(self):\n foo = DummyObject(\'foo\')\n folder[\'foo\'] = foo\n \n- self.assertEquals(folder[\'foo\'], foo)\n+ self.assertEqual(folder[\'foo\'], foo)\n try:\n folder[\'bar\']\n self.fail()\n@@ -54,5 +53,5 @@ def test_getitem_dav_request(self):\n foo = DummyObject(\'foo\')\n folder[\'foo\'] = foo\n \n- self.assertEquals(folder[\'foo\'], foo)\n+ self.assertEqual(folder[\'foo\'], foo)\n self.assertTrue(isinstance(folder[\'bar\'], NullResource))\ndiff --git a/src/plone/folder/tests/utils.py b/src/plone/folder/tests/utils.py\nindex 5c2015b..d81e2e9 100644\n--- a/src/plone/folder/tests/utils.py\n+++ b/src/plone/folder/tests/utils.py\n@@ -1,9 +1,8 @@\n-# -*- coding: utf-8 -*-\n from plone.folder.interfaces import IOrderable\n from zope.interface import implementer\n \n \n-class DummyObject(object):\n+class DummyObject:\n \n def __init__(self, id, meta_type=None):\n self.id = id\ndiff --git a/src/plone/folder/unordered.py b/src/plone/folder/unordered.py\nindex 14d9ae8..ea82a74 100644\n--- a/src/plone/folder/unordered.py\n+++ b/src/plone/folder/unordered.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import aq_base\n from plone.folder.interfaces import IOrderableFolder\n from plone.folder.interfaces import IOrdering\n@@ -8,7 +7,7 @@\n \n @implementer(IOrdering)\n @adapter(IOrderableFolder)\n-class UnorderedOrdering(object):\n+class UnorderedOrdering:\n """ This implementation provides no ordering. """\n \n def __init__(self, context):\n' + +Repository: plone.folder + + +Branch: refs/heads/master +Date: 2023-04-15T14:31:13+02:00 +Author: Gil Forcada Codinachs (gforcada) +Commit: https://github.com/plone/plone.folder/commit/4aaab78b30affe5697faac86d99484f142b58420 + +chore: isort + +Files changed: M setup.py +M src/plone/folder/nogopip.py +M src/plone/folder/ordered.py +M src/plone/folder/partial.py +M src/plone/folder/tests/test_integration.py +M src/plone/folder/tests/test_partialordering.py +M src/plone/folder/tests/test_unorderedordering.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/event/adapters.py b/plone/event/adapters.py\nindex 717657a..2ce3afc 100644\n--- a/plone/event/adapters.py\n+++ b/plone/event/adapters.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.event.interfaces import IEvent\n from plone.event.interfaces import IEventAccessor\n from zope.component import adapter\n@@ -7,7 +6,7 @@\n \n @implementer(IEventAccessor)\n @adapter(IEvent)\n-class EventAccessor(object):\n+class EventAccessor:\n """Simple event accessor adapter implementation for generic events, which\n follow the IEvent interface closely.\n \ndiff --git a/plone/event/interfaces.py b/plone/event/interfaces.py\nindex fa88995..8dc85bc 100644\n--- a/plone/event/interfaces.py\n+++ b/plone/event/interfaces.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from zope.interface import Attribute\n from zope.interface import Interface\n \n@@ -21,8 +20,8 @@ class IOccurrence(Interface):\n occurrence.\n \n """\n- start = Attribute(u\'Occurrence start date\')\n- end = Attribute(u\'Occurrence end date\')\n+ start = Attribute(\'Occurrence start date\')\n+ end = Attribute(\'Occurrence end date\')\n \n \n class ICalendarAccessor(Interface):\n@@ -31,11 +30,11 @@ class ICalendarAccessor(Interface):\n A calendar is a collection of calendar components, like events.\n \n """\n- uid = Attribute(u\'UID of the calendar. Autogenerated, read only.\')\n+ uid = Attribute(\'UID of the calendar. Autogenerated, read only.\')\n # rw attributes\n- title = Attribute(u\'Calendar title.\')\n- description = Attribute(u\'Calendar description text.\')\n- timezone = Attribute(u\'Default timezone of the calendar.\')\n+ title = Attribute(\'Calendar title.\')\n+ description = Attribute(\'Calendar description text.\')\n+ timezone = Attribute(\'Default timezone of the calendar.\')\n \n def items(self):\n """Return a list of calendar component items, like events.\n@@ -52,34 +51,34 @@ class IEventAccessor(Interface):\n """\n \n # ro attributes\n- uid = Attribute(u\'UID of the event. Autogenerated, read only.\')\n- created = Attribute(u\'Python datetime of the event creation timestamp.\')\n- duration = Attribute(u\'Duration of the event. Computed attribute.\')\n+ uid = Attribute(\'UID of the event. Autogenerated, read only.\')\n+ created = Attribute(\'Python datetime of the event creation timestamp.\')\n+ duration = Attribute(\'Duration of the event. Computed attribute.\')\n \n # reference\n url = Attribute(\n- u\'Cannonical, unique url of the event. External events \'\n- u\'are referenced by the origin url unless explicitly set.\'\n+ \'Cannonical, unique url of the event. External events \'\n+ \'are referenced by the origin url unless explicitly set.\'\n )\n \n # rw attributes\n- last_modified = Attribute(u\'Last modified Python datetime.\')\n- title = Attribute(u\'Event title.\')\n- description = Attribute(u\'Event description text.\')\n- start = Attribute(u\'Event start date as Python datetime.\')\n- end = Attribute(u\'Event end date as Python datetime.\')\n- whole_day = Attribute(u\'Event lasts whole day.\')\n- open_end = Attribute(u\'Event has no defined end time.\')\n- timezone = Attribute(u\'Timezone of the event. A pytz timezone identifier.\')\n- recurrence = Attribute(u\'RFC5545 compatible recurrence definition.\')\n- location = Attribute(u\'Location of the event.\')\n- attendees = Attribute(u\'List of attendees.\')\n- contact_name = Attribute(u\'Contact name.\')\n- contact_email = Attribute(u\'Contact email.\')\n- contact_phone = Attribute(u\'Contact phone.\')\n- event_url = Attribute(u\'Website of the event.\')\n- subjects = Attribute(u\'Categories.\')\n- text = Attribute(u\'Body text of the event.\')\n+ last_modified = Attribute(\'Last modified Python datetime.\')\n+ title = Attribute(\'Event title.\')\n+ description = Attribute(\'Event description text.\')\n+ start = Attribute(\'Event start date as Python datetime.\')\n+ end = Attribute(\'Event end date as Python datetime.\')\n+ whole_day = Attribute(\'Event lasts whole day.\')\n+ open_end = Attribute(\'Event has no defined end time.\')\n+ timezone = Attribute(\'Timezone of the event. A pytz timezone identifier.\')\n+ recurrence = Attribute(\'RFC5545 compatible recurrence definition.\')\n+ location = Attribute(\'Location of the event.\')\n+ attendees = Attribute(\'List of attendees.\')\n+ contact_name = Attribute(\'Contact name.\')\n+ contact_email = Attribute(\'Contact email.\')\n+ contact_phone = Attribute(\'Contact phone.\')\n+ event_url = Attribute(\'Website of the event.\')\n+ subjects = Attribute(\'Categories.\')\n+ text = Attribute(\'Body text of the event.\')\n \n \n class IRecurrenceSupport(Interface):\n@@ -156,37 +155,37 @@ class / created / description / geo /\n resources / rdate / x-prop / iana-prop\n \n """\n- dtstart = Attribute(u\'Start Date/Time\')\n- dtend = Attribute(u\'End Date/Time\')\n- duration = Attribute(u\'Duration\')\n- rrule = Attribute(u\'Recurrence Rule\')\n- description = Attribute(u\'Description\')\n- location = Attribute(u\'Location\')\n- summary = Attribute(u\'Summary\')\n- url = Attribute(u\'Url\')\n- attendee = Attribute(u\'Attendee\')\n- categories = Attribute(u\'Categories\')\n- contact = Attribute(u\'Contact\')\n-\n- exdate = Attribute(u\'Exdate\')\n- rdate = Attribute(u\'Rdate\')\n-\n- dtstamp = Attribute(u\'Timestamp\')\n- uid = Attribute(u\'Unique identifier\')\n- klass = Attribute(u\'Class\') # class\n- created = Attribute(u\'Created\')\n- geo = Attribute(u\'Geo\')\n- last_mod = Attribute(u\'Last Modified\') # last-mod\n- organizer = Attribute(u\'Organizer\')\n- priority = Attribute(u\'Priority\')\n- seq = Attribute(u\'Seq\')\n- status = Attribute(u\'Status\')\n- transp = Attribute(u\'Transp\')\n- recurid = Attribute(u\'Recurid\')\n- attach = Attribute(u\'Attach\')\n- comment = Attribute(u\'Comment\')\n- rstatus = Attribute(u\'Rstatus\')\n- related = Attribute(u\'Related\')\n- resources = Attribute(u\'Resources\')\n- x_prop = Attribute(u\'X Prop\') # x-prop\n- iana_prop = Attribute(u\'Iana Prop\') # iana-prop\n+ dtstart = Attribute(\'Start Date/Time\')\n+ dtend = Attribute(\'End Date/Time\')\n+ duration = Attribute(\'Duration\')\n+ rrule = Attribute(\'Recurrence Rule\')\n+ description = Attribute(\'Description\')\n+ location = Attribute(\'Location\')\n+ summary = Attribute(\'Summary\')\n+ url = Attribute(\'Url\')\n+ attendee = Attribute(\'Attendee\')\n+ categories = Attribute(\'Categories\')\n+ contact = Attribute(\'Contact\')\n+\n+ exdate = Attribute(\'Exdate\')\n+ rdate = Attribute(\'Rdate\')\n+\n+ dtstamp = Attribute(\'Timestamp\')\n+ uid = Attribute(\'Unique identifier\')\n+ klass = Attribute(\'Class\') # class\n+ created = Attribute(\'Created\')\n+ geo = Attribute(\'Geo\')\n+ last_mod = Attribute(\'Last Modified\') # last-mod\n+ organizer = Attribute(\'Organizer\')\n+ priority = Attribute(\'Priority\')\n+ seq = Attribute(\'Seq\')\n+ status = Attribute(\'Status\')\n+ transp = Attribute(\'Transp\')\n+ recurid = Attribute(\'Recurid\')\n+ attach = Attribute(\'Attach\')\n+ comment = Attribute(\'Comment\')\n+ rstatus = Attribute(\'Rstatus\')\n+ related = Attribute(\'Related\')\n+ resources = Attribute(\'Resources\')\n+ x_prop = Attribute(\'X Prop\') # x-prop\n+ iana_prop = Attribute(\'Iana Prop\') # iana-prop\ndiff --git a/plone/event/recurrence.py b/plone/event/recurrence.py\nindex 0bb42ce..7dd27ea 100644\n--- a/plone/event/recurrence.py\n+++ b/plone/event/recurrence.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from dateutil import rrule\n from plone.event.utils import DSTAUTO\n from plone.event.utils import dt2int\n@@ -88,7 +87,7 @@ def recurrence_sequence_ical(\n # time for UNTIL, RDATE and EXDATE.\n t0 = start.time() # set initial time information.\n # First, replace all times in the recurring rule with starttime\n- t0str = \'T{0:02d}{1:02d}{2:02d}\'.format(t0.hour, t0.minute, t0.second)\n+ t0str = f\'T{t0.hour:02d}{t0.minute:02d}{t0.second:02d}\'\n # Replace any times set to 000000 with start time, not all\n # rrules are set by a specific broken widget. Don\'t waste time\n # subbing if the start time is already 000000.\ndiff --git a/plone/event/tests/test_adapters.py b/plone/event/tests/test_adapters.py\nindex b302192..ad51528 100644\n--- a/plone/event/tests/test_adapters.py\n+++ b/plone/event/tests/test_adapters.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from datetime import datetime\n from plone.event.interfaces import IEvent\n from plone.event.interfaces import IEventAccessor\n@@ -9,7 +8,7 @@\n import zope.interface\n \n \n-class MockObject(object):\n+class MockObject:\n """Mock object"""\n \n \ndiff --git a/plone/event/tests/test_doctest.py b/plone/event/tests/test_doctest.py\nindex 77ab9e1..001e083 100644\n--- a/plone/event/tests/test_doctest.py\n+++ b/plone/event/tests/test_doctest.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from zope.component.testing import tearDown\n \n import doctest\ndiff --git a/plone/event/tests/test_recurrence_int_sequence.py b/plone/event/tests/test_recurrence_int_sequence.py\nindex ccd072c..00f7ec8 100644\n--- a/plone/event/tests/test_recurrence_int_sequence.py\n+++ b/plone/event/tests/test_recurrence_int_sequence.py\n@@ -1,5 +1,4 @@\n-# -*- coding: utf-8 -*-\n-import mock\n+from unittest import mock\n import unittest\n \n \ndiff --git a/plone/event/tests/test_recurrence_sequence_ical.py b/plone/event/tests/test_recurrence_sequence_ical.py\nindex 6f2ed8e..679cb77 100644\n--- a/plone/event/tests/test_recurrence_sequence_ical.py\n+++ b/plone/event/tests/test_recurrence_sequence_ical.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n import unittest\n \n \ndiff --git a/plone/event/tests/test_recurrence_sequence_timedelta.py b/plone/event/tests/test_recurrence_sequence_timedelta.py\nindex c9493f7..9cc407a 100644\n--- a/plone/event/tests/test_recurrence_sequence_timedelta.py\n+++ b/plone/event/tests/test_recurrence_sequence_timedelta.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n import unittest\n \n \ndiff --git a/plone/event/tests/test_utils.py b/plone/event/tests/test_utils.py\nindex f90fedd..f2a8e7e 100644\n--- a/plone/event/tests/test_utils.py\n+++ b/plone/event/tests/test_utils.py\n@@ -1,5 +1,4 @@\n-# -*- coding: utf-8 -*-\n-import mock\n+from unittest import mock\n import unittest\n \n \ndiff --git a/plone/event/utils.py b/plone/event/utils.py\nindex 0763205..389a733 100644\n--- a/plone/event/utils.py\n+++ b/plone/event/utils.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from datetime import date\n from datetime import datetime\n from datetime import timedelta\n@@ -59,8 +58,8 @@ def validated_timezone(timezone, fallback=None):\n except Exception:\n if fallback:\n logger.warn(\n- "The timezone {0} is not a valid timezone from the "\n- "Olson database or pytz. Falling back to {1}.".format(\n+ "The timezone {} is not a valid timezone from the "\n+ "Olson database or pytz. Falling back to {}.".format(\n timezone,\n fallback,\n )\n@@ -68,7 +67,7 @@ def validated_timezone(timezone, fallback=None):\n return fallback\n else:\n raise ValueError(\n- "The timezone {0} is not a valid timezone from "\n+ "The timezone {} is not a valid timezone from "\n "the Olson database or pytz.".format(timezone)\n )\n \n@@ -558,7 +557,7 @@ def dt2int(dt):\n if value > MAX32:\n # value must be integer fitting in the 32bit range\n raise OverflowError(\n- """{0} is not within the range of indexable dates,<<\n+ """{} is not within the range of indexable dates,<<\n exceeding 32bit range.""".format(\n dt\n )\n@@ -663,7 +662,7 @@ def rfc2445dt(dt, mode="utc", date=True, time=True):\n dt = pydt(dt)\n if mode == "utc":\n dt = utc(dt)\n- date = "{0}{1}{2}{3}".format(\n+ date = "{}{}{}{}".format(\n date and dt.strftime("%Y%m%d") or "",\n date and time and "T" or "",\n time and dt.strftime("%H%M%S") or "",\ndiff --git a/setup.py b/setup.py\nindex 05d6d46..93f57df 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from setuptools import find_packages\n from setuptools import setup\n \n@@ -10,7 +9,7 @@\n version=version,\n description="Event and calendaring related tools not bound to Plone",\n long_description=(\n- open("README.rst").read() + "\\n" + open(("CHANGES.rst")).read()\n+ open("README.rst").read() + "\\n" + open("CHANGES.rst").read()\n ),\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n' +b"diff --git a/setup.py b/setup.py\nindex b925890..32b90b4 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,4 +1,6 @@\n-from setuptools import setup, find_packages\n+from setuptools import find_packages\n+from setuptools import setup\n+\n \n version = '3.1.1.dev0'\n \ndiff --git a/src/plone/folder/nogopip.py b/src/plone/folder/nogopip.py\nindex e89eec2..c800657 100644\n--- a/src/plone/folder/nogopip.py\n+++ b/src/plone/folder/nogopip.py\n@@ -9,6 +9,7 @@\n from zope.component import getUtility\n from zope.interface import implementer\n \n+\n logger = getLogger(__name__)\n \n \ndiff --git a/src/plone/folder/ordered.py b/src/plone/folder/ordered.py\nindex c7a7882..65db8c8 100644\n--- a/src/plone/folder/ordered.py\n+++ b/src/plone/folder/ordered.py\n@@ -13,6 +13,8 @@\n from zope.component import getAdapter\n from zope.component import queryAdapter\n from zope.interface import implementer\n+\n+\n try:\n from ZTUtils.Lazy import LazyMap\n except ImportError:\ndiff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex d4a59ff..17cae95 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -1,11 +1,10 @@\n from Acquisition import aq_base\n-from zope.interface import implementer\n-from zope.component import adapts\n-from zope.container.contained import notifyContainerModified\n-\n+from plone.folder.interfaces import IExplicitOrdering\n from plone.folder.interfaces import IOrderable\n from plone.folder.interfaces import IOrderableFolder\n-from plone.folder.interfaces import IExplicitOrdering\n+from zope.component import adapts\n+from zope.container.contained import notifyContainerModified\n+from zope.interface import implementer\n \n import six\n \ndiff --git a/src/plone/folder/tests/test_integration.py b/src/plone/folder/tests/test_integration.py\nindex 6bc4414..70ed18a 100644\n--- a/src/plone/folder/tests/test_integration.py\n+++ b/src/plone/folder/tests/test_integration.py\n@@ -1,8 +1,8 @@\n from Acquisition import Implicit\n+from io import BytesIO\n from plone.folder.interfaces import IOrderable\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_FUNCTIONAL_TESTING\n-from io import BytesIO\n from transaction import savepoint\n from zope.interface import implementer\n \ndiff --git a/src/plone/folder/tests/test_partialordering.py b/src/plone/folder/tests/test_partialordering.py\nindex fe0dba7..d3a28e0 100644\n--- a/src/plone/folder/tests/test_partialordering.py\n+++ b/src/plone/folder/tests/test_partialordering.py\n@@ -1,12 +1,13 @@\n-from transaction import savepoint\n from Acquisition import Implicit\n-from zope.interface import implementer\n from plone.folder.interfaces import IOrderable\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.partial import PartialOrdering\n-from plone.folder.tests.utils import Orderable, Chaoticle\n-from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n from plone.folder.testing import PLONEFOLDER_FUNCTIONAL_TESTING\n+from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n+from plone.folder.tests.utils import Chaoticle\n+from plone.folder.tests.utils import Orderable\n+from transaction import savepoint\n+from zope.interface import implementer\n \n import unittest\n \ndiff --git a/src/plone/folder/tests/test_unorderedordering.py b/src/plone/folder/tests/test_unorderedordering.py\nindex 9165b6f..be922b2 100644\n--- a/src/plone/folder/tests/test_unorderedordering.py\n+++ b/src/plone/folder/tests/test_unorderedordering.py\n@@ -1,7 +1,7 @@\n from plone.folder.ordered import OrderedBTreeFolderBase\n-from plone.folder.unordered import UnorderedOrdering\n-from plone.folder.tests.utils import DummyObject\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n+from plone.folder.tests.utils import DummyObject\n+from plone.folder.unordered import UnorderedOrdering\n \n import unittest\n \n" -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:12:42+02:00 +Date: 2023-04-15T14:32:10+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/894078e617c0fdaf9526b559e0829fca897e807c +Commit: https://github.com/plone/plone.folder/commit/1431f6969c98f198cd91c17005afd0346cf0934d -chore: isort +chore: black + +Files changed: +M setup.py +M src/plone/__init__.py +M src/plone/folder/default.py +M src/plone/folder/interfaces.py +M src/plone/folder/nogopip.py +M src/plone/folder/ordered.py +M src/plone/folder/partial.py +M src/plone/folder/testing.py +M src/plone/folder/tests/benchmarks.py +M src/plone/folder/tests/test_dict_interface.py +M src/plone/folder/tests/test_integration.py +M src/plone/folder/tests/test_ordering_adapters.py +M src/plone/folder/tests/test_ordersupport.py +M src/plone/folder/tests/test_partialordering.py +M src/plone/folder/tests/test_unorderedordering.py +M src/plone/folder/tests/test_webdav.py +M src/plone/folder/tests/utils.py +M src/plone/folder/unordered.py + +b'diff --git a/setup.py b/setup.py\nindex 32b90b4..dfeee90 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -2,14 +2,13 @@\n from setuptools import setup\n \n \n-version = \'3.1.1.dev0\'\n+version = "3.1.1.dev0"\n \n setup(\n- name=\'plone.folder\',\n+ name="plone.folder",\n version=version,\n- description=\'BTree-based folder implementation with order support\',\n- long_description=(open("README.rst").read() + "\\n" +\n- open("CHANGES.rst").read()),\n+ description="BTree-based folder implementation with order support",\n+ long_description=(open("README.rst").read() + "\\n" + open("CHANGES.rst").read()),\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n "Environment :: Web Environment",\n@@ -29,33 +28,33 @@\n "Programming Language :: Python :: 3.7",\n "Programming Language :: Python :: 3.8",\n ],\n- keywords=\'folder btree order\',\n- author=\'Plone Foundation\',\n- author_email=\'plone-developers@lists.sourceforge.net\',\n- url=\'https://pypi.org/project/plone.folder\',\n- license=\'GPL version 2\',\n- packages=find_packages(\'src\'),\n- package_dir={\'\': \'src\'},\n- namespace_packages=[\'plone\'],\n+ keywords="folder btree order",\n+ author="Plone Foundation",\n+ author_email="plone-developers@lists.sourceforge.net",\n+ url="https://pypi.org/project/plone.folder",\n+ license="GPL version 2",\n+ packages=find_packages("src"),\n+ package_dir={"": "src"},\n+ namespace_packages=["plone"],\n include_package_data=True,\n- platforms=\'Any\',\n+ platforms="Any",\n zip_safe=False,\n install_requires=[\n- \'plone.memoize\',\n- \'Products.BTreeFolder2\',\n- \'Products.CMFCore\',\n- \'Products.ZCatalog\',\n- \'setuptools\',\n- \'six\',\n- \'zope.annotation\',\n- \'zope.component\',\n- \'zope.container\',\n- \'zope.interface\',\n- \'Zope2\',\n+ "plone.memoize",\n+ "Products.BTreeFolder2",\n+ "Products.CMFCore",\n+ "Products.ZCatalog",\n+ "setuptools",\n+ "six",\n+ "zope.annotation",\n+ "zope.component",\n+ "zope.container",\n+ "zope.interface",\n+ "Zope2",\n ],\n extras_require={\n- \'test\': [\n- \'profilehooks\',\n+ "test": [\n+ "profilehooks",\n ]\n },\n )\ndiff --git a/src/plone/__init__.py b/src/plone/__init__.py\nindex de40ea7..5284146 100644\n--- a/src/plone/__init__.py\n+++ b/src/plone/__init__.py\n@@ -1 +1 @@\n-__import__(\'pkg_resources\').declare_namespace(__name__)\n+__import__("pkg_resources").declare_namespace(__name__)\ndiff --git a/src/plone/folder/default.py b/src/plone/folder/default.py\nindex 7294f66..57c4d90 100644\n--- a/src/plone/folder/default.py\n+++ b/src/plone/folder/default.py\n@@ -13,8 +13,8 @@\n @implementer(IExplicitOrdering)\n @adapter(IOrderableFolder)\n class DefaultOrdering:\n- """ This implementation uses annotations to store the order on the\n- object, and supports explicit ordering. """\n+ """This implementation uses annotations to store the order on the\n+ object, and supports explicit ordering."""\n \n ORDER_KEY = "plone.folder.ordered.order"\n POS_KEY = "plone.folder.ordered.pos"\n@@ -23,14 +23,14 @@ def __init__(self, context):\n self.context = context\n \n def notifyAdded(self, obj_id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n order = self._order(True)\n pos = self._pos(True)\n order.append(obj_id)\n pos[obj_id] = len(order) - 1\n \n def notifyRemoved(self, obj_id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n order = self._order()\n pos = self._pos()\n try:\n@@ -43,14 +43,8 @@ def notifyRemoved(self, obj_id):\n for count, obj_id in enumerate(order):\n pos[obj_id] = count\n \n- def moveObjectsByDelta(\n- self,\n- ids,\n- delta,\n- subset_ids=None,\n- suppress_events=False\n- ):\n- """ see interfaces.py """\n+ def moveObjectsByDelta(self, ids, delta, subset_ids=None, suppress_events=False):\n+ """see interfaces.py"""\n order = self._order()\n pos = self._pos()\n min_position = 0\n@@ -60,7 +54,7 @@ def moveObjectsByDelta(\n subset_ids = self.idsInOrder()\n elif not isinstance(subset_ids, list):\n subset_ids = list(subset_ids)\n- if delta > 0: # unify moving direction\n+ if delta > 0: # unify moving direction\n ids = reversed(ids)\n subset_ids.reverse()\n counter = 0\n@@ -93,41 +87,37 @@ def moveObjectsByDelta(\n pos[obj_id] = i\n idx += 1\n except KeyError:\n- raise ValueError(\n- f\'No object with id "{obj_id:s}" exists.\'\n- )\n+ raise ValueError(f\'No object with id "{obj_id:s}" exists.\')\n if not suppress_events:\n notifyContainerModified(self.context)\n return counter\n \n def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -delta, subset_ids)\n \n def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, delta, subset_ids)\n \n def moveObjectsToTop(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -len(self._order()), subset_ids)\n \n def moveObjectsToBottom(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, len(self._order()), subset_ids)\n \n def moveObjectToPosition(self, obj_id, position, suppress_events=False):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n delta = position - self.getObjectPosition(obj_id)\n if delta:\n return self.moveObjectsByDelta(\n- obj_id,\n- delta,\n- suppress_events=suppress_events\n+ obj_id, delta, suppress_events=suppress_events\n )\n \n def orderObjects(self, key=None, reverse=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n if key is None and not reverse:\n return -1\n order = self._order()\n@@ -137,11 +127,13 @@ def orderObjects(self, key=None, reverse=None):\n # Simply reverse the current ordering.\n order.reverse()\n else:\n+\n def keyfn(obj_id):\n attr = getattr(self.context._getOb(obj_id), key)\n if callable(attr):\n return attr()\n return attr\n+\n # order.sort(cmd=None, key=keyfn, reverse=bool(reverse))\n order = sorted(order, key=keyfn, reverse=bool(reverse))\n self._set_order(order)\n@@ -150,15 +142,18 @@ def keyfn(obj_id):\n return -1\n \n def getObjectPosition(self, obj_id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n pos = self._pos()\n if obj_id in pos:\n return pos[obj_id]\n- raise ValueError(\'No object with id "{:s}" exists in "{:s}".\'.format(\n- obj_id, \'/\'.join(self.context.getPhysicalPath())))\n+ raise ValueError(\n+ \'No object with id "{:s}" exists in "{:s}".\'.format(\n+ obj_id, "/".join(self.context.getPhysicalPath())\n+ )\n+ )\n \n def idsInOrder(self):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return list(self._order())\n \n def __getitem__(self, index):\ndiff --git a/src/plone/folder/interfaces.py b/src/plone/folder/interfaces.py\nindex 2a73a21..d3aab8d 100644\n--- a/src/plone/folder/interfaces.py\n+++ b/src/plone/folder/interfaces.py\n@@ -2,73 +2,73 @@\n \n \n class IOrderable(Interface):\n- """ Marker interface for orderable portal content """\n+ """Marker interface for orderable portal content"""\n \n \n class IFolder(Interface):\n- """ Marker interface for Plone-like folders """\n+ """Marker interface for Plone-like folders"""\n \n \n class IOrderableFolder(IFolder):\n- """ A Plone-like folder with ordering support """\n+ """A Plone-like folder with ordering support"""\n \n def getOrdering():\n- """ return the currently active ordering adapter for this folder """\n+ """return the currently active ordering adapter for this folder"""\n \n- def setOrdering(ordering=\'\'):\n- """ (re)set ordering adapter to be used for this folder """\n+ def setOrdering(ordering=""):\n+ """(re)set ordering adapter to be used for this folder"""\n \n \n class IOrdering(Interface):\n- """ An adapter providing ordering operations on its context folder.\n+ """An adapter providing ordering operations on its context folder.\n \n- The OrderedBTreeFolderBase mix-in class will adapt self (the\n- folder) to this interface when trying to get object position or\n- find the order of items. There is a default implementation, but\n- you can provide a different policy.\n+ The OrderedBTreeFolderBase mix-in class will adapt self (the\n+ folder) to this interface when trying to get object position or\n+ find the order of items. There is a default implementation, but\n+ you can provide a different policy.\n \n- Your adapter (which should still adapt to IOrdered) can\n- optionally provide IExplicitOrdering, defined below. This is\n- used to support explicit ordering, e.g. through a UI. """\n+ Your adapter (which should still adapt to IOrdered) can\n+ optionally provide IExplicitOrdering, defined below. This is\n+ used to support explicit ordering, e.g. through a UI."""\n \n def notifyAdded(obj_id):\n- """ Inform the ordering implementation that an item was added """\n+ """Inform the ordering implementation that an item was added"""\n \n def notifyRemoved(obj_id):\n- """ Inform the ordering implementation that an item was removed """\n+ """Inform the ordering implementation that an item was removed"""\n \n def getObjectPosition(obj_id):\n- """ Get the position of the given object id """\n+ """Get the position of the given object id"""\n \n def idsInOrder():\n- """ Return all object ids, in the correct order """\n+ """Return all object ids, in the correct order"""\n \n \n class IExplicitOrdering(IOrdering):\n- """ An adapter allowing explicit ordering """\n+ """An adapter allowing explicit ordering"""\n \n def moveObjectsByDelta(ids, delta, subset_ids=None, suppress_events=False):\n- """ Move the specified ids (a sequence, or a single string id)\n- by the given delta (a positive or negative number). By\n- default, this moves the objects within the whole set of\n- sub-items in the context container, but if subset_ids is\n- specified, it gives a subset of ids to consider.\n- Should return the number of objects that changed position. """\n+ """Move the specified ids (a sequence, or a single string id)\n+ by the given delta (a positive or negative number). By\n+ default, this moves the objects within the whole set of\n+ sub-items in the context container, but if subset_ids is\n+ specified, it gives a subset of ids to consider.\n+ Should return the number of objects that changed position."""\n \n def moveObjectsUp(ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects up by delta in container. """\n+ """Move specified sub-objects up by delta in container."""\n \n def moveObjectsDown(ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects down by delta in container. """\n+ """Move specified sub-objects down by delta in container."""\n \n def moveObjectsToTop(ids, subset_ids=None):\n- """ Move specified sub-objects to top of container. """\n+ """Move specified sub-objects to top of container."""\n \n def moveObjectsToBottom(ids, subset_ids=None):\n- """ Move specified sub-objects to bottom of container. """\n+ """Move specified sub-objects to bottom of container."""\n \n def moveObjectToPosition(obj_id, position, suppress_events=False):\n- """ Move specified object to absolute position. """\n+ """Move specified object to absolute position."""\n \n def orderObjects(key, reverse=None):\n- """ Order sub-objects by key and direction. """\n+ """Order sub-objects by key and direction."""\ndiff --git a/src/plone/folder/nogopip.py b/src/plone/folder/nogopip.py\nindex c800657..d8b25f4 100644\n--- a/src/plone/folder/nogopip.py\n+++ b/src/plone/folder/nogopip.py\n@@ -20,7 +20,7 @@ def traverse(base, path):\n returns: content at the end or None\n """\n current = base\n- for cid in path.split(\'/\'):\n+ for cid in path.split("/"):\n if not cid:\n continue\n try:\n@@ -32,7 +32,7 @@ def traverse(base, path):\n \n @implementer(IPluggableIndex)\n class StubIndex(SimpleItem):\n- """ stub catalog index doing nothing """\n+ """stub catalog index doing nothing"""\n \n def __init__(self, id, *args, **kw):\n self.id = id\n@@ -64,10 +64,10 @@ def clear(self):\n \n @implementer(ISortIndex)\n class GopipIndex(StubIndex):\n- """ fake index for sorting against `getObjPositionInParent` """\n+ """fake index for sorting against `getObjPositionInParent`"""\n \n- meta_type = \'GopipIndex\'\n- manage_options = dict(label=\'Settings\', action=\'manage_main\'),\n+ meta_type = "GopipIndex"\n+ manage_options = (dict(label="Settings", action="manage_main"),)\n \n keyForDocument = 42\n \n@@ -87,7 +87,7 @@ def documentToKeyMap(self):\n # results themselves. luckily this is only ever called from\n # `sortResults`, so we can get it form there. oh, and lurker\n # says this won\'t work in jython, though! :)\n- rs = currentframe().f_back.f_locals[\'rs\']\n+ rs = currentframe().f_back.f_locals["rs"]\n rids = {}\n items = []\n containers = {}\n@@ -95,17 +95,17 @@ def documentToKeyMap(self):\n root = getUtility(ISiteRoot).getPhysicalRoot()\n for rid in rs:\n path = getpath(rid)\n- parent, id = path.rsplit(\'/\', 1)\n+ parent, id = path.rsplit("/", 1)\n container = containers.get(parent)\n if container is None:\n containers[parent] = container = traverse(root, parent)\n- rids[id] = rid # remember in case of single folder\n+ rids[id] = rid # remember in case of single folder\n items.append((rid, container, id)) # or else for deferred lookup\n pos = {}\n if len(containers) == 1:\n # the usual "all from one folder" case can be optimized\n folder = list(containers.values())[0]\n- if getattr(aq_base(folder), \'getOrdering\', None):\n+ if getattr(aq_base(folder), "getOrdering", None):\n ids = folder.getOrdering().idsInOrder()\n else:\n # site root or old folders\n@@ -117,7 +117,7 @@ def documentToKeyMap(self):\n return pos\n # otherwise the entire map needs to be constructed...\n for rid, container, id in items:\n- if getattr(aq_base(container), \'getObjectPosition\', None):\n+ if getattr(aq_base(container), "getObjectPosition", None):\n pos[rid] = container.getObjectPosition(id)\n else:\n # fallback for unordered folders\n@@ -125,21 +125,11 @@ def documentToKeyMap(self):\n return pos\n \n \n-manage_addGopipForm = DTMLFile(\'dtml/addGopipIndex\', globals())\n+manage_addGopipForm = DTMLFile("dtml/addGopipIndex", globals())\n \n \n-def manage_addGopipIndex(\n- self,\n- identifier,\n- REQUEST=None,\n- RESPONSE=None,\n- URL3=None\n-):\n- """ add a fake gopip index """\n+def manage_addGopipIndex(self, identifier, REQUEST=None, RESPONSE=None, URL3=None):\n+ """add a fake gopip index"""\n return self.manage_addIndex(\n- identifier,\n- \'GopipIndex\',\n- REQUEST=REQUEST,\n- RESPONSE=RESPONSE,\n- URL1=URL3\n+ identifier, "GopipIndex", REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3\n )\ndiff --git a/src/plone/folder/ordered.py b/src/plone/folder/ordered.py\nindex 65db8c8..72edf91 100644\n--- a/src/plone/folder/ordered.py\n+++ b/src/plone/folder/ordered.py\n@@ -30,29 +30,29 @@\n \n @implementer(IOrderedContainer, IOrderableFolder, IAttributeAnnotatable)\n class OrderedBTreeFolderBase(BTreeFolder2Base):\n- """ BTree folder base class with ordering support. The ordering\n- is done by a named adapter (to IOrdering), which makes the policy\n- changeable. """\n+ """BTree folder base class with ordering support. The ordering\n+ is done by a named adapter (to IOrdering), which makes the policy\n+ changeable."""\n \n- _ordering = \'\' # name of adapter defining ordering policy\n+ _ordering = "" # name of adapter defining ordering policy\n \n security = ClassSecurityInfo()\n \n def __bool__(self):\n- """ a folder is something, even if it\'s empty """\n+ """a folder is something, even if it\'s empty"""\n return True\n \n @security.protected(access_contents_information)\n def getOrdering(self):\n- """ return the currently active ordering adapter for this folder """\n+ """return the currently active ordering adapter for this folder"""\n adapter = queryAdapter(self, IOrdering, name=self._ordering)\n if adapter is None:\n adapter = getAdapter(self, IOrdering)\n return adapter\n \n @security.protected(manage_properties)\n- def setOrdering(self, ordering=\'\'):\n- """ (re)set ordering adapter to be used for this folder """\n+ def setOrdering(self, ordering=""):\n+ """(re)set ordering adapter to be used for this folder"""\n if ordering:\n # make sure the adapter exists...\n getAdapter(self, IOrdering, name=ordering)\n@@ -61,21 +61,21 @@ def setOrdering(self, ordering=\'\'):\n # IObjectManager\n \n def _getOb(self, id, default=_marker):\n- """ Return the named object from the folder. """\n+ """Return the named object from the folder."""\n try:\n return super()._getOb(id, default)\n except KeyError as e:\n raise AttributeError(e)\n \n def _setOb(self, id, object):\n- """ Store the named object in the folder. """\n+ """Store the named object in the folder."""\n super()._setOb(id, object)\n- self.getOrdering().notifyAdded(id) # notify the ordering adapter\n+ self.getOrdering().notifyAdded(id) # notify the ordering adapter\n \n def _delOb(self, id):\n- """ Remove the named object from the folder. """\n+ """Remove the named object from the folder."""\n super()._delOb(id)\n- self.getOrdering().notifyRemoved(id) # notify the ordering adapter\n+ self.getOrdering().notifyRemoved(id) # notify the ordering adapter\n \n def objectIds(self, spec=None, ordered=True):\n if not ordered:\n@@ -100,19 +100,20 @@ def objectItems(self, spec=None):\n # Returns a list of (id, subobject) tuples of the current object.\n # If \'spec\' is specified, returns only objects whose meta_type match\n # \'spec\'\n- return LazyMap(lambda id, _getOb=self._getOb: (id, _getOb(id)),\n- self.objectIds(spec))\n+ return LazyMap(\n+ lambda id, _getOb=self._getOb: (id, _getOb(id)), self.objectIds(spec)\n+ )\n \n # IOrderSupport - mostly deprecated, use the adapter directly instead\n \n @security.protected(access_contents_information)\n def getObjectPosition(self, id):\n- """ Get the position of an object by its id. """\n+ """Get the position of an object by its id."""\n return self.getOrdering().getObjectPosition(id)\n \n @security.protected(manage_properties)\n def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects up by delta in container. """\n+ """Move specified sub-objects up by delta in container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsUp(ids, delta, subset_ids)\n@@ -121,7 +122,7 @@ def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n \n @security.protected(manage_properties)\n def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects down by delta in container. """\n+ """Move specified sub-objects down by delta in container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsDown(ids, delta, subset_ids)\n@@ -130,7 +131,7 @@ def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n \n @security.protected(manage_properties)\n def moveObjectsToTop(self, ids, subset_ids=None):\n- """ Move specified sub-objects to top of container. """\n+ """Move specified sub-objects to top of container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsToTop(ids, subset_ids)\n@@ -139,7 +140,7 @@ def moveObjectsToTop(self, ids, subset_ids=None):\n \n @security.protected(manage_properties)\n def moveObjectsToBottom(self, ids, subset_ids=None):\n- """ Move specified sub-objects to bottom of container. """\n+ """Move specified sub-objects to bottom of container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsToBottom(ids, subset_ids)\n@@ -148,7 +149,7 @@ def moveObjectsToBottom(self, ids, subset_ids=None):\n \n @security.protected(ModifyPortalContent)\n def moveObject(self, id, position):\n- """ Move specified object to absolute position. """\n+ """Move specified object to absolute position."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectToPosition(id, position)\n@@ -157,7 +158,7 @@ def moveObject(self, id, position):\n \n @security.protected(manage_properties)\n def moveObjectToPosition(self, id, position, suppress_events=False):\n- """ Move specified object to absolute position. """\n+ """Move specified object to absolute position."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectToPosition(id, position, suppress_events)\n@@ -165,24 +166,17 @@ def moveObjectToPosition(self, id, position, suppress_events=False):\n return 0\n \n @security.protected(manage_properties)\n- def moveObjectsByDelta(\n- self, ids, delta, subset_ids=None, suppress_events=False\n- ):\n- """ Move specified sub-objects by delta. """\n+ def moveObjectsByDelta(self, ids, delta, subset_ids=None, suppress_events=False):\n+ """Move specified sub-objects by delta."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n- return ordering.moveObjectsByDelta(\n- ids,\n- delta,\n- subset_ids,\n- suppress_events\n- )\n+ return ordering.moveObjectsByDelta(ids, delta, subset_ids, suppress_events)\n else:\n return 0\n \n @security.protected(manage_properties)\n def orderObjects(self, key=None, reverse=None):\n- """ Order sub-objects by key and direction. """\n+ """Order sub-objects by key and direction."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.orderObjects(key, reverse)\n@@ -195,19 +189,15 @@ def iterkeys(self):\n return iter(self.objectIds())\n \n def manage_renameObject(self, id, new_id, REQUEST=None):\n- """ Rename a particular sub-object without changing its position. """\n+ """Rename a particular sub-object without changing its position."""\n old_position = self.getObjectPosition(id)\n- result = super().manage_renameObject(\n- id,\n- new_id,\n- REQUEST\n- )\n+ result = super().manage_renameObject(id, new_id, REQUEST)\n if old_position is None:\n return result\n self.moveObjectToPosition(new_id, old_position, suppress_events=True)\n- reindex = getattr(self._getOb(new_id), \'reindexObject\', None)\n+ reindex = getattr(self._getOb(new_id), "reindexObject", None)\n if reindex is not None:\n- reindex(idxs=[\'getObjPositionInParent\'])\n+ reindex(idxs=["getObjPositionInParent"])\n return result\n \n # Dict interface\n@@ -227,11 +217,14 @@ def __getitem__(self, key):\n return value\n \n # WebDAV PUT support\n- if hasattr(self, \'REQUEST\'):\n+ if hasattr(self, "REQUEST"):\n request = self.REQUEST\n- method = request.get(\'REQUEST_METHOD\', \'GET\')\n- if (HAS_WEBDAV and getattr(request, \'maybe_webdav_client\', False)\n- and method not in (\'GET\', \'POST\')):\n+ method = request.get("REQUEST_METHOD", "GET")\n+ if (\n+ HAS_WEBDAV\n+ and getattr(request, "maybe_webdav_client", False)\n+ and method not in ("GET", "POST")\n+ ):\n return NullResource(self, key, request).__of__(self)\n raise KeyError(key)\n \n@@ -242,11 +235,11 @@ def __getitem__(self, key):\n \n \n class CMFOrderedBTreeFolderBase(OrderedBTreeFolderBase, PortalFolderBase):\n- """ BTree folder for CMF sites, with ordering support. The ordering\n- is done by adapter (to IOrdering), which makes the policy\n- changeable. """\n+ """BTree folder for CMF sites, with ordering support. The ordering\n+ is done by adapter (to IOrdering), which makes the policy\n+ changeable."""\n \n- def __init__(self, id, title=\'\'):\n+ def __init__(self, id, title=""):\n PortalFolderBase.__init__(self, id, title)\n BTreeFolder2Base.__init__(self, id)\n \ndiff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex 17cae95..0ae54c2 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -9,14 +9,15 @@\n import six\n \n \n-ORDER_ATTR = \'_objectordering\'\n+ORDER_ATTR = "_objectordering"\n \n \n @implementer(IExplicitOrdering)\n class PartialOrdering:\n- """ this implementation uses a list to store order information on a\n- regular attribute of the folderish object; explicit ordering\n- is supported """\n+ """this implementation uses a list to store order information on a\n+ regular attribute of the folderish object; explicit ordering\n+ is supported"""\n+\n adapts(IOrderableFolder)\n \n def __init__(self, context):\n@@ -38,24 +39,24 @@ def order(self, value):\n setattr(context, ORDER_ATTR, value)\n \n def notifyAdded(self, id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n assert not id in self.order\n context = aq_base(self.context)\n obj = context._getOb(id)\n if IOrderable.providedBy(obj):\n self.order.append(id)\n- self.context._p_changed = True # the order was changed\n+ self.context._p_changed = True # the order was changed\n \n def notifyRemoved(self, id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n try:\n self.order.remove(id)\n- self.context._p_changed = True # the order was changed\n- except ValueError: # removing non-orderable items is okay\n+ self.context._p_changed = True # the order was changed\n+ except ValueError: # removing non-orderable items is okay\n pass\n \n def idsInOrder(self, onlyOrderables=False):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n ordered = list(self.order)\n ordered_set = set(ordered)\n if not onlyOrderables:\n@@ -65,9 +66,8 @@ def idsInOrder(self, onlyOrderables=False):\n ordered.append(id)\n return ordered\n \n- def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n- suppress_events=False):\n- """ see interfaces.py """\n+ def moveObjectsByDelta(self, ids, delta, subset_ids=None, suppress_events=False):\n+ """see interfaces.py"""\n min_position = 0\n if isinstance(ids, str):\n ids = [ids]\n@@ -75,7 +75,7 @@ def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n subset_ids = self.idsInOrder(onlyOrderables=True)\n elif not isinstance(subset_ids, list):\n subset_ids = list(subset_ids)\n- if delta > 0: # unify moving direction\n+ if delta > 0: # unify moving direction\n ids = reversed(ids)\n subset_ids.reverse()\n counter = 0\n@@ -106,38 +106,39 @@ def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n except KeyError:\n raise ValueError(\'No object with id "%s" exists.\' % id)\n if idx > 0:\n- self.context._p_changed = True # the order was changed\n+ self.context._p_changed = True # the order was changed\n if not suppress_events:\n notifyContainerModified(self.context)\n return counter\n \n def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -delta, subset_ids)\n \n def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, delta, subset_ids)\n \n def moveObjectsToTop(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -len(self.order), subset_ids)\n \n def moveObjectsToBottom(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, len(self.order), subset_ids)\n \n def moveObjectToPosition(self, id, position, suppress_events=False):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n old_position = self.getObjectPosition(id)\n if old_position is not None:\n delta = position - old_position\n if delta:\n- return self.moveObjectsByDelta(id, delta,\n- suppress_events=suppress_events)\n+ return self.moveObjectsByDelta(\n+ id, delta, suppress_events=suppress_events\n+ )\n \n def orderObjects(self, key=None, reverse=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n if key is None:\n if not reverse:\n return -1\n@@ -145,17 +146,19 @@ def orderObjects(self, key=None, reverse=None):\n # Simply reverse the current ordering.\n self.order.reverse()\n else:\n+\n def keyfn(id):\n attr = getattr(self.context._getOb(id), key)\n if callable(attr):\n return attr()\n return attr\n+\n self.order = sorted(self.order, key=keyfn, reverse=bool(reverse))\n- self.context._p_changed = True # the order was changed\n+ self.context._p_changed = True # the order was changed\n return -1\n \n def getObjectPosition(self, id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n try:\n # using `index` here might not be that efficient for very large\n # lists, but the idea behind this adapter is to use it when the\ndiff --git a/src/plone/folder/testing.py b/src/plone/folder/testing.py\nindex 4afd1ac..9927242 100644\n--- a/src/plone/folder/testing.py\n+++ b/src/plone/folder/testing.py\n@@ -7,7 +7,6 @@\n \n \n class PloneFolderLayer(PloneSandboxLayer):\n-\n defaultBases = (PLONE_FIXTURE,)\n \n def setUpZope(self, app, configurationContext):\n@@ -17,11 +16,9 @@ def setUpZope(self, app, configurationContext):\n PLONEFOLDER_FIXTURE = PloneFolderLayer()\n \n PLONEFOLDER_INTEGRATION_TESTING = IntegrationTesting(\n- bases=(PLONEFOLDER_FIXTURE,),\n- name=\'PloneFolderLayer:IntegrationTesting\'\n+ bases=(PLONEFOLDER_FIXTURE,), name="PloneFolderLayer:IntegrationTesting"\n )\n \n PLONEFOLDER_FUNCTIONAL_TESTING = FunctionalTesting(\n- bases=(PLONEFOLDER_FIXTURE,),\n- name=\'PloneFolderLayer:FunctionalTesting\'\n+ bases=(PLONEFOLDER_FIXTURE,), name="PloneFolderLayer:FunctionalTesting"\n )\ndiff --git a/src/plone/folder/tests/benchmarks.py b/src/plone/folder/tests/benchmarks.py\nindex 9ae703d..a788f58 100644\n--- a/src/plone/folder/tests/benchmarks.py\n+++ b/src/plone/folder/tests/benchmarks.py\n@@ -12,20 +12,20 @@\n \n \n class BenchmarkTests(TestCase):\n-\n layer = PloneFolderLayer\n \n def testDeleteSpeed(self):\n folder = OrderedBTreeFolderBase("f1")\n for idx in range(100000):\n- id = \'foo-%s\' % idx\n- folder[id] = DummyObject(id, \'bar\')\n+ id = "foo-%s" % idx\n+ folder[id] = DummyObject(id, "bar")\n last = reversed(folder.keys()[-100:])\n \n @timecall\n def delete():\n for id in last:\n del folder[id]\n+\n delete()\n \n \ndiff --git a/src/plone/folder/tests/test_dict_interface.py b/src/plone/folder/tests/test_dict_interface.py\nindex d71a7a7..489604e 100644\n--- a/src/plone/folder/tests/test_dict_interface.py\n+++ b/src/plone/folder/tests/test_dict_interface.py\n@@ -7,38 +7,38 @@\n \n \n class DictInterfaceTests(unittest.TestCase):\n- """ tests for dict style interface """\n+ """tests for dict style interface"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def test_getitem(self):\n folder = OrderedBTreeFolderBase("f1")\n- foo = DummyObject(\'foo\')\n- folder._setOb(\'foo\', foo)\n- self.assertEqual(folder[\'foo\'], foo)\n- self.assertEqual(folder.__getitem__(\'foo\'), foo)\n- self.assertRaises(KeyError, folder.__getitem__, \'bar\')\n+ foo = DummyObject("foo")\n+ folder._setOb("foo", foo)\n+ self.assertEqual(folder["foo"], foo)\n+ self.assertEqual(folder.__getitem__("foo"), foo)\n+ self.assertRaises(KeyError, folder.__getitem__, "bar")\n \n def test_setitem(self):\n folder = OrderedBTreeFolderBase("f1")\n- foo = DummyObject(\'foo\')\n- folder[\'foo\'] = foo\n- self.assertEqual(folder._getOb(\'foo\'), foo)\n+ foo = DummyObject("foo")\n+ folder["foo"] = foo\n+ self.assertEqual(folder._getOb("foo"), foo)\n \n def test_contains(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder._setOb(\'foo\', DummyObject(\'foo\'))\n- folder._setOb(\'bar\', DummyObject(\'bar\'))\n- self.assertTrue(\'foo\' in folder)\n- self.assertTrue(\'bar\' in folder)\n+ folder._setOb("foo", DummyObject("foo"))\n+ folder._setOb("bar", DummyObject("bar"))\n+ self.assertTrue("foo" in folder)\n+ self.assertTrue("bar" in folder)\n \n def test_delitem(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder._setOb(\'foo\', DummyObject(\'foo\'))\n- folder._setOb(\'bar\', DummyObject(\'bar\'))\n+ folder._setOb("foo", DummyObject("foo"))\n+ folder._setOb("bar", DummyObject("bar"))\n self.assertEqual(len(folder.objectIds()), 2)\n- del folder[\'foo\']\n- del folder[\'bar\']\n+ del folder["foo"]\n+ del folder["bar"]\n self.assertEqual(len(folder.objectIds()), 0)\n \n def test_len_empty_folder(self):\n@@ -47,40 +47,40 @@ def test_len_empty_folder(self):\n \n def test_len_one_child(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder[\'child\'] = DummyObject(\'child\')\n+ folder["child"] = DummyObject("child")\n self.assertEqual(len(folder), 1)\n \n def test_to_verify_ticket_9120(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder[\'ob1\'] = ob1 = DummyObject(\'ob1\')\n- folder[\'ob2\'] = DummyObject(\'ob2\')\n- folder[\'ob3\'] = DummyObject(\'ob3\')\n- folder[\'ob4\'] = ob4 = DummyObject(\'ob4\')\n- del folder[\'ob2\']\n- del folder[\'ob3\']\n- self.assertEqual(folder.keys(), [\'ob1\', \'ob4\'])\n+ folder["ob1"] = ob1 = DummyObject("ob1")\n+ folder["ob2"] = DummyObject("ob2")\n+ folder["ob3"] = DummyObject("ob3")\n+ folder["ob4"] = ob4 = DummyObject("ob4")\n+ del folder["ob2"]\n+ del folder["ob3"]\n+ self.assertEqual(folder.keys(), ["ob1", "ob4"])\n self.assertEqual(list(map(aq_base, folder.values())), [ob1, ob4])\n self.assertEqual([key in folder for key in folder], [True, True])\n \n \n class RelatedToDictInterfaceTests(unittest.TestCase):\n- """ various tests which are related to the dict-like interface """\n+ """various tests which are related to the dict-like interface"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder._setOb(\'o1\', DummyObject(\'o1\', \'mt1\'))\n- folder._setOb(\'o2\', DummyObject(\'o2\', \'mt2\'))\n- folder._setOb(\'o3\', DummyObject(\'o3\', \'mt1\'))\n- folder._setOb(\'o4\', DummyObject(\'o4\', \'mt2\'))\n+ folder._setOb("o1", DummyObject("o1", "mt1"))\n+ folder._setOb("o2", DummyObject("o2", "mt2"))\n+ folder._setOb("o3", DummyObject("o3", "mt1"))\n+ folder._setOb("o4", DummyObject("o4", "mt2"))\n return folder\n \n def testObjectIdsWithSpec(self):\n folder = self.create()\n- self.assertEqual([\'o1\', \'o3\'], folder.objectIds(spec=\'mt1\'))\n- self.assertEqual([\'o2\', \'o4\'], folder.objectIds(spec=\'mt2\'))\n- folder.moveObjectsToTop([\'o3\'])\n- folder.moveObjectsDown([\'o2\'])\n- self.assertEqual([\'o3\', \'o1\'], folder.objectIds(spec=\'mt1\'))\n- self.assertEqual([\'o4\', \'o2\'], folder.objectIds(spec=\'mt2\'))\n+ self.assertEqual(["o1", "o3"], folder.objectIds(spec="mt1"))\n+ self.assertEqual(["o2", "o4"], folder.objectIds(spec="mt2"))\n+ folder.moveObjectsToTop(["o3"])\n+ folder.moveObjectsDown(["o2"])\n+ self.assertEqual(["o3", "o1"], folder.objectIds(spec="mt1"))\n+ self.assertEqual(["o4", "o2"], folder.objectIds(spec="mt2"))\ndiff --git a/src/plone/folder/tests/test_integration.py b/src/plone/folder/tests/test_integration.py\nindex 70ed18a..d4b3371 100644\n--- a/src/plone/folder/tests/test_integration.py\n+++ b/src/plone/folder/tests/test_integration.py\n@@ -11,23 +11,22 @@\n \n @implementer(IOrderable)\n class DummyFolder(OrderedBTreeFolderBase, Implicit):\n- """ we need to mix in acquisition """\n+ """we need to mix in acquisition"""\n \n- meta_type = \'DummyFolder\'\n+ meta_type = "DummyFolder"\n \n \n class IntegrationTests(unittest.TestCase):\n-\n layer = PLONEFOLDER_FUNCTIONAL_TESTING\n \n def testExportDoesntIncludeParent(self):\n- self.app = self.layer[\'app\']\n- self.app._setOb(\'foo\', DummyFolder(\'foo\'))\n+ self.app = self.layer["app"]\n+ self.app._setOb("foo", DummyFolder("foo"))\n foo = self.app.foo\n- foo[\'bar\'] = DummyFolder(\'bar\')\n- savepoint(optimistic=True) # savepoint assigns oids\n+ foo["bar"] = DummyFolder("bar")\n+ savepoint(optimistic=True) # savepoint assigns oids\n # now let\'s export to a buffer and check the objects...\n exp = BytesIO()\n self.app._p_jar.exportFile(foo.bar._p_oid, exp)\n- self.assertTrue(b\'bar\' in exp.getvalue())\n- self.assertFalse(b\'foo\' in exp.getvalue())\n+ self.assertTrue(b"bar" in exp.getvalue())\n+ self.assertFalse(b"foo" in exp.getvalue())\ndiff --git a/src/plone/folder/tests/test_ordering_adapters.py b/src/plone/folder/tests/test_ordering_adapters.py\nindex c12d7f7..6a4b174 100644\n--- a/src/plone/folder/tests/test_ordering_adapters.py\n+++ b/src/plone/folder/tests/test_ordering_adapters.py\n@@ -8,7 +8,7 @@\n \n \n class OrderingAdapterTests(unittest.TestCase):\n- """ tests regarding available ordering adapters """\n+ """tests regarding available ordering adapters"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n@@ -18,21 +18,21 @@ def testDefaultAdapter(self):\n \n def testUnorderedOrdering(self):\n folder = OrderedBTreeFolderBase()\n- folder._ordering = \'unordered\'\n+ folder._ordering = "unordered"\n self.assertTrue(isinstance(folder.getOrdering(), UnorderedOrdering))\n \n def testUnknownOrdering(self):\n folder = OrderedBTreeFolderBase()\n- folder._ordering = \'foo\'\n+ folder._ordering = "foo"\n self.assertTrue(isinstance(folder.getOrdering(), DefaultOrdering))\n \n def testSetOrdering(self):\n folder = OrderedBTreeFolderBase()\n- folder.setOrdering(\'unordered\')\n+ folder.setOrdering("unordered")\n self.assertTrue(isinstance(folder.getOrdering(), UnorderedOrdering))\n folder.setOrdering()\n self.assertTrue(isinstance(folder.getOrdering(), DefaultOrdering))\n \n def testSetUnknownOrdering(self):\n folder = OrderedBTreeFolderBase()\n- self.assertRaises(ComponentLookupError, folder.setOrdering, \'foo\')\n+ self.assertRaises(ComponentLookupError, folder.setOrdering, "foo")\ndiff --git a/src/plone/folder/tests/test_ordersupport.py b/src/plone/folder/tests/test_ordersupport.py\nindex 8a7208f..05f7ff5 100644\n--- a/src/plone/folder/tests/test_ordersupport.py\n+++ b/src/plone/folder/tests/test_ordersupport.py\n@@ -16,16 +16,16 @@ def getId(self):\n \n \n class OFSOrderSupportTests(unittest.TestCase):\n- """ tests borrowed from OFS.tests.testOrderSupport """\n+ """tests borrowed from OFS.tests.testOrderSupport"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n- folder = TestFolder(\'f1\')\n- folder[\'o1\'] = DummyObject(\'o1\', \'mt1\')\n- folder[\'o2\'] = DummyObject(\'o2\', \'mt2\')\n- folder[\'o3\'] = DummyObject(\'o3\', \'mt1\')\n- folder[\'o4\'] = DummyObject(\'o4\', \'mt2\')\n+ folder = TestFolder("f1")\n+ folder["o1"] = DummyObject("o1", "mt1")\n+ folder["o2"] = DummyObject("o2", "mt2")\n+ folder["o3"] = DummyObject("o3", "mt1")\n+ folder["o4"] = DummyObject("o4", "mt2")\n return folder\n \n # Test for ordering of basic methods\n@@ -39,38 +39,24 @@ def test_objectIdsOrdered(self):\n def test_objectValuesOrdered(self):\n folder = self.create()\n self.assertEqual(\n- ["o1", "o2", "o3", "o4"],\n- [x.id for x in folder.objectValues()]\n+ ["o1", "o2", "o3", "o4"], [x.id for x in folder.objectValues()]\n )\n folder.moveObjectsUp(("o2",), 1)\n self.assertEqual(\n- ["o2", "o1", "o3", "o4"],\n- [x.id for x in folder.objectValues()]\n+ ["o2", "o1", "o3", "o4"], [x.id for x in folder.objectValues()]\n )\n \n def test_objectItemsOrdered(self):\n folder = self.create()\n- self.assertEqual(\n- ["o1", "o2", "o3", "o4"],\n- [x for x, y in folder.objectItems()]\n- )\n+ self.assertEqual(["o1", "o2", "o3", "o4"], [x for x, y in folder.objectItems()])\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEqual(\n- ["o2", "o1", "o3", "o4"],\n- [x for x, y in folder.objectItems()]\n- )\n+ self.assertEqual(["o2", "o1", "o3", "o4"], [x for x, y in folder.objectItems()])\n \n def test_iterkeys(self):\n folder = self.create()\n- self.assertEqual(\n- ["o1", "o2", "o3", "o4"],\n- [x for x in folder.keys()]\n- )\n+ self.assertEqual(["o1", "o2", "o3", "o4"], [x for x in folder.keys()])\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEqual(\n- ["o2", "o1", "o3", "o4"],\n- [x for x in folder.keys()]\n- )\n+ self.assertEqual(["o2", "o1", "o3", "o4"], [x for x in folder.keys()])\n \n def test_iter(self):\n folder = self.create()\n@@ -80,11 +66,11 @@ def test_iter(self):\n \n def test_getitem(self):\n ordering = IOrdering(self.create())\n- self.assertEqual(ordering[1], \'o2\')\n- self.assertEqual(ordering[-1], \'o4\')\n- self.assertEqual(ordering[1:2], [\'o2\'])\n- self.assertEqual(ordering[1:-1], [\'o2\', \'o3\'])\n- self.assertEqual(ordering[1:], [\'o2\', \'o3\', \'o4\'])\n+ self.assertEqual(ordering[1], "o2")\n+ self.assertEqual(ordering[-1], "o4")\n+ self.assertEqual(ordering[1:2], ["o2"])\n+ self.assertEqual(ordering[1:-1], ["o2", "o3"])\n+ self.assertEqual(ordering[1:], ["o2", "o3", "o4"])\n \n # Tests borrowed from OFS.tests.testsOrderSupport\n \n@@ -92,271 +78,279 @@ def runTableTests(self, methodname, table):\n for args, order, rval in table:\n f = self.create()\n method = getattr(f, methodname)\n- if rval == \'ValueError\':\n+ if rval == "ValueError":\n self.assertRaises(ValueError, method, *args)\n else:\n self.assertEqual(method(*args), rval)\n self.assertEqual(f.objectIds(), order)\n \n def test_moveObjectsUp(self):\n- self.runTableTests(\'moveObjectsUp\',\n- ( ( ( \'o4\', 1 ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1 )\n- , ( ( \'o4\', 2 ), [\'o1\', \'o4\', \'o2\', \'o3\'], 1 )\n- , ( ( (\'o1\', \'o3\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o1\', \'o3\'), 9 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), 1 ), [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1)\n- , ( ( (\'o3\', \'o1\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsUp",\n+ (\n+ (("o4", 1), ["o1", "o2", "o4", "o3"], 1),\n+ (("o4", 2), ["o1", "o4", "o2", "o3"], 1),\n+ ((("o1", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o1", "o3"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o2", "o3", "o1", "o4"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o2", "o3", "o1", "o4"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o3", "o1"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def test_moveObjectsDown(self):\n- self.runTableTests(\'moveObjectsDown\',\n- ( ( ( \'o1\', 1 ), [\'o2\', \'o1\', \'o3\', \'o4\'], 1 )\n- , ( ( \'o1\', 2 ), [\'o2\', \'o3\', \'o1\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o4\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o4\'), 9 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), 1 ), [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), 1 ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1)\n- , ( ( (\'o4\', \'o2\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsDown",\n+ (\n+ (("o1", 1), ["o2", "o1", "o3", "o4"], 1),\n+ (("o1", 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("o2", "o4"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o4"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o1", "o4", "o2", "o3"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o1", "o4", "o2", "o3"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"), 1), ["o1", "o2", "o4", "o3"], 1),\n+ ((("o4", "o2"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def test_moveObjectsToTop(self):\n- self.runTableTests(\'moveObjectsToTop\',\n- ( ( ( \'o4\', ), [\'o4\', \'o1\', \'o2\', \'o3\'], 1 )\n- , ( ( (\'o1\', \'o3\'), ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), ), [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), ), [\'o3\', \'o1\', \'o2\', \'o4\'], 1)\n- , ( ( (\'o3\', \'o1\'), ), [\'o3\', \'o1\', \'o2\', \'o4\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsToTop",\n+ (\n+ (("o4",), ["o4", "o1", "o2", "o3"], 1),\n+ ((("o1", "o3"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"),), ["o3", "o1", "o2", "o4"], 1),\n+ ((("o3", "o1"),), ["o3", "o1", "o2", "o4"], 1),\n+ ),\n+ )\n \n def test_moveObjectsToBottom(self):\n- self.runTableTests(\'moveObjectsToBottom\',\n- ( ( ( \'o1\', ), [\'o2\', \'o3\', \'o4\', \'o1\'], 1 )\n- , ( ( (\'o2\', \'o4\'), ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), ), [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1)\n- , ( ( (\'o4\', \'o2\'), ), [\'o1\', \'o3\', \'o4\', \'o2\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsToBottom",\n+ (\n+ (("o1",), ["o2", "o3", "o4", "o1"], 1),\n+ ((("o2", "o4"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"),), ["o1", "o2", "o4", "o3"], 1),\n+ ((("o4", "o2"),), ["o1", "o3", "o4", "o2"], 1),\n+ ),\n+ )\n \n def test_orderObjects(self):\n- self.runTableTests(\'orderObjects\',\n- ( ( ( \'id\', \'id\' ), [\'o4\', \'o3\', \'o2\', \'o1\'], -1)\n- , ( ( \'meta_type\', \'\' ), [\'o1\', \'o3\', \'o2\', \'o4\'], -1)\n- # for the next line the sort order is different from the\n- # original test in OFS, since the current implementation\n- # keeps the original order as much as possible, i.e. minimize\n- # exchange operations within the list; this is correct as\n- # far as the test goes, since it didn\'t specify a secondary\n- # sort key...\n- , ( ( \'meta_type\', \'n\' ), [\'o2\', \'o4\', \'o1\', \'o3\'], -1)\n- )\n- )\n+ self.runTableTests(\n+ "orderObjects",\n+ (\n+ (("id", "id"), ["o4", "o3", "o2", "o1"], -1),\n+ (("meta_type", ""), ["o1", "o3", "o2", "o4"], -1)\n+ # for the next line the sort order is different from the\n+ # original test in OFS, since the current implementation\n+ # keeps the original order as much as possible, i.e. minimize\n+ # exchange operations within the list; this is correct as\n+ # far as the test goes, since it didn\'t specify a secondary\n+ # sort key...\n+ ,\n+ (("meta_type", "n"), ["o2", "o4", "o1", "o3"], -1),\n+ ),\n+ )\n \n def test_getObjectPosition(self):\n- self.runTableTests(\'getObjectPosition\',\n- ( ( ( \'o2\', ), [\'o1\', \'o2\', \'o3\', \'o4\'], 1)\n- , ( ( \'o4\', ), [\'o1\', \'o2\', \'o3\', \'o4\'], 3)\n- , ( ( \'n2\', ), [\'o1\', \'o2\', \'o3\', \'o4\'], \'ValueError\')\n- )\n- )\n+ self.runTableTests(\n+ "getObjectPosition",\n+ (\n+ (("o2",), ["o1", "o2", "o3", "o4"], 1),\n+ (("o4",), ["o1", "o2", "o3", "o4"], 3),\n+ (("n2",), ["o1", "o2", "o3", "o4"], "ValueError"),\n+ ),\n+ )\n \n def test_moveObjectToPosition(self):\n- self.runTableTests(\'moveObjectToPosition\',\n- ( ( ( \'o2\', 2 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1)\n- , ( ( \'o4\', 2 ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1)\n- , ( ( \'n2\', 2 ), [\'o1\', \'o2\', \'o3\', \'o4\'], \'ValueError\')\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectToPosition",\n+ (\n+ (("o2", 2), ["o1", "o3", "o2", "o4"], 1),\n+ (("o4", 2), ["o1", "o2", "o4", "o3"], 1),\n+ (("n2", 2), ["o1", "o2", "o3", "o4"], "ValueError"),\n+ ),\n+ )\n \n def test_getObjectPosition_error_message(self):\n folder = self.create()\n try:\n- folder.getObjectPosition(\'n4\')\n+ folder.getObjectPosition("n4")\n self.assertFail()\n except ValueError as err:\n- self.assertEqual(\n- str(err), \'No object with id "n4" exists in "f1".\')\n+ self.assertEqual(str(err), \'No object with id "n4" exists in "f1".\')\n \n \n class PloneOrderSupportTests(unittest.TestCase):\n- """ tests borrowed from Products.CMFPlone.tests.testOrderSupport """\n+ """tests borrowed from Products.CMFPlone.tests.testOrderSupport"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def setUp(self):\n self.folder = OrderedBTreeFolderBase("f1")\n- self.folder[\'foo\'] = DummyObject(\'foo\', \'mt1\')\n- self.folder[\'bar\'] = DummyObject(\'bar\', \'mt1\')\n- self.folder[\'baz\'] = DummyObject(\'baz\', \'mt1\')\n+ self.folder["foo"] = DummyObject("foo", "mt1")\n+ self.folder["bar"] = DummyObject("bar", "mt1")\n+ self.folder["baz"] = DummyObject("baz", "mt1")\n \n def testGetObjectPosition(self):\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObject(self):\n- self.folder.moveObjectToPosition(\'foo\', 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("foo", 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectToSamePos(self):\n- self.folder.moveObjectToPosition(\'bar\', 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("bar", 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectToFirstPos(self):\n- self.folder.moveObjectToPosition(\'bar\', 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("bar", 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectToLastPos(self):\n- self.folder.moveObjectToPosition(\'bar\', 2)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectToPosition("bar", 2)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveObjectOutLowerBounds(self):\n # Pos will be normalized to 0\n- self.folder.moveObjectToPosition(\'bar\', -1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("bar", -1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectOutUpperBounds(self):\n # Pos will be normalized to 2\n- self.folder.moveObjectToPosition(\'bar\', 3)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectToPosition("bar", 3)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveObjectsUp(self):\n- self.folder.moveObjectsUp([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectsUp(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectsDown(self):\n- self.folder.moveObjectsDown([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsDown(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveObjectsToTop(self):\n- self.folder.moveObjectsToTop([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectsToTop(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectsToBottom(self):\n- self.folder.moveObjectsToBottom([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsToBottom(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveTwoObjectsUp(self):\n- self.folder.moveObjectsUp([\'bar\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.moveObjectsUp(["bar", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testMoveTwoObjectsDown(self):\n- self.folder.moveObjectsDown([\'foo\', \'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsDown(["foo", "bar"])\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveTwoObjectsToTop(self):\n- self.folder.moveObjectsToTop([\'bar\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.moveObjectsToTop(["bar", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testMoveTwoObjectsToBottom(self):\n- self.folder.moveObjectsToBottom([\'foo\', \'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsToBottom(["foo", "bar"])\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testOrderObjects(self):\n- self.folder.orderObjects(\'id\')\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.orderObjects("id")\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testOrderObjectsReverse(self):\n- self.folder.orderObjects(\'id\', reverse=True)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.orderObjects("id", reverse=True)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testOrderObjectsByMethod(self):\n- self.folder.orderObjects(\'dummy_method\')\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.orderObjects("dummy_method")\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testOrderObjectsOnlyReverse(self):\n self.folder.orderObjects(reverse=True)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testSubsetIds(self):\n- self.folder.moveObjectsByDelta([\'baz\'], -1, [\'foo\', \'bar\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsByDelta(["baz"], -1, ["foo", "bar", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testSkipObjectsNotInSubsetIds(self):\n- self.folder.moveObjectsByDelta([\'baz\'], -1, [\'foo\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1) # no move\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.moveObjectsByDelta(["baz"], -1, ["foo", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1) # no move\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testIgnoreNonObjects(self):\n # Fix for (http://dev.plone.org/plone/ticket/3959) non\n # contentish objects cause errors, we should just ignore them\n- self.folder.moveObjectsByDelta([\'bar\', \'blah\'], -1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectsByDelta(["bar", "blah"], -1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testNotifyRemoved(self):\n ordering = self.folder.getOrdering()\n- self.assertEqual(\n- ordering.idsInOrder(),\n- [\'foo\', \'bar\', \'baz\']\n- )\n+ self.assertEqual(ordering.idsInOrder(), ["foo", "bar", "baz"])\n \n # make sure notifyRemoved with non-existent id does not throw error\n- ordering.notifyRemoved(\'foobar\')\n+ ordering.notifyRemoved("foobar")\n \n # normal\n- ordering.notifyRemoved(\'foo\')\n- self.assertEqual(\n- ordering.idsInOrder(),\n- [\'bar\', \'baz\']\n- )\n+ ordering.notifyRemoved("foo")\n+ self.assertEqual(ordering.idsInOrder(), ["bar", "baz"])\ndiff --git a/src/plone/folder/tests/test_partialordering.py b/src/plone/folder/tests/test_partialordering.py\nindex d3a28e0..eca9544 100644\n--- a/src/plone/folder/tests/test_partialordering.py\n+++ b/src/plone/folder/tests/test_partialordering.py\n@@ -13,21 +13,21 @@\n \n \n class PartialOrderingTests(unittest.TestCase):\n- """ tests regarding order-support for only items marked orderable """\n+ """tests regarding order-support for only items marked orderable"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n container = OrderedBTreeFolderBase()\n- container.setOrdering(\'partial\')\n- container[\'o1\'] = Orderable(\'o1\', \'mt1\')\n- container[\'o2\'] = Orderable(\'o2\', \'mt2\')\n- container[\'c1\'] = Chaoticle(\'c1\', \'mt3\')\n- container[\'o3\'] = Orderable(\'o3\', \'mt1\')\n- container[\'c2\'] = Chaoticle(\'c2\', \'mt2\')\n- container[\'c3\'] = Chaoticle(\'c3\', \'mt1\')\n- container[\'o4\'] = Orderable(\'o4\', \'mt2\')\n- self.unordered = [\'c1\', \'c2\', \'c3\']\n+ container.setOrdering("partial")\n+ container["o1"] = Orderable("o1", "mt1")\n+ container["o2"] = Orderable("o2", "mt2")\n+ container["c1"] = Chaoticle("c1", "mt3")\n+ container["o3"] = Orderable("o3", "mt1")\n+ container["c2"] = Chaoticle("c2", "mt2")\n+ container["c3"] = Chaoticle("c3", "mt1")\n+ container["o4"] = Orderable("o4", "mt2")\n+ self.unordered = ["c1", "c2", "c3"]\n ordering = container.getOrdering()\n return container, ordering\n \n@@ -38,43 +38,29 @@ def testAdapter(self):\n def testNotifyAdded(self):\n container, ordering = self.create()\n self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o3\', \'o4\'] + self.unordered\n+ ordering.idsInOrder(), ["o1", "o2", "o3", "o4"] + self.unordered\n )\n- container[\'o5\'] = Orderable(\'o5\')\n+ container["o5"] = Orderable("o5")\n self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o3\', \'o4\', \'o5\'] + self.unordered\n+ ordering.idsInOrder(), ["o1", "o2", "o3", "o4", "o5"] + self.unordered\n )\n self.assertEqual(\n- set(container.objectIds()),\n- {\'o1\', \'o2\', \'o3\', \'o4\', \'o5\', \'c1\', \'c2\', \'c3\'}\n+ set(container.objectIds()), {"o1", "o2", "o3", "o4", "o5", "c1", "c2", "c3"}\n )\n \n def testNotifyRemoved(self):\n container, ordering = self.create()\n self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o3\', \'o4\'] + self.unordered\n+ ordering.idsInOrder(), ["o1", "o2", "o3", "o4"] + self.unordered\n )\n- container._delOb(\'o3\')\n+ container._delOb("o3")\n+ self.assertEqual(ordering.idsInOrder(), ["o1", "o2", "o4"] + self.unordered)\n self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o4\'] + self.unordered\n- )\n- self.assertEqual(\n- set(container.objectIds()),\n- {\'o1\', \'o2\', \'o4\', \'c1\', \'c2\', \'c3\'}\n- )\n- container._delOb(\'o1\')\n- self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o2\', \'o4\'] + self.unordered\n- )\n- self.assertEqual(\n- set(container.objectIds()),\n- {\'o2\', \'o4\', \'c1\', \'c2\', \'c3\'}\n+ set(container.objectIds()), {"o1", "o2", "o4", "c1", "c2", "c3"}\n )\n+ container._delOb("o1")\n+ self.assertEqual(ordering.idsInOrder(), ["o2", "o4"] + self.unordered)\n+ self.assertEqual(set(container.objectIds()), {"o2", "o4", "c1", "c2", "c3"})\n \n def runTableTests(self, action, tests):\n for args, order, rval in tests:\n@@ -86,132 +72,175 @@ def runTableTests(self, action, tests):\n else:\n self.assertEqual(method(*args), rval)\n self.assertEqual(ordering.idsInOrder(), order + self.unordered)\n- self.assertEqual(set(container.objectIds()), ids) # all here?\n+ self.assertEqual(set(container.objectIds()), ids) # all here?\n \n def testMoveObjectsByDelta(self):\n- self.runTableTests(\'moveObjectsByDelta\', (\n- ((\'o1\', 1), [\'o2\', \'o1\', \'o3\', \'o4\'], 1),\n- ((\'o1\', 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'o2\', \'o4\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o4\'), 9), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'), 1), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o1\'), 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'c1\', \'o3\'), 1), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- (((\'n2\', \'o2\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o4\', \'o2\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsByDelta",\n+ (\n+ (("o1", 1), ["o2", "o1", "o3", "o4"], 1),\n+ (("o1", 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("o2", "o4"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o4"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o1", "o4", "o2", "o3"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o1", "o4", "o2", "o3"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o1"), 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("c1", "o3"), 1), ["o1", "o2", "o4", "o3"], 1),\n+ ((("n2", "o2"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o4", "o2"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsDown(self):\n- self.runTableTests(\'moveObjectsDown\', (\n- ((\'o1\',), [\'o2\', \'o1\', \'o3\', \'o4\'], 1),\n- ((\'o1\', 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'o2\', \'o4\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o4\'), 9), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'),), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o1\'), 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'c1\', \'o3\'),), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- (((\'n2\', \'o2\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o4\', \'o2\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsDown",\n+ (\n+ (("o1",), ["o2", "o1", "o3", "o4"], 1),\n+ (("o1", 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("o2", "o4"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o4"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o1", "o4", "o2", "o3"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o1", "o4", "o2", "o3"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o1"), 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("c1", "o3"),), ["o1", "o2", "o4", "o3"], 1),\n+ ((("n2", "o2"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o4", "o2"),), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsUp(self):\n- self.runTableTests(\'moveObjectsUp\', (\n- ((\'o4\',), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- ((\'o4\', 1), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- ((\'o4\', 2), [\'o1\', \'o4\', \'o2\', \'o3\'], 1),\n- (((\'o1\', \'o3\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o1\', \'o3\'), 9), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'), 1), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o2\', \'o3\', \'o4\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o4\'), 2), [\'o1\', \'o4\', \'o2\', \'o3\'], 1),\n- (((\'c1\', \'o3\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'n2\', \'o3\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o3\', \'o1\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsUp",\n+ (\n+ (("o4",), ["o1", "o2", "o4", "o3"], 1),\n+ (("o4", 1), ["o1", "o2", "o4", "o3"], 1),\n+ (("o4", 2), ["o1", "o4", "o2", "o3"], 1),\n+ ((("o1", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o1", "o3"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o2", "o3", "o1", "o4"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o2", "o3", "o1", "o4"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o4"), 2), ["o1", "o4", "o2", "o3"], 1),\n+ ((("c1", "o3"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("n2", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o3", "o1"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsToTop(self):\n- self.runTableTests(\'moveObjectsToTop\', (\n- ((\'o4\',), [\'o4\', \'o1\', \'o2\', \'o3\'], 1),\n- (((\'o1\', \'o3\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'),), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), (\'o2\', \'o3\', \'o4\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o4\'),), [\'o4\', \'o1\', \'o2\', \'o3\'], 1),\n- (((\'c1\', \'o3\'),), [\'o3\', \'o1\', \'o2\', \'o4\'], 1),\n- (((\'n2\', \'o3\'),), [\'o3\', \'o1\', \'o2\', \'o4\'], 1),\n- (((\'o3\', \'o1\'),), [\'o3\', \'o1\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsToTop",\n+ (\n+ (("o4",), ["o4", "o1", "o2", "o3"], 1),\n+ ((("o1", "o3"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o4"),), ["o4", "o1", "o2", "o3"], 1),\n+ ((("c1", "o3"),), ["o3", "o1", "o2", "o4"], 1),\n+ ((("n2", "o3"),), ["o3", "o1", "o2", "o4"], 1),\n+ ((("o3", "o1"),), ["o3", "o1", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsToBottom(self):\n- self.runTableTests(\'moveObjectsToBottom\', (\n- ((\'o1\',), [\'o2\', \'o3\', \'o4\', \'o1\'], 1),\n- (((\'o2\', \'o4\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'),), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o1\'),), [\'o2\', \'o3\', \'o4\', \'o1\'], 1),\n- (((\'c1\', \'o2\'),), [\'o1\', \'o3\', \'o4\', \'o2\'], 1),\n- (((\'n2\', \'o3\'),), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- (((\'o4\', \'o2\'),), [\'o1\', \'o3\', \'o4\', \'o2\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsToBottom",\n+ (\n+ (("o1",), ["o2", "o3", "o4", "o1"], 1),\n+ ((("o2", "o4"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o1"),), ["o2", "o3", "o4", "o1"], 1),\n+ ((("c1", "o2"),), ["o1", "o3", "o4", "o2"], 1),\n+ ((("n2", "o3"),), ["o1", "o2", "o4", "o3"], 1),\n+ ((("o4", "o2"),), ["o1", "o3", "o4", "o2"], 1),\n+ ),\n+ )\n \n def testMoveObjectToPosition(self):\n- self.runTableTests(\'moveObjectToPosition\', (\n- ((\'o2\', 2), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ((\'o4\', 2), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- ((\'c1\', 2), [\'o1\', \'o2\', \'o3\', \'o4\'], None), # existent, but non-orderable\n- ((\'n2\', 2), [\'o1\', \'o2\', \'o3\', \'o4\'], ValueError),\n- ))\n+ self.runTableTests(\n+ "moveObjectToPosition",\n+ (\n+ (("o2", 2), ["o1", "o3", "o2", "o4"], 1),\n+ (("o4", 2), ["o1", "o2", "o4", "o3"], 1),\n+ (\n+ ("c1", 2),\n+ ["o1", "o2", "o3", "o4"],\n+ None,\n+ ), # existent, but non-orderable\n+ (("n2", 2), ["o1", "o2", "o3", "o4"], ValueError),\n+ ),\n+ )\n \n def testOrderObjects(self):\n- self.runTableTests(\'orderObjects\', (\n- ((\'id\', \'id\'), [\'o4\', \'o3\', \'o2\', \'o1\'], -1),\n- ((\'meta_type\', \'\'), [\'o1\', \'o3\', \'o2\', \'o4\'], -1),\n- # for the next line the sort order is different from the\n- # original test in OFS, since the current implementation\n- # keeps the original order as much as possible, i.e. minimize\n- # exchange operations within the list; this is correct as\n- # far as the test goes, since it didn\'t specify a secondary\n- # sort key...\n- ((\'meta_type\', \'n\'), [\'o2\', \'o4\', \'o1\', \'o3\'], -1),\n- ))\n+ self.runTableTests(\n+ "orderObjects",\n+ (\n+ (("id", "id"), ["o4", "o3", "o2", "o1"], -1),\n+ (("meta_type", ""), ["o1", "o3", "o2", "o4"], -1),\n+ # for the next line the sort order is different from the\n+ # original test in OFS, since the current implementation\n+ # keeps the original order as much as possible, i.e. minimize\n+ # exchange operations within the list; this is correct as\n+ # far as the test goes, since it didn\'t specify a secondary\n+ # sort key...\n+ (("meta_type", "n"), ["o2", "o4", "o1", "o3"], -1),\n+ ),\n+ )\n \n def testGetObjectPosition(self):\n- self.runTableTests(\'getObjectPosition\', (\n- ((\'o2\',), [\'o1\', \'o2\', \'o3\', \'o4\'], 1),\n- ((\'o4\',), [\'o1\', \'o2\', \'o3\', \'o4\'], 3),\n- ((\'n2\',), [\'o1\', \'o2\', \'o3\', \'o4\'], ValueError),\n- ((\'c2\',), [\'o1\', \'o2\', \'o3\', \'o4\'], None), # existent, but non-orderable\n- ))\n+ self.runTableTests(\n+ "getObjectPosition",\n+ (\n+ (("o2",), ["o1", "o2", "o3", "o4"], 1),\n+ (("o4",), ["o1", "o2", "o3", "o4"], 3),\n+ (("n2",), ["o1", "o2", "o3", "o4"], ValueError),\n+ (\n+ ("c2",),\n+ ["o1", "o2", "o3", "o4"],\n+ None,\n+ ), # existent, but non-orderable\n+ ),\n+ )\n \n \n @implementer(IOrderable)\n class DummyFolder(OrderedBTreeFolderBase, Implicit):\n- """ we need to mix in acquisition """\n+ """we need to mix in acquisition"""\n \n- meta_type = \'DummyFolder\'\n- _ordering = \'partial\'\n+ meta_type = "DummyFolder"\n+ _ordering = "partial"\n \n def dummy_method(self):\n return self.id\n \n \n class PartialOrderingIntegrationTests(unittest.TestCase):\n-\n layer = PLONEFOLDER_FUNCTIONAL_TESTING\n \n def setUp(self):\n- self.app = self.layer[\'app\']\n+ self.app = self.layer["app"]\n context = self.app\n- context._setOb(\'foo\', DummyFolder(\'foo\')) # not pythonic in 2.10 :(\n- context.foo[\'bar1\'] = DummyFolder(\'bar1\')\n- context.foo[\'bar2\'] = DummyFolder(\'bar2\')\n- context.foo[\'bar3\'] = DummyFolder(\'bar3\')\n+ context._setOb("foo", DummyFolder("foo")) # not pythonic in 2.10 :(\n+ context.foo["bar1"] = DummyFolder("bar1")\n+ context.foo["bar2"] = DummyFolder("bar2")\n+ context.foo["bar3"] = DummyFolder("bar3")\n savepoint(optimistic=True)\n self.assertEqual(self.registered, [])\n \n@@ -221,36 +250,38 @@ def registered(self):\n \n def testAddObjectChangesOrderInfo(self):\n foo = self.app.foo\n- foo[\'bar23\'] = DummyFolder(\'bar23\')\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar2\', \'bar3\', \'bar23\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo["bar23"] = DummyFolder("bar23")\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar2", "bar3", "bar23"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n \n def testRemoveObjectChangesOrderInfo(self):\n foo = self.app.foo\n- foo._delOb(\'bar2\',)\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar3\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo._delOb(\n+ "bar2",\n+ )\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar3"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n \n def testMoveObjectChangesOrderInfo(self):\n foo = self.app.foo\n- foo.moveObjectsUp((\'bar2\',))\n- self.assertEqual(foo.objectIds(), [\'bar2\', \'bar1\', \'bar3\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo.moveObjectsUp(("bar2",))\n+ self.assertEqual(foo.objectIds(), ["bar2", "bar1", "bar3"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n \n def testOrderObjectsChangesOrderInfo(self):\n foo = self.app.foo\n- foo.orderObjects(\'id\', reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar3\', \'bar2\', \'bar1\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo.orderObjects("id", reverse=True)\n+ self.assertEqual(foo.objectIds(), ["bar3", "bar2", "bar1"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n # Reverse the current ordering.\n foo.orderObjects(reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar2\', \'bar3\'])\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar2", "bar3"])\n \n def testOrderObjectsByMethodChangesOrderInfo(self):\n foo = self.app.foo\n- foo.orderObjects(\'dummy_method\', reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar3\', \'bar2\', \'bar1\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo.orderObjects("dummy_method", reverse=True)\n+ self.assertEqual(foo.objectIds(), ["bar3", "bar2", "bar1"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n # Reverse the current ordering.\n foo.orderObjects(reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar2\', \'bar3\'])\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar2", "bar3"])\ndiff --git a/src/plone/folder/tests/test_unorderedordering.py b/src/plone/folder/tests/test_unorderedordering.py\nindex be922b2..f780870 100644\n--- a/src/plone/folder/tests/test_unorderedordering.py\n+++ b/src/plone/folder/tests/test_unorderedordering.py\n@@ -7,17 +7,17 @@\n \n \n class UnorderedOrderingTests(unittest.TestCase):\n- """ tests regarding order-support for folders with unordered ordering """\n+ """tests regarding order-support for folders with unordered ordering"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n container = OrderedBTreeFolderBase()\n- container._ordering = \'unordered\'\n- container._setOb(\'o1\', DummyObject(\'o1\', \'mt1\'))\n- container._setOb(\'o2\', DummyObject(\'o2\', \'mt2\'))\n- container._setOb(\'o3\', DummyObject(\'o3\', \'mt1\'))\n- container._setOb(\'o4\', DummyObject(\'o4\', \'mt2\'))\n+ container._ordering = "unordered"\n+ container._setOb("o1", DummyObject("o1", "mt1"))\n+ container._setOb("o2", DummyObject("o2", "mt2"))\n+ container._setOb("o3", DummyObject("o3", "mt1"))\n+ container._setOb("o4", DummyObject("o4", "mt2"))\n return container\n \n def testAdapter(self):\n@@ -27,28 +27,16 @@ def testAdapter(self):\n \n def testNotifyAdded(self):\n container = self.create()\n- self.assertEqual(\n- set(container.objectIds()),\n- {\'o1\', \'o2\', \'o3\', \'o4\'}\n- )\n- container._setOb(\'o5\', DummyObject(\'o5\', \'mt1\'))\n- self.assertEqual(\n- set(container.objectIds()),\n- {\'o1\', \'o2\', \'o3\', \'o4\', \'o5\'}\n- )\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o3", "o4"})\n+ container._setOb("o5", DummyObject("o5", "mt1"))\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o3", "o4", "o5"})\n \n def testNotifyRemoved(self):\n container = self.create()\n- self.assertEqual(\n- set(container.objectIds()),\n- {\'o1\', \'o2\', \'o3\', \'o4\'}\n- )\n- container._delOb(\'o3\')\n- self.assertEqual(\n- set(container.objectIds()),\n- {\'o1\', \'o2\', \'o4\'}\n- )\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o3", "o4"})\n+ container._delOb("o3")\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o4"})\n \n def testGetObjectPosition(self):\n container = self.create()\n- self.assertEqual(container.getObjectPosition(\'o2\'), None)\n+ self.assertEqual(container.getObjectPosition("o2"), None)\ndiff --git a/src/plone/folder/tests/test_webdav.py b/src/plone/folder/tests/test_webdav.py\nindex 7f2cb18..338b628 100644\n--- a/src/plone/folder/tests/test_webdav.py\n+++ b/src/plone/folder/tests/test_webdav.py\n@@ -16,12 +16,11 @@\n \n \n class TestRequestContainer(Explicit):\n-\n REQUEST = TestRequest()\n \n \n class WebDAVTests(unittest.TestCase):\n- """ tests regarding support for WebDAV NullResources """\n+ """tests regarding support for WebDAV NullResources"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n@@ -30,28 +29,28 @@ def test_getitem_not_dav_request(self):\n folder = CMFOrderedBTreeFolderBase("f1").__of__(root)\n \n root.REQUEST.maybe_webdav_client = False\n- root.REQUEST._environ[\'REQUEST_METHOD\'] = \'GET\'\n+ root.REQUEST._environ["REQUEST_METHOD"] = "GET"\n \n- foo = DummyObject(\'foo\')\n- folder[\'foo\'] = foo\n+ foo = DummyObject("foo")\n+ folder["foo"] = foo\n \n- self.assertEqual(folder[\'foo\'], foo)\n+ self.assertEqual(folder["foo"], foo)\n try:\n- folder[\'bar\']\n+ folder["bar"]\n self.fail()\n except KeyError:\n pass\n \n- @unittest.skipUnless(HAS_WEBDAV, \'ZServer is optional\')\n+ @unittest.skipUnless(HAS_WEBDAV, "ZServer is optional")\n def test_getitem_dav_request(self):\n root = TestRequestContainer()\n folder = CMFOrderedBTreeFolderBase("f1").__of__(root)\n \n root.REQUEST.maybe_webdav_client = True\n- root.REQUEST._environ[\'REQUEST_METHOD\'] = \'PUT\'\n+ root.REQUEST._environ["REQUEST_METHOD"] = "PUT"\n \n- foo = DummyObject(\'foo\')\n- folder[\'foo\'] = foo\n+ foo = DummyObject("foo")\n+ folder["foo"] = foo\n \n- self.assertEqual(folder[\'foo\'], foo)\n- self.assertTrue(isinstance(folder[\'bar\'], NullResource))\n+ self.assertEqual(folder["foo"], foo)\n+ self.assertTrue(isinstance(folder["bar"], NullResource))\ndiff --git a/src/plone/folder/tests/utils.py b/src/plone/folder/tests/utils.py\nindex d81e2e9..aa1e79f 100644\n--- a/src/plone/folder/tests/utils.py\n+++ b/src/plone/folder/tests/utils.py\n@@ -3,7 +3,6 @@\n \n \n class DummyObject:\n-\n def __init__(self, id, meta_type=None):\n self.id = id\n self.meta_type = meta_type\n@@ -20,8 +19,8 @@ def dummy_method(self):\n \n @implementer(IOrderable)\n class Orderable(DummyObject):\n- """ orderable mock object """\n+ """orderable mock object"""\n \n \n class Chaoticle(DummyObject):\n- """ non-orderable mock object; this does not implement `IOrderable` """\n+ """non-orderable mock object; this does not implement `IOrderable`"""\ndiff --git a/src/plone/folder/unordered.py b/src/plone/folder/unordered.py\nindex ea82a74..751443b 100644\n--- a/src/plone/folder/unordered.py\n+++ b/src/plone/folder/unordered.py\n@@ -8,7 +8,7 @@\n @implementer(IOrdering)\n @adapter(IOrderableFolder)\n class UnorderedOrdering:\n- """ This implementation provides no ordering. """\n+ """This implementation provides no ordering."""\n \n def __init__(self, context):\n self.context = context\n' + +Repository: plone.folder + + +Branch: refs/heads/master +Date: 2023-04-15T14:32:29+02:00 +Author: Gil Forcada Codinachs (gforcada) +Commit: https://github.com/plone/plone.folder/commit/6d9d88b2dda1854e2754e816f4adb82b2177a23d + +chore: zpretty Files changed: -M plone/event/tests/test_recurrence_int_sequence.py -M plone/event/tests/test_recurrence_sequence_ical.py -M plone/event/tests/test_recurrence_sequence_timedelta.py -M plone/event/tests/test_utils.py +M src/plone/folder/configure.zcml -b'diff --git a/plone/event/tests/test_recurrence_int_sequence.py b/plone/event/tests/test_recurrence_int_sequence.py\nindex 00f7ec8..b858a9c 100644\n--- a/plone/event/tests/test_recurrence_int_sequence.py\n+++ b/plone/event/tests/test_recurrence_int_sequence.py\n@@ -1,4 +1,5 @@\n from unittest import mock\n+\n import unittest\n \n \ndiff --git a/plone/event/tests/test_recurrence_sequence_ical.py b/plone/event/tests/test_recurrence_sequence_ical.py\nindex 679cb77..ae08c8f 100644\n--- a/plone/event/tests/test_recurrence_sequence_ical.py\n+++ b/plone/event/tests/test_recurrence_sequence_ical.py\n@@ -3,16 +3,16 @@\n \n class TestRecurrenceSequenceIcal(unittest.TestCase):\n def test_start(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23)\n seq = recurrence_sequence_ical(start)\n results = [res for res in seq]\n self.assertEqual(len(results), 1)\n \n def test_recrule_str(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23)\n recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=5\'\n seq = recurrence_sequence_ical(start, recrule=recrule)\n@@ -23,8 +23,8 @@ def test_recrule_str_rdate(self):\n """Test, if an RDATE date has the correct time set.\n See: "BUGFIX WRONG RDATE TIME" in recurrence.py\n """\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23, 10, 10)\n recrule = """FREQ=DAILY;INTERVAL=1;COUNT=3\n RDATE:20111129T000000"""\n@@ -36,8 +36,9 @@ def test_recrule_str_rdate(self):\n def test_recrule_str_exdate(self):\n """Test, if an EXDATE date are not in the resulting recurrence set.\n """\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n import pytz\n at = pytz.timezone(\'Europe/Vienna\')\n start = at.localize(datetime(2013, 6, 29, 10, 10))\n@@ -57,8 +58,9 @@ def test_recrule_str_until(self):\n """Test, if UNTIL stops the sequence at the end of the day, even if\n it\'s set to 0:00 by the recurrence widget.\n """\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n import pytz\n at = pytz.timezone(\'Europe/Vienna\')\n start = at.localize(datetime(2013, 6, 29, 10, 10))\n@@ -75,8 +77,8 @@ def test_recrule_str_until(self):\n self.assertEqual(res, res_test)\n \n def test_recrule_from_until(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23)\n recrule = None\n from_ = datetime(2011, 11, 1)\n@@ -91,8 +93,8 @@ def test_recrule_from_until(self):\n self.assertEqual(len(results), 1)\n \n def test_recrule_str_more_than_MAXCOUNT(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23)\n recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=1001\'\n seq = recurrence_sequence_ical(start, recrule=recrule)\n@@ -100,8 +102,8 @@ def test_recrule_str_more_than_MAXCOUNT(self):\n self.assertEqual(len(results), 1000)\n \n def test_recrule_str_more_than_count(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23)\n recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=10\'\n count = 5\n@@ -110,8 +112,8 @@ def test_recrule_str_more_than_count(self):\n self.assertEqual(len(results), 5)\n \n def test_recrule_from(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23)\n recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n from_ = datetime(2011, 11, 25)\n@@ -126,8 +128,8 @@ def test_recrule_from(self):\n self.assertEqual(len(results), 3)\n \n def test_recrule_until(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 24)\n recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n from_ = datetime(2011, 11, 23)\n@@ -144,9 +146,9 @@ def test_recrule_until(self):\n def test_recrule_from_until_with_duration(self):\n """Should include events ranging into the queried timerange.\n """\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n from datetime import timedelta\n+ from plone.event.recurrence import recurrence_sequence_ical\n start = datetime(2011, 11, 23)\n recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n from_ = datetime(2011, 11, 26)\n@@ -162,8 +164,8 @@ def test_recrule_from_until_with_duration(self):\n self.assertEqual(len(results), 4)\n \n def test_recrule_until_with_timezone(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n \n start = datetime(2011, 11, 24)\n recrule = \'RRULE:FREQ=DAILY;UNTIL=20111130T000000Z\'\ndiff --git a/plone/event/tests/test_recurrence_sequence_timedelta.py b/plone/event/tests/test_recurrence_sequence_timedelta.py\nindex 9cc407a..fdb21af 100644\n--- a/plone/event/tests/test_recurrence_sequence_timedelta.py\n+++ b/plone/event/tests/test_recurrence_sequence_timedelta.py\n@@ -3,8 +3,8 @@\n \n class TestRecurrenceSequenceTimedelta(unittest.TestCase):\n def test_delta_None(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n start = datetime(2011, 11, 23)\n until = datetime(2011, 11, 24)\n td = recurrence_sequence_timedelta(start, until=until)\n@@ -12,8 +12,8 @@ def test_delta_None(self):\n self.assertEqual(len(results), 1)\n \n def test_delta_zero(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n start = datetime(2011, 11, 23)\n delta = 0\n until = datetime(2011, 11, 24)\n@@ -22,8 +22,8 @@ def test_delta_zero(self):\n self.assertEqual(len(results), 1)\n \n def test_until_None(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n start = datetime(2011, 11, 23)\n delta = 1\n td = recurrence_sequence_timedelta(start, delta=delta)\n@@ -31,8 +31,8 @@ def test_until_None(self):\n self.assertEqual(len(results), 1)\n \n def test_delta_an_hour_until_next_day(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n start = datetime(2011, 11, 23)\n delta = 60\n until = datetime(2011, 11, 24)\n@@ -41,8 +41,8 @@ def test_delta_an_hour_until_next_day(self):\n self.assertEqual(len(results), 25)\n \n def test_recur_more_than_MAXCOUNT(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n start = datetime(2011, 11, 23)\n delta = 1\n until = datetime(2012, 11, 23)\n@@ -51,8 +51,8 @@ def test_recur_more_than_MAXCOUNT(self):\n self.assertEqual(len(results), 1001)\n \n def test_recur_more_than_count(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n start = datetime(2011, 11, 23)\n delta = 1\n until = datetime(2011, 11, 24)\ndiff --git a/plone/event/tests/test_utils.py b/plone/event/tests/test_utils.py\nindex f2a8e7e..0576920 100644\n--- a/plone/event/tests/test_utils.py\n+++ b/plone/event/tests/test_utils.py\n@@ -1,4 +1,5 @@\n from unittest import mock\n+\n import unittest\n \n \n' +b'diff --git a/src/plone/folder/configure.zcml b/src/plone/folder/configure.zcml\nindex 490a8f4..ce40737 100644\n--- a/src/plone/folder/configure.zcml\n+++ b/src/plone/folder/configure.zcml\n@@ -1,11 +1,16 @@\n \n+ i18n_domain="plone.folder"\n+ >\n \n- \n- \n- \n+ \n+ \n+ \n \n-\n\\ No newline at end of file\n+\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:13:22+02:00 +Date: 2023-04-15T14:34:44+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/dfc81ff143aa27cb7fdca0196cf8a34c31fd1eb6 +Commit: https://github.com/plone/plone.folder/commit/2571b9c23d7f0498c18cc92a12666edaf86265d1 -chore: black +chore: update trove classifiers Files changed: -M plone/__init__.py -M plone/event/adapters.py -M plone/event/interfaces.py -M plone/event/recurrence.py -M plone/event/tests/test_adapters.py -M plone/event/tests/test_doctest.py -M plone/event/tests/test_recurrence_int_sequence.py -M plone/event/tests/test_recurrence_sequence_ical.py -M plone/event/tests/test_recurrence_sequence_timedelta.py -M plone/event/tests/test_utils.py M setup.py -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/event/adapters.py b/plone/event/adapters.py\nindex 2ce3afc..2549298 100644\n--- a/plone/event/adapters.py\n+++ b/plone/event/adapters.py\n@@ -14,7 +14,7 @@ class EventAccessor:\n """\n \n def __init__(self, context):\n- object.__setattr__(self, \'context\', context)\n+ object.__setattr__(self, "context", context)\n \n def __getattr__(self, name):\n return getattr(self.context, name)\ndiff --git a/plone/event/interfaces.py b/plone/event/interfaces.py\nindex 8dc85bc..5f3af6e 100644\n--- a/plone/event/interfaces.py\n+++ b/plone/event/interfaces.py\n@@ -3,9 +3,7 @@\n \n \n class IEvent(Interface):\n- """Event type marker interface.\n-\n- """\n+ """Event type marker interface."""\n \n \n class IEventRecurrence(Interface):\n@@ -20,8 +18,9 @@ class IOccurrence(Interface):\n occurrence.\n \n """\n- start = Attribute(\'Occurrence start date\')\n- end = Attribute(\'Occurrence end date\')\n+\n+ start = Attribute("Occurrence start date")\n+ end = Attribute("Occurrence end date")\n \n \n class ICalendarAccessor(Interface):\n@@ -30,16 +29,15 @@ class ICalendarAccessor(Interface):\n A calendar is a collection of calendar components, like events.\n \n """\n- uid = Attribute(\'UID of the calendar. Autogenerated, read only.\')\n+\n+ uid = Attribute("UID of the calendar. Autogenerated, read only.")\n # rw attributes\n- title = Attribute(\'Calendar title.\')\n- description = Attribute(\'Calendar description text.\')\n- timezone = Attribute(\'Default timezone of the calendar.\')\n+ title = Attribute("Calendar title.")\n+ description = Attribute("Calendar description text.")\n+ timezone = Attribute("Default timezone of the calendar.")\n \n def items(self):\n- """Return a list of calendar component items, like events.\n-\n- """\n+ """Return a list of calendar component items, like events."""\n \n \n class IEventAccessor(Interface):\n@@ -51,40 +49,38 @@ class IEventAccessor(Interface):\n """\n \n # ro attributes\n- uid = Attribute(\'UID of the event. Autogenerated, read only.\')\n- created = Attribute(\'Python datetime of the event creation timestamp.\')\n- duration = Attribute(\'Duration of the event. Computed attribute.\')\n+ uid = Attribute("UID of the event. Autogenerated, read only.")\n+ created = Attribute("Python datetime of the event creation timestamp.")\n+ duration = Attribute("Duration of the event. Computed attribute.")\n \n # reference\n url = Attribute(\n- \'Cannonical, unique url of the event. External events \'\n- \'are referenced by the origin url unless explicitly set.\'\n+ "Cannonical, unique url of the event. External events "\n+ "are referenced by the origin url unless explicitly set."\n )\n \n # rw attributes\n- last_modified = Attribute(\'Last modified Python datetime.\')\n- title = Attribute(\'Event title.\')\n- description = Attribute(\'Event description text.\')\n- start = Attribute(\'Event start date as Python datetime.\')\n- end = Attribute(\'Event end date as Python datetime.\')\n- whole_day = Attribute(\'Event lasts whole day.\')\n- open_end = Attribute(\'Event has no defined end time.\')\n- timezone = Attribute(\'Timezone of the event. A pytz timezone identifier.\')\n- recurrence = Attribute(\'RFC5545 compatible recurrence definition.\')\n- location = Attribute(\'Location of the event.\')\n- attendees = Attribute(\'List of attendees.\')\n- contact_name = Attribute(\'Contact name.\')\n- contact_email = Attribute(\'Contact email.\')\n- contact_phone = Attribute(\'Contact phone.\')\n- event_url = Attribute(\'Website of the event.\')\n- subjects = Attribute(\'Categories.\')\n- text = Attribute(\'Body text of the event.\')\n+ last_modified = Attribute("Last modified Python datetime.")\n+ title = Attribute("Event title.")\n+ description = Attribute("Event description text.")\n+ start = Attribute("Event start date as Python datetime.")\n+ end = Attribute("Event end date as Python datetime.")\n+ whole_day = Attribute("Event lasts whole day.")\n+ open_end = Attribute("Event has no defined end time.")\n+ timezone = Attribute("Timezone of the event. A pytz timezone identifier.")\n+ recurrence = Attribute("RFC5545 compatible recurrence definition.")\n+ location = Attribute("Location of the event.")\n+ attendees = Attribute("List of attendees.")\n+ contact_name = Attribute("Contact name.")\n+ contact_email = Attribute("Contact email.")\n+ contact_phone = Attribute("Contact phone.")\n+ event_url = Attribute("Website of the event.")\n+ subjects = Attribute("Categories.")\n+ text = Attribute("Body text of the event.")\n \n \n class IRecurrenceSupport(Interface):\n- """Event type recurrence adatper.\n-\n- """\n+ """Event type recurrence adatper."""\n \n def occurrences(self, range_start, range_end):\n """Return a list of IOccurrence objects with custom attributes of the\n@@ -100,9 +96,7 @@ def occurrences(self, range_start, range_end):\n \n \n class IICalendar(Interface):\n- """Adapter, which is used to construct an icalendar object.\n-\n- """\n+ """Adapter, which is used to construct an icalendar object."""\n \n \n class IICalendarEventComponent(Interface):\n@@ -155,37 +149,38 @@ class / created / description / geo /\n resources / rdate / x-prop / iana-prop\n \n """\n- dtstart = Attribute(\'Start Date/Time\')\n- dtend = Attribute(\'End Date/Time\')\n- duration = Attribute(\'Duration\')\n- rrule = Attribute(\'Recurrence Rule\')\n- description = Attribute(\'Description\')\n- location = Attribute(\'Location\')\n- summary = Attribute(\'Summary\')\n- url = Attribute(\'Url\')\n- attendee = Attribute(\'Attendee\')\n- categories = Attribute(\'Categories\')\n- contact = Attribute(\'Contact\')\n-\n- exdate = Attribute(\'Exdate\')\n- rdate = Attribute(\'Rdate\')\n-\n- dtstamp = Attribute(\'Timestamp\')\n- uid = Attribute(\'Unique identifier\')\n- klass = Attribute(\'Class\') # class\n- created = Attribute(\'Created\')\n- geo = Attribute(\'Geo\')\n- last_mod = Attribute(\'Last Modified\') # last-mod\n- organizer = Attribute(\'Organizer\')\n- priority = Attribute(\'Priority\')\n- seq = Attribute(\'Seq\')\n- status = Attribute(\'Status\')\n- transp = Attribute(\'Transp\')\n- recurid = Attribute(\'Recurid\')\n- attach = Attribute(\'Attach\')\n- comment = Attribute(\'Comment\')\n- rstatus = Attribute(\'Rstatus\')\n- related = Attribute(\'Related\')\n- resources = Attribute(\'Resources\')\n- x_prop = Attribute(\'X Prop\') # x-prop\n- iana_prop = Attribute(\'Iana Prop\') # iana-prop\n+\n+ dtstart = Attribute("Start Date/Time")\n+ dtend = Attribute("End Date/Time")\n+ duration = Attribute("Duration")\n+ rrule = Attribute("Recurrence Rule")\n+ description = Attribute("Description")\n+ location = Attribute("Location")\n+ summary = Attribute("Summary")\n+ url = Attribute("Url")\n+ attendee = Attribute("Attendee")\n+ categories = Attribute("Categories")\n+ contact = Attribute("Contact")\n+\n+ exdate = Attribute("Exdate")\n+ rdate = Attribute("Rdate")\n+\n+ dtstamp = Attribute("Timestamp")\n+ uid = Attribute("Unique identifier")\n+ klass = Attribute("Class") # class\n+ created = Attribute("Created")\n+ geo = Attribute("Geo")\n+ last_mod = Attribute("Last Modified") # last-mod\n+ organizer = Attribute("Organizer")\n+ priority = Attribute("Priority")\n+ seq = Attribute("Seq")\n+ status = Attribute("Status")\n+ transp = Attribute("Transp")\n+ recurid = Attribute("Recurid")\n+ attach = Attribute("Attach")\n+ comment = Attribute("Comment")\n+ rstatus = Attribute("Rstatus")\n+ related = Attribute("Related")\n+ resources = Attribute("Resources")\n+ x_prop = Attribute("X Prop") # x-prop\n+ iana_prop = Attribute("Iana Prop") # iana-prop\ndiff --git a/plone/event/recurrence.py b/plone/event/recurrence.py\nindex 7dd27ea..e2b528b 100644\n--- a/plone/event/recurrence.py\n+++ b/plone/event/recurrence.py\n@@ -15,12 +15,12 @@\n \n \n def recurrence_sequence_ical(\n- start,\n- recrule=None,\n- from_=None,\n- until=None,\n- count=None,\n- duration=None,\n+ start,\n+ recrule=None,\n+ from_=None,\n+ until=None,\n+ count=None,\n+ duration=None,\n ):\n """Calculates a sequence of datetime objects from a recurrence rule\n following the RFC2445 specification, using python-dateutil recurrence\n@@ -67,7 +67,7 @@ def recurrence_sequence_ical(\n _from = tzdel(from_)\n _until = tzdel(until)\n if duration:\n- assert (isinstance(duration, datetime.timedelta))\n+ assert isinstance(duration, datetime.timedelta)\n else:\n duration = datetime.timedelta(0)\n \n@@ -87,16 +87,16 @@ def recurrence_sequence_ical(\n # time for UNTIL, RDATE and EXDATE.\n t0 = start.time() # set initial time information.\n # First, replace all times in the recurring rule with starttime\n- t0str = f\'T{t0.hour:02d}{t0.minute:02d}{t0.second:02d}\'\n+ t0str = f"T{t0.hour:02d}{t0.minute:02d}{t0.second:02d}"\n # Replace any times set to 000000 with start time, not all\n # rrules are set by a specific broken widget. Don\'t waste time\n # subbing if the start time is already 000000.\n- if t0str != \'T000000\':\n- recrule = re.sub(r\'T000000\', t0str, recrule)\n+ if t0str != "T000000":\n+ recrule = re.sub(r"T000000", t0str, recrule)\n # Then, replace incorrect until times with the end of the day\n recrule = re.sub(\n- r\'(UNTIL[^T]*[0-9]{8})T(000000)\',\n- r\'\\1T235959\',\n+ r"(UNTIL[^T]*[0-9]{8})T(000000)",\n+ r"\\1T235959",\n recrule,\n )\n \n@@ -140,13 +140,13 @@ def recurrence_sequence_ical(\n \n \n def recurrence_sequence_timedelta(\n- start,\n- delta=None,\n- until=None,\n- count=None,\n- dst=DSTAUTO,\n+ start,\n+ delta=None,\n+ until=None,\n+ count=None,\n+ dst=DSTAUTO,\n ):\n- """ Calculates a sequence of datetime objects from a timedelta integer,\n+ """Calculates a sequence of datetime objects from a timedelta integer,\n which defines the minutes between each occurence.\n \n :param start: datetime or DateTime instance of the date from which the\n@@ -204,7 +204,7 @@ def recurrence_sequence_timedelta(\n \n \n def recurrence_int_sequence(sequence):\n- """ Generates a sequence of integer representations from a sequence of\n+ """Generates a sequence of integer representations from a sequence of\n dateime instances.\n \n :param sequence: An iterable sequence of datetime instances.\ndiff --git a/plone/event/tests/test_adapters.py b/plone/event/tests/test_adapters.py\nindex ad51528..df92e79 100644\n--- a/plone/event/tests/test_adapters.py\n+++ b/plone/event/tests/test_adapters.py\n@@ -15,15 +15,17 @@ class MockObject:\n class TestAdapters(unittest.TestCase):\n def setUp(self):\n import zope.component\n- context = xmlconfig.file(\'meta.zcml\', zope.component)\n- xmlconfig.file(\'configure.zcml\', zope.component, context=context)\n+\n+ context = xmlconfig.file("meta.zcml", zope.component)\n+ xmlconfig.file("configure.zcml", zope.component, context=context)\n \n import plone.event\n- xmlconfig.file(\'configure.zcml\', plone.event, context=context)\n+\n+ xmlconfig.file("configure.zcml", plone.event, context=context)\n \n def test_event_accessor(self):\n obj = MockObject()\n- tz = pytz.timezone(\'Europe/Vienna\')\n+ tz = pytz.timezone("Europe/Vienna")\n obj.start = datetime(2012, 12, 12, 10, 0, tzinfo=tz)\n obj.end = datetime(2012, 12, 12, 12, 0, tzinfo=tz)\n zope.interface.alsoProvides(obj, IEvent)\n@@ -48,9 +50,9 @@ def test_event_accessor(self):\n acc.something = True\n self.assertTrue(acc.something == obj.something is True)\n del acc.something\n- self.assertTrue(hasattr(acc, \'something\') is False)\n- self.assertTrue(hasattr(obj, \'something\') is False)\n+ self.assertTrue(hasattr(acc, "something") is False)\n+ self.assertTrue(hasattr(obj, "something") is False)\n \n del acc.start\n- self.assertTrue(hasattr(acc, \'start\') is False)\n- self.assertTrue(hasattr(obj, \'start\') is False)\n+ self.assertTrue(hasattr(acc, "start") is False)\n+ self.assertTrue(hasattr(obj, "start") is False)\ndiff --git a/plone/event/tests/test_doctest.py b/plone/event/tests/test_doctest.py\nindex 001e083..6e7b759 100644\n--- a/plone/event/tests/test_doctest.py\n+++ b/plone/event/tests/test_doctest.py\n@@ -7,11 +7,13 @@\n \n OPTIONFLAGS = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS\n DOCFILES = [\n- \'recurrence.rst\',\n- \'recurrence_dateutil.rst\',\n- \'utils.rst\',\n+ "recurrence.rst",\n+ "recurrence_dateutil.rst",\n+ "utils.rst",\n+]\n+DOCMODS = [\n+ "plone.event.utils",\n ]\n-DOCMODS = [\'plone.event.utils\', ]\n \n \n def test_suite():\n@@ -19,24 +21,19 @@ def test_suite():\n suite.addTests(\n [\n doctest.DocFileSuite(\n- os.path.join(os.path.dirname(__file__), \'..\', docfile),\n+ os.path.join(os.path.dirname(__file__), "..", docfile),\n module_relative=False,\n optionflags=OPTIONFLAGS,\n- tearDown=tearDown\n+ tearDown=tearDown,\n )\n for docfile in DOCFILES\n ]\n )\n suite.addTests(\n- [\n- doctest.DocTestSuite(\n- docmod, optionflags=OPTIONFLAGS\n- )\n- for docmod in DOCMODS\n- ]\n+ [doctest.DocTestSuite(docmod, optionflags=OPTIONFLAGS) for docmod in DOCMODS]\n )\n return suite\n \n \n-if __name__ == \'__main__\':\n- unittest.main(defaultTest=\'test_suite\')\n+if __name__ == "__main__":\n+ unittest.main(defaultTest="test_suite")\ndiff --git a/plone/event/tests/test_recurrence_int_sequence.py b/plone/event/tests/test_recurrence_int_sequence.py\nindex b858a9c..9812fb4 100644\n--- a/plone/event/tests/test_recurrence_int_sequence.py\n+++ b/plone/event/tests/test_recurrence_int_sequence.py\n@@ -4,10 +4,11 @@\n \n \n class TestRecurrenceIntSequence(unittest.TestCase):\n- @mock.patch(\'plone.event.recurrence.dt2int\')\n+ @mock.patch("plone.event.recurrence.dt2int")\n def test_recrule_str_(self, dt2int):\n from plone.event.recurrence import recurrence_int_sequence\n+\n sequence = [1, 2, 3]\n- dt2int.return_value = \'a\'\n+ dt2int.return_value = "a"\n res = [a for a in recurrence_int_sequence(sequence)]\n- self.assertEqual(res, [\'a\', \'a\', \'a\'])\n+ self.assertEqual(res, ["a", "a", "a"])\ndiff --git a/plone/event/tests/test_recurrence_sequence_ical.py b/plone/event/tests/test_recurrence_sequence_ical.py\nindex ae08c8f..25f1887 100644\n--- a/plone/event/tests/test_recurrence_sequence_ical.py\n+++ b/plone/event/tests/test_recurrence_sequence_ical.py\n@@ -5,6 +5,7 @@ class TestRecurrenceSequenceIcal(unittest.TestCase):\n def test_start(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n seq = recurrence_sequence_ical(start)\n results = [res for res in seq]\n@@ -13,18 +14,20 @@ def test_start(self):\n def test_recrule_str(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=10;COUNT=5"\n seq = recurrence_sequence_ical(start, recrule=recrule)\n results = [res for res in seq]\n self.assertEqual(len(results), 5)\n \n def test_recrule_str_rdate(self):\n """Test, if an RDATE date has the correct time set.\n- See: "BUGFIX WRONG RDATE TIME" in recurrence.py\n+ See: "BUGFIX WRONG RDATE TIME" in recurrence.py\n """\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23, 10, 10)\n recrule = """FREQ=DAILY;INTERVAL=1;COUNT=3\n RDATE:20111129T000000"""\n@@ -34,22 +37,22 @@ def test_recrule_str_rdate(self):\n self.assertEqual(results[0].time(), results[-1].time())\n \n def test_recrule_str_exdate(self):\n- """Test, if an EXDATE date are not in the resulting recurrence set.\n- """\n+ """Test, if an EXDATE date are not in the resulting recurrence set."""\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n \n import pytz\n- at = pytz.timezone(\'Europe/Vienna\')\n+\n+ at = pytz.timezone("Europe/Vienna")\n start = at.localize(datetime(2013, 6, 29, 10, 10))\n- recrule = \'RRULE:FREQ=DAILY;COUNT=4\\r\\nEXDATE:20130630T000000,20130701T000000\\r\\nRDATE:20130706T000000,20130809T000000\' # noqa\n+ recrule = "RRULE:FREQ=DAILY;COUNT=4\\r\\nEXDATE:20130630T000000,20130701T000000\\r\\nRDATE:20130706T000000,20130809T000000" # noqa\n seq = recurrence_sequence_ical(start, recrule=recrule)\n res = [res for res in seq]\n res_test = [\n at.localize(datetime(2013, 6, 29, 10, 10)),\n at.localize(datetime(2013, 7, 2, 10, 10)),\n at.localize(datetime(2013, 7, 6, 10, 10)),\n- at.localize(datetime(2013, 8, 9, 10, 10))\n+ at.localize(datetime(2013, 8, 9, 10, 10)),\n ]\n self.assertEqual(len(res), 4)\n self.assertEqual(res, res_test)\n@@ -62,16 +65,17 @@ def test_recrule_str_until(self):\n from plone.event.recurrence import recurrence_sequence_ical\n \n import pytz\n- at = pytz.timezone(\'Europe/Vienna\')\n+\n+ at = pytz.timezone("Europe/Vienna")\n start = at.localize(datetime(2013, 6, 29, 10, 10))\n- recrule = \'RRULE:FREQ=DAILY;UNTIL=20130702T000000\'\n+ recrule = "RRULE:FREQ=DAILY;UNTIL=20130702T000000"\n seq = recurrence_sequence_ical(start, recrule=recrule)\n res = [res for res in seq]\n res_test = [\n at.localize(datetime(2013, 6, 29, 10, 10)),\n at.localize(datetime(2013, 6, 30, 10, 10)),\n at.localize(datetime(2013, 7, 1, 10, 10)),\n- at.localize(datetime(2013, 7, 2, 10, 10))\n+ at.localize(datetime(2013, 7, 2, 10, 10)),\n ]\n self.assertEqual(len(res), 4)\n self.assertEqual(res, res_test)\n@@ -79,6 +83,7 @@ def test_recrule_str_until(self):\n def test_recrule_from_until(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n recrule = None\n from_ = datetime(2011, 11, 1)\n@@ -95,8 +100,9 @@ def test_recrule_from_until(self):\n def test_recrule_str_more_than_MAXCOUNT(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=1001\'\n+ recrule = "FREQ=DAILY;INTERVAL=10;COUNT=1001"\n seq = recurrence_sequence_ical(start, recrule=recrule)\n results = [res for res in seq]\n self.assertEqual(len(results), 1000)\n@@ -104,8 +110,9 @@ def test_recrule_str_more_than_MAXCOUNT(self):\n def test_recrule_str_more_than_count(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=10\'\n+ recrule = "FREQ=DAILY;INTERVAL=10;COUNT=10"\n count = 5\n seq = recurrence_sequence_ical(start, recrule=recrule, count=count)\n results = [res for res in seq]\n@@ -114,8 +121,9 @@ def test_recrule_str_more_than_count(self):\n def test_recrule_from(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=1;COUNT=5"\n from_ = datetime(2011, 11, 25)\n until = datetime(2011, 11, 27)\n seq = recurrence_sequence_ical(\n@@ -130,8 +138,9 @@ def test_recrule_from(self):\n def test_recrule_until(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 24)\n- recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=1;COUNT=5"\n from_ = datetime(2011, 11, 23)\n until = datetime(2011, 11, 27)\n seq = recurrence_sequence_ical(\n@@ -144,13 +153,13 @@ def test_recrule_until(self):\n self.assertEqual(len(results), 4)\n \n def test_recrule_from_until_with_duration(self):\n- """Should include events ranging into the queried timerange.\n- """\n+ """Should include events ranging into the queried timerange."""\n from datetime import datetime\n from datetime import timedelta\n from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=1;COUNT=5"\n from_ = datetime(2011, 11, 26)\n until = datetime(2011, 11, 27)\n seq = recurrence_sequence_ical(\n@@ -168,6 +177,6 @@ def test_recrule_until_with_timezone(self):\n from plone.event.recurrence import recurrence_sequence_ical\n \n start = datetime(2011, 11, 24)\n- recrule = \'RRULE:FREQ=DAILY;UNTIL=20111130T000000Z\'\n+ recrule = "RRULE:FREQ=DAILY;UNTIL=20111130T000000Z"\n seq = list(recurrence_sequence_ical(start, recrule=recrule))\n self.assertEqual(len(seq), 7)\ndiff --git a/plone/event/tests/test_recurrence_sequence_timedelta.py b/plone/event/tests/test_recurrence_sequence_timedelta.py\nindex fdb21af..9ca7210 100644\n--- a/plone/event/tests/test_recurrence_sequence_timedelta.py\n+++ b/plone/event/tests/test_recurrence_sequence_timedelta.py\n@@ -5,6 +5,7 @@ class TestRecurrenceSequenceTimedelta(unittest.TestCase):\n def test_delta_None(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n until = datetime(2011, 11, 24)\n td = recurrence_sequence_timedelta(start, until=until)\n@@ -14,6 +15,7 @@ def test_delta_None(self):\n def test_delta_zero(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 0\n until = datetime(2011, 11, 24)\n@@ -24,6 +26,7 @@ def test_delta_zero(self):\n def test_until_None(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 1\n td = recurrence_sequence_timedelta(start, delta=delta)\n@@ -33,6 +36,7 @@ def test_until_None(self):\n def test_delta_an_hour_until_next_day(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 60\n until = datetime(2011, 11, 24)\n@@ -43,6 +47,7 @@ def test_delta_an_hour_until_next_day(self):\n def test_recur_more_than_MAXCOUNT(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 1\n until = datetime(2012, 11, 23)\n@@ -53,6 +58,7 @@ def test_recur_more_than_MAXCOUNT(self):\n def test_recur_more_than_count(self):\n from datetime import datetime\n from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 1\n until = datetime(2011, 11, 24)\ndiff --git a/plone/event/tests/test_utils.py b/plone/event/tests/test_utils.py\nindex 0576920..ca82a01 100644\n--- a/plone/event/tests/test_utils.py\n+++ b/plone/event/tests/test_utils.py\n@@ -4,41 +4,47 @@\n \n \n class TestUtils(unittest.TestCase):\n- @mock.patch(\'plone.event.utils.pytz\')\n- @mock.patch(\'plone.event.utils.os\')\n+ @mock.patch("plone.event.utils.pytz")\n+ @mock.patch("plone.event.utils.os")\n def test_default_timezone(self, os, pytz):\n from plone.event.utils import default_timezone\n- os.environ.keys.return_value = [\'TZ\']\n+\n+ os.environ.keys.return_value = ["TZ"]\n os.environ = mock.MagicMock()\n- pytz.timezone().zone = \'zone\'\n- self.assertEqual(default_timezone(), \'zone\')\n+ pytz.timezone().zone = "zone"\n+ self.assertEqual(default_timezone(), "zone")\n \n def test_utcoffset_normalize(self):\n from plone.event.utils import utcoffset_normalize\n+\n date = mock.Mock()\n date.replace = mock.Mock(side_effect=KeyError)\n self.assertEqual(utcoffset_normalize(date), date)\n \n- @mock.patch(\'plone.event.utils.guesstz\')\n- @mock.patch(\'plone.event.utils.utctz\')\n+ @mock.patch("plone.event.utils.guesstz")\n+ @mock.patch("plone.event.utils.utctz")\n def test_pydt__missing_zone_is_None(self, utctz, guesstz):\n from plone.event.utils import pydt\n+\n dt = mock.Mock()\n dt.toZone.return_value = dt\n dt.parts.return_value = (2011, 11, 24, 11, 39, 00)\n guesstz.return_value = None\n import pytz\n- utctz.return_value = pytz.timezone(\'UTC\')\n+\n+ utctz.return_value = pytz.timezone("UTC")\n pydt(dt)\n self.assertTrue(utctz.called)\n \n- @mock.patch(\'plone.event.utils.guesstz\')\n- @mock.patch(\'plone.event.utils.utctz\')\n+ @mock.patch("plone.event.utils.guesstz")\n+ @mock.patch("plone.event.utils.utctz")\n def test_pydt__missing_zone_is_not_None(self, utctz, guesstz):\n from plone.event.utils import pydt\n+\n dt = mock.Mock()\n import pytz\n- utctz.return_value = pytz.timezone(\'UTC\')\n+\n+ utctz.return_value = pytz.timezone("UTC")\n missing_zone = utctz()\n dt.toZone.return_value = dt\n dt.parts.return_value = (2011, 11, 24, 11, 39, 00)\n@@ -48,16 +54,19 @@ def test_pydt__missing_zone_is_not_None(self, utctz, guesstz):\n \n def test_pydt__wrong_type(self):\n from plone.event.utils import pydt\n- self.assertEqual(pydt(\'wrongtype\'), None)\n+\n+ self.assertEqual(pydt("wrongtype"), None)\n \n def test_dt2int_dt_is_None(self):\n from plone.event.utils import dt2int\n+\n self.assertFalse(dt2int(None))\n \n- @mock.patch(\'plone.event.utils.MAX32\', 0)\n- @mock.patch(\'plone.event.utils.utc\')\n+ @mock.patch("plone.event.utils.MAX32", 0)\n+ @mock.patch("plone.event.utils.utc")\n def test_dt2int_less_MAX32(self, utc):\n from plone.event.utils import dt2int\n+\n dt = mock.Mock()\n dd = mock.Mock()\n utc.return_value = dd\n@@ -68,10 +77,11 @@ def test_dt2int_less_MAX32(self, utc):\n dd.minute = 16\n self.assertRaises(OverflowError, lambda: dt2int(dt))\n \n- @mock.patch(\'plone.event.utils.MAX32\', 1077778937)\n- @mock.patch(\'plone.event.utils.utc\')\n+ @mock.patch("plone.event.utils.MAX32", 1077778937)\n+ @mock.patch("plone.event.utils.utc")\n def test_dt2int_more_MAX32(self, utc):\n from plone.event.utils import dt2int\n+\n dt = mock.Mock()\n dd = mock.Mock()\n utc.return_value = dd\ndiff --git a/setup.py b/setup.py\nindex 93f57df..b6ccb92 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -2,15 +2,13 @@\n from setuptools import setup\n \n \n-version = \'1.4.3.dev0\'\n+version = "1.4.3.dev0"\n \n setup(\n- name=\'plone.event\',\n+ name="plone.event",\n version=version,\n description="Event and calendaring related tools not bound to Plone",\n- long_description=(\n- open("README.rst").read() + "\\n" + open("CHANGES.rst").read()\n- ),\n+ long_description=(open("README.rst").read() + "\\n" + open("CHANGES.rst").read()),\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n "Framework :: Plone",\n@@ -28,26 +26,28 @@\n "Programming Language :: Python :: 3.10",\n "Programming Language :: Python :: 3.11",\n ],\n- keywords=\'Plone calendar calendaring event recurring\',\n- author=\'Plone Foundation\',\n- author_email=\'plone-developers@lists.sourceforge.net\',\n- url=\'https://github.com/plone/plone.event\',\n- license=\'GPL\',\n+ keywords="Plone calendar calendaring event recurring",\n+ author="Plone Foundation",\n+ author_email="plone-developers@lists.sourceforge.net",\n+ url="https://github.com/plone/plone.event",\n+ license="GPL",\n packages=find_packages(),\n- namespace_packages=[\'plone\'],\n+ namespace_packages=["plone"],\n include_package_data=True,\n zip_safe=False,\n- python_requires=\'>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*\',\n+ python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*",\n install_requires=[\n- \'setuptools\',\n- \'python-dateutil\', # >4.0.2\n- \'pytz\',\n- \'zope.component\',\n- \'zope.interface\',\n+ "setuptools",\n+ "python-dateutil", # >4.0.2\n+ "pytz",\n+ "zope.component",\n+ "zope.interface",\n ],\n- extras_require={\'test\': [\n- \'DateTime\',\n- \'mock\',\n- \'zope.configuration\',\n- ], },\n+ extras_require={\n+ "test": [\n+ "DateTime",\n+ "mock",\n+ "zope.configuration",\n+ ],\n+ },\n )\n' +b'diff --git a/setup.py b/setup.py\nindex dfeee90..c686573 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -13,7 +13,7 @@\n "Development Status :: 5 - Production/Stable",\n "Environment :: Web Environment",\n "Framework :: Plone",\n- "Framework :: Plone :: 5.2",\n+ "Framework :: Plone :: 6.0",\n "Framework :: Plone :: Core",\n "Framework :: Zope2",\n "Framework :: Zope :: 4",\n@@ -23,10 +23,10 @@\n "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",\n "Operating System :: OS Independent",\n "Programming Language :: Python",\n- "Programming Language :: Python :: 2.7",\n- "Programming Language :: Python :: 3.6",\n- "Programming Language :: Python :: 3.7",\n "Programming Language :: Python :: 3.8",\n+ "Programming Language :: Python :: 3.9",\n+ "Programming Language :: Python :: 3.10",\n+ "Programming Language :: Python :: 3.11",\n ],\n keywords="folder btree order",\n author="Plone Foundation",\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:13:37+02:00 +Date: 2023-04-15T14:34:54+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/9df45c0f2f4fbb1ad5ed753a7e30c7106f5fc655 +Commit: https://github.com/plone/plone.folder/commit/4ab86311378d1697bd7338feaa840d97db973090 -chore: zpretty +feat: pyroma Files changed: -M plone/event/configure.zcml +M setup.py -b'diff --git a/plone/event/configure.zcml b/plone/event/configure.zcml\nindex f9699f7..1e6e17c 100644\n--- a/plone/event/configure.zcml\n+++ b/plone/event/configure.zcml\n@@ -1,7 +1,8 @@\n \n+ i18n_domain="plone.event"\n+ >\n \n- \n+ \n \n \n' +b'diff --git a/setup.py b/setup.py\nindex c686573..cd7a893 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -39,6 +39,7 @@\n include_package_data=True,\n platforms="Any",\n zip_safe=False,\n+ python_requires=">=3.8",\n install_requires=[\n "plone.memoize",\n "Products.BTreeFolder2",\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:21:23+02:00 +Date: 2023-04-15T14:35:18+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/f30946baf0d147d70b4285f7ce6a5db1fc420118 +Commit: https://github.com/plone/plone.folder/commit/0757ce34e6ad31623a9393bfc09f2a2c99b63c25 feat: codespell Files changed: M CHANGES.rst -M plone/event/interfaces.py -M plone/event/recurrence.py -M plone/event/recurrence.rst -M plone/event/recurrence_dateutil.rst -M plone/event/utils.py -M plone/event/utils.rst -b'diff --git a/CHANGES.rst b/CHANGES.rst\nindex b5948f3..1b72551 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -108,10 +108,10 @@ Fixes:\n ----------------\n \n - Fix tests, where they broke with unicode recurrence strings and unicode date\n- formating strings.\n+ formatting strings.\n [thet]\n \n-- Make rrule munging hack only apply to RDATEs, EXDATEs and UNTILs which have\n+- Make rrule munging hack only apply to `RDATE`, `EXDATE` and `UNTIL` which have\n null times, otherwise the DateRecurrenceIndex is broken for those who are\n generating RRULES using a non-broken widget. This will still result in broken\n RRULEs for some edge cases (where an RDATE is explicitly set for midnight on\ndiff --git a/plone/event/interfaces.py b/plone/event/interfaces.py\nindex 5f3af6e..572b7e1 100644\n--- a/plone/event/interfaces.py\n+++ b/plone/event/interfaces.py\n@@ -55,7 +55,7 @@ class IEventAccessor(Interface):\n \n # reference\n url = Attribute(\n- "Cannonical, unique url of the event. External events "\n+ "Canonical, unique url of the event. External events "\n "are referenced by the origin url unless explicitly set."\n )\n \n@@ -80,7 +80,7 @@ class IEventAccessor(Interface):\n \n \n class IRecurrenceSupport(Interface):\n- """Event type recurrence adatper."""\n+ """Event type recurrence adapter."""\n \n def occurrences(self, range_start, range_end):\n """Return a list of IOccurrence objects with custom attributes of the\ndiff --git a/plone/event/recurrence.py b/plone/event/recurrence.py\nindex e2b528b..2900837 100644\n--- a/plone/event/recurrence.py\n+++ b/plone/event/recurrence.py\n@@ -44,13 +44,13 @@ def recurrence_sequence_ical(\n MAXDATE limit the recurrence calculation.\n :type until: datetime.datetime\n \n- :param count: Optional integer which defines the number of occurences.\n+ :param count: Optional integer which defines the number of occurrences.\n If not given, until or MAXDATE limits the recurrence\n calculation.\n :type count: integer\n \n :param duration: Optional timedelta instance, which is used to calculate\n- if a occurence datetime plus duration is within the\n+ if a occurrence datetime plus duration is within the\n queried timerange.\n :type duration: datetime.timedelta\n \n@@ -147,14 +147,14 @@ def recurrence_sequence_timedelta(\n dst=DSTAUTO,\n ):\n """Calculates a sequence of datetime objects from a timedelta integer,\n- which defines the minutes between each occurence.\n+ which defines the minutes between each occurrence.\n \n :param start: datetime or DateTime instance of the date from which the\n recurrence sequence is calculated.\n :type start: datetime\n \n :param delta: Integer which defines the minutes\n- between each date occurence.\n+ between each date occurrence.\n :type delta: integer\n \n :param until: datetime or DateTime instance of the date, until the\n@@ -162,7 +162,7 @@ def recurrence_sequence_timedelta(\n count or MAXDATE limit the recurrence calculation.\n :type until: datetime\n \n- :param count: Integer which defines the number of occurences. If not given,\n+ :param count: Integer which defines the number of occurrences. If not given,\n until or MAXDATE limits the recurrence calculation.\n :param count: integer\n \ndiff --git a/plone/event/recurrence.rst b/plone/event/recurrence.rst\nindex 67ad89e..e85db9d 100644\n--- a/plone/event/recurrence.rst\n+++ b/plone/event/recurrence.rst\n@@ -65,7 +65,7 @@ Timezone aware Daylight Saving Time dates crossing\n datetime.datetime(2010, 11, 1, 9, 0, tzinfo=)]\n \n \n-Note, that recurrence_sequence_ical calculates occurences timezone naively and\n+Note, that recurrence_sequence_ical calculates occurrences timezone naively and\n applies timezones afterwards. This leads into a problem in corner cases:\n >>> list(recurrence_sequence_ical(\n ... start=at.localize(datetime(2010,10,30,23,0,0,0)),\n@@ -109,10 +109,10 @@ Multiple Ruleset\n datetime.datetime(2010, 1, 20, 0, 0, tzinfo=)]\n \n \n-Limiting number of occurences\n+Limiting number of occurrences\n -----------------------------\n \n-Until (date until recurrence happens) and count (Number of occurences) can also\n+Until (date until recurrence happens) and count (Number of occurrences) can also\n be given in recurrence_sequence_ical, instead of defining it in the rrule.\n But defining it in a rrule gives more flexibility since you can set it for each\n rrule individually.\n@@ -301,10 +301,10 @@ Here the correct behaviour on day level with DSTKEEP.\n datetime.datetime(2008, 3, 30, 19, 0, tzinfo=),\n datetime.datetime(2008, 3, 30, 20, 0, tzinfo=)]\n \n-Usally we want an clever behaviour, dependend on delta. This is implemented\n+Usually we want a clever behaviour, dependent on delta. This is implemented\n with DSTAUTO, which is the default behaviour.\n \n-Here the correct behaviour on day level or above: DSTADJUST is choosen.\n+Here the correct behaviour on day level or above: DSTADJUST is chosen.\n \n >>> start = datetime(2008, 3, 29, 11, 0, 0, 0, pytz.timezone(\'CET\'))\n >>> until = datetime(2008, 3, 31, 11, 0, 0, 0, pytz.timezone(\'CET\'))\n@@ -319,7 +319,7 @@ Here the correct behaviour on day level or above: DSTADJUST is choosen.\n datetime.datetime(2008, 3, 31, 11, 0, tzinfo=)]\n \n \n-The correct behaviour on below day level: DSTKEEP is choosen.\n+The correct behaviour on below day level: DSTKEEP is chosen.\n \n >>> start = datetime(2008, 3, 29, 21, 0, 0, 0, pytz.timezone(\'CET\'))\n >>> until = datetime(2008, 3, 30, 21, 0, 0, 0, pytz.timezone(\'CET\')) - timedelta(microseconds=1)\n@@ -398,7 +398,7 @@ timezones works.\n >>> seqDT[0] == seqdt[0]\n True\n \n-Does integer represenation work?\n+Does integer representation work?\n >>> seqDT = list(recurrence_int_sequence(recurrence_sequence_timedelta(DT, 0, None)))\n >>> seqdt = list(recurrence_int_sequence(recurrence_sequence_timedelta(dt, 0, None)))\n \ndiff --git a/plone/event/recurrence_dateutil.rst b/plone/event/recurrence_dateutil.rst\nindex 685f700..cf2dc85 100644\n--- a/plone/event/recurrence_dateutil.rst\n+++ b/plone/event/recurrence_dateutil.rst\n@@ -49,12 +49,12 @@ This issue is corrected by plone.event.util.utcoffset_normalize:\n \n \n It\'s safer to let rrule calculate timezone naive dates and localizing them\n-afterwards than letting rrule substracting (EXDATE) timezone correct dates from\n+afterwards than letting rrule subtracting (EXDATE) timezone correct dates from\n a possibly timezone incorrect recurrence sequence. This issue will be gone, if\n rrule does TZ normalizing itself before applying EXDATE to the recurrence\n sequence.\n \n-See here... This is our recurrence rule. We want to substract from the sequence\n+See here... This is our recurrence rule. We want to subtract from the sequence\n the date 2010-10-31, 23:30 in UTC, which is 2010-11-01, 0:30 in Austria, UTC+1\n \n ::\n@@ -63,7 +63,7 @@ the date 2010-10-31, 23:30 in UTC, which is 2010-11-01, 0:30 in Austria, UTC+1\n ... EXDATE:20101031T233000Z"""\n \n If we let the sequence start from 1st November, the 1st November is correctly\n-substracted, since the sequence has all correct timezones.\n+subtracted, since the sequence has all correct timezones.\n \n ::\n \n@@ -73,7 +73,7 @@ substracted, since the sequence has all correct timezones.\n datetime.datetime(2010, 11, 3, 0, 30, tzinfo=)]\n \n But if we start from 30th October, where UTC+2 offset is still active, the\n-sequence has incorrect timezones and substracting does not work as expected\n+sequence has incorrect timezones and subtracting does not work as expected\n anymore.\n \n ::\ndiff --git a/plone/event/utils.py b/plone/event/utils.py\nindex 389a733..e5acbb6 100644\n--- a/plone/event/utils.py\n+++ b/plone/event/utils.py\n@@ -272,7 +272,7 @@ def utcoffset_normalize(date, delta=None, dstmode=DSTAUTO):\n the same relative to UTC. So, 8:00 GMT+1 before will result\n in 7:00 GMT+2 afterwards. This behavior might be what\n machines expect, when recurrence rules are defined.\n- Mode DSTAUTO: If the relative delta between two occurences of\n+ Mode DSTAUTO: If the relative delta between two occurrences of\n a reucurrence sequence is less than a day, DSTKEEP will be\n used - otherwise DSTADJUST. This behavior is the default.\n """\n@@ -508,7 +508,7 @@ def pydt(dt, missing_zone=None, exact=False):\n def guesstz(DT):\n """\'Guess\' pytz from a zope DateTime.\n \n- !!! theres no real good method to guess the timezone.\n+ !!! there is no real good method to guess the timezone.\n DateTime was build somewhere in 1998 long before python had a working\n datetime implementation available and still stucks with this incomplete\n implementation.\n@@ -521,12 +521,12 @@ def guesstz(DT):\n \'Europe/Vienna\'\n \n GMT timezones which are popular with DateTime cannot be guessed,\n- unfortunatly\n+ unfortunately\n >>> guesstz(DateTime(\'2010-01-01 GMT+1\'))\n """\n tzname = DT.timezone()\n \n- # Please note, the GMT offset based timezone informations in DateTime are\n+ # Please note, the GMT offset based timezone information in DateTime are\n # not compatible with Etc/GMT based from pytz. They have different offsets.\n try:\n tz = pytz.timezone(tzname)\ndiff --git a/plone/event/utils.rst b/plone/event/utils.rst\nindex 5278036..cdac790 100644\n--- a/plone/event/utils.rst\n+++ b/plone/event/utils.rst\n@@ -44,7 +44,7 @@ time in a way, that it\'s value will be the same as before normalizing.\n >>> utcoffset_normalize(date2, dstmode=DSTADJUST)\n datetime.datetime(2010, 11, 10, 0, 0, tzinfo=)\n \n-With DSTKEEP, normalizing will also keep the time as originaly set by UTC\n+With DSTKEEP, normalizing will also keep the time as originally set by UTC\n offset - time\'s value will change.\n >>> utcoffset_normalize(date2, dstmode=DSTKEEP)\n datetime.datetime(2010, 11, 9, 23, 0, tzinfo=)\n' +b'diff --git a/CHANGES.rst b/CHANGES.rst\nindex 2dfa069..f6c08ff 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -293,7 +293,7 @@ Fixes:\n dict-like API.\n [optilude]\n \n-- Fix issue with removing non-orderable content for partial ordering suppport.\n+- Fix issue with removing non-orderable content for partial ordering support.\n [witsch]\n \n - Fix ``getObjectPosition`` to return a value representing "no position" for\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:21:47+02:00 +Date: 2023-04-15T14:36:29+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/31ea59015a0862f171f5167b71b2a4f6a198ae04 +Commit: https://github.com/plone/plone.folder/commit/982386460b2fe90bbe67038afde6aa5eedf60831 -feat: flake8 +feat: drop six usage Files changed: -M plone/event/utils.py +M setup.py +M src/plone/folder/default.py +M src/plone/folder/partial.py +M src/plone/folder/tests/test_ordersupport.py -b'diff --git a/plone/event/utils.py b/plone/event/utils.py\nindex e5acbb6..16029d4 100644\n--- a/plone/event/utils.py\n+++ b/plone/event/utils.py\n@@ -149,7 +149,7 @@ def is_same_time(start, end, exact=False):\n :returns: True, if start and end have the same time, otherwise False.\n :rtype: Boolean.\n \n- >>> from plone.event.utils import is_same_time, pydt\n+ >>> from plone.event.utils import is_same_time\n >>> from datetime import datetime, timedelta\n \n >>> is_same_time(datetime.now(), datetime.now()+timedelta(hours=1))\n' +b'diff --git a/setup.py b/setup.py\nindex cd7a893..7eef4f5 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -46,7 +46,6 @@\n "Products.CMFCore",\n "Products.ZCatalog",\n "setuptools",\n- "six",\n "zope.annotation",\n "zope.component",\n "zope.container",\ndiff --git a/src/plone/folder/default.py b/src/plone/folder/default.py\nindex 57c4d90..de3f086 100644\n--- a/src/plone/folder/default.py\n+++ b/src/plone/folder/default.py\n@@ -7,8 +7,6 @@\n from zope.container.contained import notifyContainerModified\n from zope.interface import implementer\n \n-import six\n-\n \n @implementer(IExplicitOrdering)\n @adapter(IOrderableFolder)\ndiff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex 0ae54c2..a78394d 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -6,8 +6,6 @@\n from zope.container.contained import notifyContainerModified\n from zope.interface import implementer\n \n-import six\n-\n \n ORDER_ATTR = "_objectordering"\n \ndiff --git a/src/plone/folder/tests/test_ordersupport.py b/src/plone/folder/tests/test_ordersupport.py\nindex 05f7ff5..c05001d 100644\n--- a/src/plone/folder/tests/test_ordersupport.py\n+++ b/src/plone/folder/tests/test_ordersupport.py\n@@ -4,7 +4,6 @@\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n from plone.folder.tests.utils import DummyObject\n \n-import six\n import unittest\n \n \n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:22:43+02:00 +Date: 2023-04-15T14:37:36+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/9d861f26ab412238e1fee6b61f421ca1130218d4 +Commit: https://github.com/plone/plone.folder/commit/808d296c9bd724d20790c613c2d4a736d1a4a0f9 -chore: update trove classifiers +feat: flake8 Files changed: -M setup.py +M src/plone/folder/partial.py +M src/plone/folder/tests/test_webdav.py -b'diff --git a/setup.py b/setup.py\nindex b6ccb92..6f5cdac 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -12,15 +12,10 @@\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n "Framework :: Plone",\n- "Framework :: Plone :: 5.1",\n- "Framework :: Plone :: 5.2",\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 :: 2.7",\n- "Programming Language :: Python :: 3.6",\n- "Programming Language :: Python :: 3.7",\n "Programming Language :: Python :: 3.8",\n "Programming Language :: Python :: 3.9",\n "Programming Language :: Python :: 3.10",\n@@ -35,7 +30,7 @@\n namespace_packages=["plone"],\n include_package_data=True,\n zip_safe=False,\n- python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*",\n+ python_requires=">=3.8",\n install_requires=[\n "setuptools",\n "python-dateutil", # >4.0.2\n' +b'diff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex a78394d..d1ab5d0 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -38,7 +38,7 @@ def order(self, value):\n \n def notifyAdded(self, id):\n """see interfaces.py"""\n- assert not id in self.order\n+ assert id not in self.order\n context = aq_base(self.context)\n obj = context._getOb(id)\n if IOrderable.providedBy(obj):\ndiff --git a/src/plone/folder/tests/test_webdav.py b/src/plone/folder/tests/test_webdav.py\nindex 338b628..d4a9637 100644\n--- a/src/plone/folder/tests/test_webdav.py\n+++ b/src/plone/folder/tests/test_webdav.py\n@@ -4,7 +4,6 @@\n from plone.folder.tests.utils import DummyObject\n from zope.publisher.browser import TestRequest\n \n-import pkg_resources\n import unittest\n \n \n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:23:29+02:00 +Date: 2023-04-15T14:45:57+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/73866e439fe2b14be18d5a7c6cfbe5dfa388925e +Commit: https://github.com/plone/plone.folder/commit/7807a50a8a1cb005a84de76fe1f7596ce1d1c165 -feat: declare dependencies +fix: code is inside src folder Files changed: -M setup.py +M tox.ini -b'diff --git a/setup.py b/setup.py\nindex 6f5cdac..ec9ce29 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -41,7 +41,6 @@\n extras_require={\n "test": [\n "DateTime",\n- "mock",\n "zope.configuration",\n ],\n },\n' +b'diff --git a/tox.ini b/tox.ini\nindex c5e3f4f..21289b5 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -49,7 +49,7 @@ deps =\n zope.testrunner\n -c https://dist.plone.org/release/6.0-dev/constraints.txt\n commands =\n- zope-testrunner --all --test-path={toxinidir} -s plone.folder {posargs}\n+ zope-testrunner --all --test-path={toxinidir}/src -s plone.folder {posargs}\n extras =\n test\n \n@@ -62,7 +62,7 @@ deps =\n zope.testrunner\n -c https://dist.plone.org/release/6.0-dev/constraints.txt\n commands =\n- coverage run {envbindir}/zope-testrunner --all --test-path={toxinidir} -s plone.folder {posargs}\n+ coverage run {envbindir}/zope-testrunner --all --test-path={toxinidir}/src -s plone.folder {posargs}\n coverage report -m --format markdown\n extras =\n test\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:27:19+02:00 +Date: 2023-04-15T14:46:15+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/f4d751acdb793927ba2d69519ef05dcf81b31898 +Commit: https://github.com/plone/plone.folder/commit/ba99db564bbc0200f7009c9c16e59f6894f7277a -chore: bump version +feat: declare dependencies Files changed: +M pyproject.toml M setup.py -b'diff --git a/setup.py b/setup.py\nindex ec9ce29..9234b93 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -2,7 +2,7 @@\n from setuptools import setup\n \n \n-version = "1.4.3.dev0"\n+version = "2.0.0.dev0"\n \n setup(\n name="plone.event",\n' +b'diff --git a/pyproject.toml b/pyproject.toml\nindex 92c3af9..9054002 100644\n--- a/pyproject.toml\n+++ b/pyproject.toml\n@@ -81,3 +81,4 @@ Zope = [\n \'Products.CMFCore\', \'Products.CMFDynamicViewFTI\',\n ]\n python-dateutil = [\'dateutil\']\n+\'Products.ZCatalog\' = [\'Products.PluginIndexes\']\ndiff --git a/setup.py b/setup.py\nindex 7eef4f5..07c1bd2 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -41,19 +41,13 @@\n zip_safe=False,\n python_requires=">=3.8",\n install_requires=[\n- "plone.memoize",\n- "Products.BTreeFolder2",\n "Products.CMFCore",\n "Products.ZCatalog",\n "setuptools",\n- "zope.annotation",\n- "zope.component",\n- "zope.container",\n- "zope.interface",\n- "Zope2",\n ],\n extras_require={\n "test": [\n+ "plone.app.testing",\n "profilehooks",\n ]\n },\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-15T14:27:19+02:00 +Date: 2023-04-15T15:36:25+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.event/commit/2e2c3542ebfa69401ff6d12f98f4e4547daa4773 +Commit: https://github.com/plone/plone.folder/commit/445178f54700342af5ba48bb639f08fae5c22361 Add news entry Files changed: A news/1.breaking -b'diff --git a/news/1.breaking b/news/1.breaking\nnew file mode 100644\nindex 0000000..6a2e7d2\n--- /dev/null\n+++ b/news/1.breaking\n@@ -0,0 +1,2 @@\n+Drop python 2.7 compatibility.\n+[gforcada]\n' +b'diff --git a/news/1.breaking b/news/1.breaking\nnew file mode 100644\nindex 0000000..174ecbf\n--- /dev/null\n+++ b/news/1.breaking\n@@ -0,0 +1,2 @@\n+Drop python 2.7 support.\n+[gforcada]\n' -Repository: plone.event +Repository: plone.folder Branch: refs/heads/master -Date: 2023-04-17T18:10:17+02:00 +Date: 2023-04-17T18:13:32+02:00 Author: Jens W. Klein (jensens) -Commit: https://github.com/plone/plone.event/commit/32ed6428ab87c33b4c85ecc677b23e3966302e6c +Commit: https://github.com/plone/plone.folder/commit/cc9eeed92f75a5bd0ffe9f1ae59e6fb32ed1dc76 -Merge pull request #16 from plone/config-with-default-template-79a1a2bf +Merge pull request #18 from plone/config-with-default-template-dc2e2aa0 Config with default template @@ -218,27 +262,30 @@ A .meta.toml A .pre-commit-config.yaml A news/1.breaking A news/5cc689e5.internal +A tox.ini M CHANGES.rst -M plone/__init__.py -M plone/event/adapters.py -M plone/event/configure.zcml -M plone/event/interfaces.py -M plone/event/recurrence.py -M plone/event/recurrence.rst -M plone/event/recurrence_dateutil.rst -M plone/event/tests/test_adapters.py -M plone/event/tests/test_doctest.py -M plone/event/tests/test_recurrence_int_sequence.py -M plone/event/tests/test_recurrence_sequence_ical.py -M plone/event/tests/test_recurrence_sequence_timedelta.py -M plone/event/tests/test_utils.py -M plone/event/utils.py -M plone/event/utils.rst M pyproject.toml M setup.cfg M setup.py -M tox.ini -D .travis.yml - -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..1b2346d\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 = "5cc689e5"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..fdafec1\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.3.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.3\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.4\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/.travis.yml b/.travis.yml\ndeleted file mode 100644\nindex afff7e4..0000000\n--- a/.travis.yml\n+++ /dev/null\n@@ -1,12 +0,0 @@\n-language: python\n-python:\n- - 2.7\n- - 3.6\n- - 3.7\n- - 3.8\n-install:\n- - pip install tox-travis\n-script:\n- - tox\n-notifications:\n- email: false\ndiff --git a/CHANGES.rst b/CHANGES.rst\nindex b5948f3..1b72551 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -108,10 +108,10 @@ Fixes:\n ----------------\n \n - Fix tests, where they broke with unicode recurrence strings and unicode date\n- formating strings.\n+ formatting strings.\n [thet]\n \n-- Make rrule munging hack only apply to RDATEs, EXDATEs and UNTILs which have\n+- Make rrule munging hack only apply to `RDATE`, `EXDATE` and `UNTIL` which have\n null times, otherwise the DateRecurrenceIndex is broken for those who are\n generating RRULES using a non-broken widget. This will still result in broken\n RRULEs for some edge cases (where an RDATE is explicitly set for midnight on\ndiff --git a/news/1.breaking b/news/1.breaking\nnew file mode 100644\nindex 0000000..6a2e7d2\n--- /dev/null\n+++ b/news/1.breaking\n@@ -0,0 +1,2 @@\n+Drop python 2.7 compatibility.\n+[gforcada]\ndiff --git a/news/5cc689e5.internal b/news/5cc689e5.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/5cc689e5.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/event/adapters.py b/plone/event/adapters.py\nindex 717657a..2549298 100644\n--- a/plone/event/adapters.py\n+++ b/plone/event/adapters.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.event.interfaces import IEvent\n from plone.event.interfaces import IEventAccessor\n from zope.component import adapter\n@@ -7,7 +6,7 @@\n \n @implementer(IEventAccessor)\n @adapter(IEvent)\n-class EventAccessor(object):\n+class EventAccessor:\n """Simple event accessor adapter implementation for generic events, which\n follow the IEvent interface closely.\n \n@@ -15,7 +14,7 @@ class EventAccessor(object):\n """\n \n def __init__(self, context):\n- object.__setattr__(self, \'context\', context)\n+ object.__setattr__(self, "context", context)\n \n def __getattr__(self, name):\n return getattr(self.context, name)\ndiff --git a/plone/event/configure.zcml b/plone/event/configure.zcml\nindex f9699f7..1e6e17c 100644\n--- a/plone/event/configure.zcml\n+++ b/plone/event/configure.zcml\n@@ -1,7 +1,8 @@\n \n+ i18n_domain="plone.event"\n+ >\n \n- \n+ \n \n \ndiff --git a/plone/event/interfaces.py b/plone/event/interfaces.py\nindex fa88995..572b7e1 100644\n--- a/plone/event/interfaces.py\n+++ b/plone/event/interfaces.py\n@@ -1,12 +1,9 @@\n-# -*- coding: utf-8 -*-\n from zope.interface import Attribute\n from zope.interface import Interface\n \n \n class IEvent(Interface):\n- """Event type marker interface.\n-\n- """\n+ """Event type marker interface."""\n \n \n class IEventRecurrence(Interface):\n@@ -21,8 +18,9 @@ class IOccurrence(Interface):\n occurrence.\n \n """\n- start = Attribute(u\'Occurrence start date\')\n- end = Attribute(u\'Occurrence end date\')\n+\n+ start = Attribute("Occurrence start date")\n+ end = Attribute("Occurrence end date")\n \n \n class ICalendarAccessor(Interface):\n@@ -31,16 +29,15 @@ class ICalendarAccessor(Interface):\n A calendar is a collection of calendar components, like events.\n \n """\n- uid = Attribute(u\'UID of the calendar. Autogenerated, read only.\')\n+\n+ uid = Attribute("UID of the calendar. Autogenerated, read only.")\n # rw attributes\n- title = Attribute(u\'Calendar title.\')\n- description = Attribute(u\'Calendar description text.\')\n- timezone = Attribute(u\'Default timezone of the calendar.\')\n+ title = Attribute("Calendar title.")\n+ description = Attribute("Calendar description text.")\n+ timezone = Attribute("Default timezone of the calendar.")\n \n def items(self):\n- """Return a list of calendar component items, like events.\n-\n- """\n+ """Return a list of calendar component items, like events."""\n \n \n class IEventAccessor(Interface):\n@@ -52,40 +49,38 @@ class IEventAccessor(Interface):\n """\n \n # ro attributes\n- uid = Attribute(u\'UID of the event. Autogenerated, read only.\')\n- created = Attribute(u\'Python datetime of the event creation timestamp.\')\n- duration = Attribute(u\'Duration of the event. Computed attribute.\')\n+ uid = Attribute("UID of the event. Autogenerated, read only.")\n+ created = Attribute("Python datetime of the event creation timestamp.")\n+ duration = Attribute("Duration of the event. Computed attribute.")\n \n # reference\n url = Attribute(\n- u\'Cannonical, unique url of the event. External events \'\n- u\'are referenced by the origin url unless explicitly set.\'\n+ "Canonical, unique url of the event. External events "\n+ "are referenced by the origin url unless explicitly set."\n )\n \n # rw attributes\n- last_modified = Attribute(u\'Last modified Python datetime.\')\n- title = Attribute(u\'Event title.\')\n- description = Attribute(u\'Event description text.\')\n- start = Attribute(u\'Event start date as Python datetime.\')\n- end = Attribute(u\'Event end date as Python datetime.\')\n- whole_day = Attribute(u\'Event lasts whole day.\')\n- open_end = Attribute(u\'Event has no defined end time.\')\n- timezone = Attribute(u\'Timezone of the event. A pytz timezone identifier.\')\n- recurrence = Attribute(u\'RFC5545 compatible recurrence definition.\')\n- location = Attribute(u\'Location of the event.\')\n- attendees = Attribute(u\'List of attendees.\')\n- contact_name = Attribute(u\'Contact name.\')\n- contact_email = Attribute(u\'Contact email.\')\n- contact_phone = Attribute(u\'Contact phone.\')\n- event_url = Attribute(u\'Website of the event.\')\n- subjects = Attribute(u\'Categories.\')\n- text = Attribute(u\'Body text of the event.\')\n+ last_modified = Attribute("Last modified Python datetime.")\n+ title = Attribute("Event title.")\n+ description = Attribute("Event description text.")\n+ start = Attribute("Event start date as Python datetime.")\n+ end = Attribute("Event end date as Python datetime.")\n+ whole_day = Attribute("Event lasts whole day.")\n+ open_end = Attribute("Event has no defined end time.")\n+ timezone = Attribute("Timezone of the event. A pytz timezone identifier.")\n+ recurrence = Attribute("RFC5545 compatible recurrence definition.")\n+ location = Attribute("Location of the event.")\n+ attendees = Attribute("List of attendees.")\n+ contact_name = Attribute("Contact name.")\n+ contact_email = Attribute("Contact email.")\n+ contact_phone = Attribute("Contact phone.")\n+ event_url = Attribute("Website of the event.")\n+ subjects = Attribute("Categories.")\n+ text = Attribute("Body text of the event.")\n \n \n class IRecurrenceSupport(Interface):\n- """Event type recurrence adatper.\n-\n- """\n+ """Event type recurrence adapter."""\n \n def occurrences(self, range_start, range_end):\n """Return a list of IOccurrence objects with custom attributes of the\n@@ -101,9 +96,7 @@ def occurrences(self, range_start, range_end):\n \n \n class IICalendar(Interface):\n- """Adapter, which is used to construct an icalendar object.\n-\n- """\n+ """Adapter, which is used to construct an icalendar object."""\n \n \n class IICalendarEventComponent(Interface):\n@@ -156,37 +149,38 @@ class / created / description / geo /\n resources / rdate / x-prop / iana-prop\n \n """\n- dtstart = Attribute(u\'Start Date/Time\')\n- dtend = Attribute(u\'End Date/Time\')\n- duration = Attribute(u\'Duration\')\n- rrule = Attribute(u\'Recurrence Rule\')\n- description = Attribute(u\'Description\')\n- location = Attribute(u\'Location\')\n- summary = Attribute(u\'Summary\')\n- url = Attribute(u\'Url\')\n- attendee = Attribute(u\'Attendee\')\n- categories = Attribute(u\'Categories\')\n- contact = Attribute(u\'Contact\')\n-\n- exdate = Attribute(u\'Exdate\')\n- rdate = Attribute(u\'Rdate\')\n-\n- dtstamp = Attribute(u\'Timestamp\')\n- uid = Attribute(u\'Unique identifier\')\n- klass = Attribute(u\'Class\') # class\n- created = Attribute(u\'Created\')\n- geo = Attribute(u\'Geo\')\n- last_mod = Attribute(u\'Last Modified\') # last-mod\n- organizer = Attribute(u\'Organizer\')\n- priority = Attribute(u\'Priority\')\n- seq = Attribute(u\'Seq\')\n- status = Attribute(u\'Status\')\n- transp = Attribute(u\'Transp\')\n- recurid = Attribute(u\'Recurid\')\n- attach = Attribute(u\'Attach\')\n- comment = Attribute(u\'Comment\')\n- rstatus = Attribute(u\'Rstatus\')\n- related = Attribute(u\'Related\')\n- resources = Attribute(u\'Resources\')\n- x_prop = Attribute(u\'X Prop\') # x-prop\n- iana_prop = Attribute(u\'Iana Prop\') # iana-prop\n+\n+ dtstart = Attribute("Start Date/Time")\n+ dtend = Attribute("End Date/Time")\n+ duration = Attribute("Duration")\n+ rrule = Attribute("Recurrence Rule")\n+ description = Attribute("Description")\n+ location = Attribute("Location")\n+ summary = Attribute("Summary")\n+ url = Attribute("Url")\n+ attendee = Attribute("Attendee")\n+ categories = Attribute("Categories")\n+ contact = Attribute("Contact")\n+\n+ exdate = Attribute("Exdate")\n+ rdate = Attribute("Rdate")\n+\n+ dtstamp = Attribute("Timestamp")\n+ uid = Attribute("Unique identifier")\n+ klass = Attribute("Class") # class\n+ created = Attribute("Created")\n+ geo = Attribute("Geo")\n+ last_mod = Attribute("Last Modified") # last-mod\n+ organizer = Attribute("Organizer")\n+ priority = Attribute("Priority")\n+ seq = Attribute("Seq")\n+ status = Attribute("Status")\n+ transp = Attribute("Transp")\n+ recurid = Attribute("Recurid")\n+ attach = Attribute("Attach")\n+ comment = Attribute("Comment")\n+ rstatus = Attribute("Rstatus")\n+ related = Attribute("Related")\n+ resources = Attribute("Resources")\n+ x_prop = Attribute("X Prop") # x-prop\n+ iana_prop = Attribute("Iana Prop") # iana-prop\ndiff --git a/plone/event/recurrence.py b/plone/event/recurrence.py\nindex 0bb42ce..2900837 100644\n--- a/plone/event/recurrence.py\n+++ b/plone/event/recurrence.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from dateutil import rrule\n from plone.event.utils import DSTAUTO\n from plone.event.utils import dt2int\n@@ -16,12 +15,12 @@\n \n \n def recurrence_sequence_ical(\n- start,\n- recrule=None,\n- from_=None,\n- until=None,\n- count=None,\n- duration=None,\n+ start,\n+ recrule=None,\n+ from_=None,\n+ until=None,\n+ count=None,\n+ duration=None,\n ):\n """Calculates a sequence of datetime objects from a recurrence rule\n following the RFC2445 specification, using python-dateutil recurrence\n@@ -45,13 +44,13 @@ def recurrence_sequence_ical(\n MAXDATE limit the recurrence calculation.\n :type until: datetime.datetime\n \n- :param count: Optional integer which defines the number of occurences.\n+ :param count: Optional integer which defines the number of occurrences.\n If not given, until or MAXDATE limits the recurrence\n calculation.\n :type count: integer\n \n :param duration: Optional timedelta instance, which is used to calculate\n- if a occurence datetime plus duration is within the\n+ if a occurrence datetime plus duration is within the\n queried timerange.\n :type duration: datetime.timedelta\n \n@@ -68,7 +67,7 @@ def recurrence_sequence_ical(\n _from = tzdel(from_)\n _until = tzdel(until)\n if duration:\n- assert (isinstance(duration, datetime.timedelta))\n+ assert isinstance(duration, datetime.timedelta)\n else:\n duration = datetime.timedelta(0)\n \n@@ -88,16 +87,16 @@ def recurrence_sequence_ical(\n # time for UNTIL, RDATE and EXDATE.\n t0 = start.time() # set initial time information.\n # First, replace all times in the recurring rule with starttime\n- t0str = \'T{0:02d}{1:02d}{2:02d}\'.format(t0.hour, t0.minute, t0.second)\n+ t0str = f"T{t0.hour:02d}{t0.minute:02d}{t0.second:02d}"\n # Replace any times set to 000000 with start time, not all\n # rrules are set by a specific broken widget. Don\'t waste time\n # subbing if the start time is already 000000.\n- if t0str != \'T000000\':\n- recrule = re.sub(r\'T000000\', t0str, recrule)\n+ if t0str != "T000000":\n+ recrule = re.sub(r"T000000", t0str, recrule)\n # Then, replace incorrect until times with the end of the day\n recrule = re.sub(\n- r\'(UNTIL[^T]*[0-9]{8})T(000000)\',\n- r\'\\1T235959\',\n+ r"(UNTIL[^T]*[0-9]{8})T(000000)",\n+ r"\\1T235959",\n recrule,\n )\n \n@@ -141,21 +140,21 @@ def recurrence_sequence_ical(\n \n \n def recurrence_sequence_timedelta(\n- start,\n- delta=None,\n- until=None,\n- count=None,\n- dst=DSTAUTO,\n+ start,\n+ delta=None,\n+ until=None,\n+ count=None,\n+ dst=DSTAUTO,\n ):\n- """ Calculates a sequence of datetime objects from a timedelta integer,\n- which defines the minutes between each occurence.\n+ """Calculates a sequence of datetime objects from a timedelta integer,\n+ which defines the minutes between each occurrence.\n \n :param start: datetime or DateTime instance of the date from which the\n recurrence sequence is calculated.\n :type start: datetime\n \n :param delta: Integer which defines the minutes\n- between each date occurence.\n+ between each date occurrence.\n :type delta: integer\n \n :param until: datetime or DateTime instance of the date, until the\n@@ -163,7 +162,7 @@ def recurrence_sequence_timedelta(\n count or MAXDATE limit the recurrence calculation.\n :type until: datetime\n \n- :param count: Integer which defines the number of occurences. If not given,\n+ :param count: Integer which defines the number of occurrences. If not given,\n until or MAXDATE limits the recurrence calculation.\n :param count: integer\n \n@@ -205,7 +204,7 @@ def recurrence_sequence_timedelta(\n \n \n def recurrence_int_sequence(sequence):\n- """ Generates a sequence of integer representations from a sequence of\n+ """Generates a sequence of integer representations from a sequence of\n dateime instances.\n \n :param sequence: An iterable sequence of datetime instances.\ndiff --git a/plone/event/recurrence.rst b/plone/event/recurrence.rst\nindex 67ad89e..e85db9d 100644\n--- a/plone/event/recurrence.rst\n+++ b/plone/event/recurrence.rst\n@@ -65,7 +65,7 @@ Timezone aware Daylight Saving Time dates crossing\n datetime.datetime(2010, 11, 1, 9, 0, tzinfo=)]\n \n \n-Note, that recurrence_sequence_ical calculates occurences timezone naively and\n+Note, that recurrence_sequence_ical calculates occurrences timezone naively and\n applies timezones afterwards. This leads into a problem in corner cases:\n >>> list(recurrence_sequence_ical(\n ... start=at.localize(datetime(2010,10,30,23,0,0,0)),\n@@ -109,10 +109,10 @@ Multiple Ruleset\n datetime.datetime(2010, 1, 20, 0, 0, tzinfo=)]\n \n \n-Limiting number of occurences\n+Limiting number of occurrences\n -----------------------------\n \n-Until (date until recurrence happens) and count (Number of occurences) can also\n+Until (date until recurrence happens) and count (Number of occurrences) can also\n be given in recurrence_sequence_ical, instead of defining it in the rrule.\n But defining it in a rrule gives more flexibility since you can set it for each\n rrule individually.\n@@ -301,10 +301,10 @@ Here the correct behaviour on day level with DSTKEEP.\n datetime.datetime(2008, 3, 30, 19, 0, tzinfo=),\n datetime.datetime(2008, 3, 30, 20, 0, tzinfo=)]\n \n-Usally we want an clever behaviour, dependend on delta. This is implemented\n+Usually we want a clever behaviour, dependent on delta. This is implemented\n with DSTAUTO, which is the default behaviour.\n \n-Here the correct behaviour on day level or above: DSTADJUST is choosen.\n+Here the correct behaviour on day level or above: DSTADJUST is chosen.\n \n >>> start = datetime(2008, 3, 29, 11, 0, 0, 0, pytz.timezone(\'CET\'))\n >>> until = datetime(2008, 3, 31, 11, 0, 0, 0, pytz.timezone(\'CET\'))\n@@ -319,7 +319,7 @@ Here the correct behaviour on day level or above: DSTADJUST is choosen.\n datetime.datetime(2008, 3, 31, 11, 0, tzinfo=)]\n \n \n-The correct behaviour on below day level: DSTKEEP is choosen.\n+The correct behaviour on below day level: DSTKEEP is chosen.\n \n >>> start = datetime(2008, 3, 29, 21, 0, 0, 0, pytz.timezone(\'CET\'))\n >>> until = datetime(2008, 3, 30, 21, 0, 0, 0, pytz.timezone(\'CET\')) - timedelta(microseconds=1)\n@@ -398,7 +398,7 @@ timezones works.\n >>> seqDT[0] == seqdt[0]\n True\n \n-Does integer represenation work?\n+Does integer representation work?\n >>> seqDT = list(recurrence_int_sequence(recurrence_sequence_timedelta(DT, 0, None)))\n >>> seqdt = list(recurrence_int_sequence(recurrence_sequence_timedelta(dt, 0, None)))\n \ndiff --git a/plone/event/recurrence_dateutil.rst b/plone/event/recurrence_dateutil.rst\nindex 685f700..cf2dc85 100644\n--- a/plone/event/recurrence_dateutil.rst\n+++ b/plone/event/recurrence_dateutil.rst\n@@ -49,12 +49,12 @@ This issue is corrected by plone.event.util.utcoffset_normalize:\n \n \n It\'s safer to let rrule calculate timezone naive dates and localizing them\n-afterwards than letting rrule substracting (EXDATE) timezone correct dates from\n+afterwards than letting rrule subtracting (EXDATE) timezone correct dates from\n a possibly timezone incorrect recurrence sequence. This issue will be gone, if\n rrule does TZ normalizing itself before applying EXDATE to the recurrence\n sequence.\n \n-See here... This is our recurrence rule. We want to substract from the sequence\n+See here... This is our recurrence rule. We want to subtract from the sequence\n the date 2010-10-31, 23:30 in UTC, which is 2010-11-01, 0:30 in Austria, UTC+1\n \n ::\n@@ -63,7 +63,7 @@ the date 2010-10-31, 23:30 in UTC, which is 2010-11-01, 0:30 in Austria, UTC+1\n ... EXDATE:20101031T233000Z"""\n \n If we let the sequence start from 1st November, the 1st November is correctly\n-substracted, since the sequence has all correct timezones.\n+subtracted, since the sequence has all correct timezones.\n \n ::\n \n@@ -73,7 +73,7 @@ substracted, since the sequence has all correct timezones.\n datetime.datetime(2010, 11, 3, 0, 30, tzinfo=)]\n \n But if we start from 30th October, where UTC+2 offset is still active, the\n-sequence has incorrect timezones and substracting does not work as expected\n+sequence has incorrect timezones and subtracting does not work as expected\n anymore.\n \n ::\ndiff --git a/plone/event/tests/test_adapters.py b/plone/event/tests/test_adapters.py\nindex b302192..df92e79 100644\n--- a/plone/event/tests/test_adapters.py\n+++ b/plone/event/tests/test_adapters.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from datetime import datetime\n from plone.event.interfaces import IEvent\n from plone.event.interfaces import IEventAccessor\n@@ -9,22 +8,24 @@\n import zope.interface\n \n \n-class MockObject(object):\n+class MockObject:\n """Mock object"""\n \n \n class TestAdapters(unittest.TestCase):\n def setUp(self):\n import zope.component\n- context = xmlconfig.file(\'meta.zcml\', zope.component)\n- xmlconfig.file(\'configure.zcml\', zope.component, context=context)\n+\n+ context = xmlconfig.file("meta.zcml", zope.component)\n+ xmlconfig.file("configure.zcml", zope.component, context=context)\n \n import plone.event\n- xmlconfig.file(\'configure.zcml\', plone.event, context=context)\n+\n+ xmlconfig.file("configure.zcml", plone.event, context=context)\n \n def test_event_accessor(self):\n obj = MockObject()\n- tz = pytz.timezone(\'Europe/Vienna\')\n+ tz = pytz.timezone("Europe/Vienna")\n obj.start = datetime(2012, 12, 12, 10, 0, tzinfo=tz)\n obj.end = datetime(2012, 12, 12, 12, 0, tzinfo=tz)\n zope.interface.alsoProvides(obj, IEvent)\n@@ -49,9 +50,9 @@ def test_event_accessor(self):\n acc.something = True\n self.assertTrue(acc.something == obj.something is True)\n del acc.something\n- self.assertTrue(hasattr(acc, \'something\') is False)\n- self.assertTrue(hasattr(obj, \'something\') is False)\n+ self.assertTrue(hasattr(acc, "something") is False)\n+ self.assertTrue(hasattr(obj, "something") is False)\n \n del acc.start\n- self.assertTrue(hasattr(acc, \'start\') is False)\n- self.assertTrue(hasattr(obj, \'start\') is False)\n+ self.assertTrue(hasattr(acc, "start") is False)\n+ self.assertTrue(hasattr(obj, "start") is False)\ndiff --git a/plone/event/tests/test_doctest.py b/plone/event/tests/test_doctest.py\nindex 77ab9e1..6e7b759 100644\n--- a/plone/event/tests/test_doctest.py\n+++ b/plone/event/tests/test_doctest.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from zope.component.testing import tearDown\n \n import doctest\n@@ -8,11 +7,13 @@\n \n OPTIONFLAGS = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS\n DOCFILES = [\n- \'recurrence.rst\',\n- \'recurrence_dateutil.rst\',\n- \'utils.rst\',\n+ "recurrence.rst",\n+ "recurrence_dateutil.rst",\n+ "utils.rst",\n+]\n+DOCMODS = [\n+ "plone.event.utils",\n ]\n-DOCMODS = [\'plone.event.utils\', ]\n \n \n def test_suite():\n@@ -20,24 +21,19 @@ def test_suite():\n suite.addTests(\n [\n doctest.DocFileSuite(\n- os.path.join(os.path.dirname(__file__), \'..\', docfile),\n+ os.path.join(os.path.dirname(__file__), "..", docfile),\n module_relative=False,\n optionflags=OPTIONFLAGS,\n- tearDown=tearDown\n+ tearDown=tearDown,\n )\n for docfile in DOCFILES\n ]\n )\n suite.addTests(\n- [\n- doctest.DocTestSuite(\n- docmod, optionflags=OPTIONFLAGS\n- )\n- for docmod in DOCMODS\n- ]\n+ [doctest.DocTestSuite(docmod, optionflags=OPTIONFLAGS) for docmod in DOCMODS]\n )\n return suite\n \n \n-if __name__ == \'__main__\':\n- unittest.main(defaultTest=\'test_suite\')\n+if __name__ == "__main__":\n+ unittest.main(defaultTest="test_suite")\ndiff --git a/plone/event/tests/test_recurrence_int_sequence.py b/plone/event/tests/test_recurrence_int_sequence.py\nindex ccd072c..9812fb4 100644\n--- a/plone/event/tests/test_recurrence_int_sequence.py\n+++ b/plone/event/tests/test_recurrence_int_sequence.py\n@@ -1,13 +1,14 @@\n-# -*- coding: utf-8 -*-\n-import mock\n+from unittest import mock\n+\n import unittest\n \n \n class TestRecurrenceIntSequence(unittest.TestCase):\n- @mock.patch(\'plone.event.recurrence.dt2int\')\n+ @mock.patch("plone.event.recurrence.dt2int")\n def test_recrule_str_(self, dt2int):\n from plone.event.recurrence import recurrence_int_sequence\n+\n sequence = [1, 2, 3]\n- dt2int.return_value = \'a\'\n+ dt2int.return_value = "a"\n res = [a for a in recurrence_int_sequence(sequence)]\n- self.assertEqual(res, [\'a\', \'a\', \'a\'])\n+ self.assertEqual(res, ["a", "a", "a"])\ndiff --git a/plone/event/tests/test_recurrence_sequence_ical.py b/plone/event/tests/test_recurrence_sequence_ical.py\nindex 6f2ed8e..25f1887 100644\n--- a/plone/event/tests/test_recurrence_sequence_ical.py\n+++ b/plone/event/tests/test_recurrence_sequence_ical.py\n@@ -1,31 +1,33 @@\n-# -*- coding: utf-8 -*-\n import unittest\n \n \n class TestRecurrenceSequenceIcal(unittest.TestCase):\n def test_start(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n seq = recurrence_sequence_ical(start)\n results = [res for res in seq]\n self.assertEqual(len(results), 1)\n \n def test_recrule_str(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=10;COUNT=5"\n seq = recurrence_sequence_ical(start, recrule=recrule)\n results = [res for res in seq]\n self.assertEqual(len(results), 5)\n \n def test_recrule_str_rdate(self):\n """Test, if an RDATE date has the correct time set.\n- See: "BUGFIX WRONG RDATE TIME" in recurrence.py\n+ See: "BUGFIX WRONG RDATE TIME" in recurrence.py\n """\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23, 10, 10)\n recrule = """FREQ=DAILY;INTERVAL=1;COUNT=3\n RDATE:20111129T000000"""\n@@ -35,21 +37,22 @@ def test_recrule_str_rdate(self):\n self.assertEqual(results[0].time(), results[-1].time())\n \n def test_recrule_str_exdate(self):\n- """Test, if an EXDATE date are not in the resulting recurrence set.\n- """\n- from plone.event.recurrence import recurrence_sequence_ical\n+ """Test, if an EXDATE date are not in the resulting recurrence set."""\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n import pytz\n- at = pytz.timezone(\'Europe/Vienna\')\n+\n+ at = pytz.timezone("Europe/Vienna")\n start = at.localize(datetime(2013, 6, 29, 10, 10))\n- recrule = \'RRULE:FREQ=DAILY;COUNT=4\\r\\nEXDATE:20130630T000000,20130701T000000\\r\\nRDATE:20130706T000000,20130809T000000\' # noqa\n+ recrule = "RRULE:FREQ=DAILY;COUNT=4\\r\\nEXDATE:20130630T000000,20130701T000000\\r\\nRDATE:20130706T000000,20130809T000000" # noqa\n seq = recurrence_sequence_ical(start, recrule=recrule)\n res = [res for res in seq]\n res_test = [\n at.localize(datetime(2013, 6, 29, 10, 10)),\n at.localize(datetime(2013, 7, 2, 10, 10)),\n at.localize(datetime(2013, 7, 6, 10, 10)),\n- at.localize(datetime(2013, 8, 9, 10, 10))\n+ at.localize(datetime(2013, 8, 9, 10, 10)),\n ]\n self.assertEqual(len(res), 4)\n self.assertEqual(res, res_test)\n@@ -58,26 +61,29 @@ def test_recrule_str_until(self):\n """Test, if UNTIL stops the sequence at the end of the day, even if\n it\'s set to 0:00 by the recurrence widget.\n """\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n import pytz\n- at = pytz.timezone(\'Europe/Vienna\')\n+\n+ at = pytz.timezone("Europe/Vienna")\n start = at.localize(datetime(2013, 6, 29, 10, 10))\n- recrule = \'RRULE:FREQ=DAILY;UNTIL=20130702T000000\'\n+ recrule = "RRULE:FREQ=DAILY;UNTIL=20130702T000000"\n seq = recurrence_sequence_ical(start, recrule=recrule)\n res = [res for res in seq]\n res_test = [\n at.localize(datetime(2013, 6, 29, 10, 10)),\n at.localize(datetime(2013, 6, 30, 10, 10)),\n at.localize(datetime(2013, 7, 1, 10, 10)),\n- at.localize(datetime(2013, 7, 2, 10, 10))\n+ at.localize(datetime(2013, 7, 2, 10, 10)),\n ]\n self.assertEqual(len(res), 4)\n self.assertEqual(res, res_test)\n \n def test_recrule_from_until(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n recrule = None\n from_ = datetime(2011, 11, 1)\n@@ -92,29 +98,32 @@ def test_recrule_from_until(self):\n self.assertEqual(len(results), 1)\n \n def test_recrule_str_more_than_MAXCOUNT(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=1001\'\n+ recrule = "FREQ=DAILY;INTERVAL=10;COUNT=1001"\n seq = recurrence_sequence_ical(start, recrule=recrule)\n results = [res for res in seq]\n self.assertEqual(len(results), 1000)\n \n def test_recrule_str_more_than_count(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=10;COUNT=10\'\n+ recrule = "FREQ=DAILY;INTERVAL=10;COUNT=10"\n count = 5\n seq = recurrence_sequence_ical(start, recrule=recrule, count=count)\n results = [res for res in seq]\n self.assertEqual(len(results), 5)\n \n def test_recrule_from(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=1;COUNT=5"\n from_ = datetime(2011, 11, 25)\n until = datetime(2011, 11, 27)\n seq = recurrence_sequence_ical(\n@@ -127,10 +136,11 @@ def test_recrule_from(self):\n self.assertEqual(len(results), 3)\n \n def test_recrule_until(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 24)\n- recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=1;COUNT=5"\n from_ = datetime(2011, 11, 23)\n until = datetime(2011, 11, 27)\n seq = recurrence_sequence_ical(\n@@ -143,13 +153,13 @@ def test_recrule_until(self):\n self.assertEqual(len(results), 4)\n \n def test_recrule_from_until_with_duration(self):\n- """Should include events ranging into the queried timerange.\n- """\n- from plone.event.recurrence import recurrence_sequence_ical\n+ """Should include events ranging into the queried timerange."""\n from datetime import datetime\n from datetime import timedelta\n+ from plone.event.recurrence import recurrence_sequence_ical\n+\n start = datetime(2011, 11, 23)\n- recrule = \'FREQ=DAILY;INTERVAL=1;COUNT=5\'\n+ recrule = "FREQ=DAILY;INTERVAL=1;COUNT=5"\n from_ = datetime(2011, 11, 26)\n until = datetime(2011, 11, 27)\n seq = recurrence_sequence_ical(\n@@ -163,10 +173,10 @@ def test_recrule_from_until_with_duration(self):\n self.assertEqual(len(results), 4)\n \n def test_recrule_until_with_timezone(self):\n- from plone.event.recurrence import recurrence_sequence_ical\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_ical\n \n start = datetime(2011, 11, 24)\n- recrule = \'RRULE:FREQ=DAILY;UNTIL=20111130T000000Z\'\n+ recrule = "RRULE:FREQ=DAILY;UNTIL=20111130T000000Z"\n seq = list(recurrence_sequence_ical(start, recrule=recrule))\n self.assertEqual(len(seq), 7)\ndiff --git a/plone/event/tests/test_recurrence_sequence_timedelta.py b/plone/event/tests/test_recurrence_sequence_timedelta.py\nindex c9493f7..9ca7210 100644\n--- a/plone/event/tests/test_recurrence_sequence_timedelta.py\n+++ b/plone/event/tests/test_recurrence_sequence_timedelta.py\n@@ -1,11 +1,11 @@\n-# -*- coding: utf-8 -*-\n import unittest\n \n \n class TestRecurrenceSequenceTimedelta(unittest.TestCase):\n def test_delta_None(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n until = datetime(2011, 11, 24)\n td = recurrence_sequence_timedelta(start, until=until)\n@@ -13,8 +13,9 @@ def test_delta_None(self):\n self.assertEqual(len(results), 1)\n \n def test_delta_zero(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 0\n until = datetime(2011, 11, 24)\n@@ -23,8 +24,9 @@ def test_delta_zero(self):\n self.assertEqual(len(results), 1)\n \n def test_until_None(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 1\n td = recurrence_sequence_timedelta(start, delta=delta)\n@@ -32,8 +34,9 @@ def test_until_None(self):\n self.assertEqual(len(results), 1)\n \n def test_delta_an_hour_until_next_day(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 60\n until = datetime(2011, 11, 24)\n@@ -42,8 +45,9 @@ def test_delta_an_hour_until_next_day(self):\n self.assertEqual(len(results), 25)\n \n def test_recur_more_than_MAXCOUNT(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 1\n until = datetime(2012, 11, 23)\n@@ -52,8 +56,9 @@ def test_recur_more_than_MAXCOUNT(self):\n self.assertEqual(len(results), 1001)\n \n def test_recur_more_than_count(self):\n- from plone.event.recurrence import recurrence_sequence_timedelta\n from datetime import datetime\n+ from plone.event.recurrence import recurrence_sequence_timedelta\n+\n start = datetime(2011, 11, 23)\n delta = 1\n until = datetime(2011, 11, 24)\ndiff --git a/plone/event/tests/test_utils.py b/plone/event/tests/test_utils.py\nindex f90fedd..ca82a01 100644\n--- a/plone/event/tests/test_utils.py\n+++ b/plone/event/tests/test_utils.py\n@@ -1,44 +1,50 @@\n-# -*- coding: utf-8 -*-\n-import mock\n+from unittest import mock\n+\n import unittest\n \n \n class TestUtils(unittest.TestCase):\n- @mock.patch(\'plone.event.utils.pytz\')\n- @mock.patch(\'plone.event.utils.os\')\n+ @mock.patch("plone.event.utils.pytz")\n+ @mock.patch("plone.event.utils.os")\n def test_default_timezone(self, os, pytz):\n from plone.event.utils import default_timezone\n- os.environ.keys.return_value = [\'TZ\']\n+\n+ os.environ.keys.return_value = ["TZ"]\n os.environ = mock.MagicMock()\n- pytz.timezone().zone = \'zone\'\n- self.assertEqual(default_timezone(), \'zone\')\n+ pytz.timezone().zone = "zone"\n+ self.assertEqual(default_timezone(), "zone")\n \n def test_utcoffset_normalize(self):\n from plone.event.utils import utcoffset_normalize\n+\n date = mock.Mock()\n date.replace = mock.Mock(side_effect=KeyError)\n self.assertEqual(utcoffset_normalize(date), date)\n \n- @mock.patch(\'plone.event.utils.guesstz\')\n- @mock.patch(\'plone.event.utils.utctz\')\n+ @mock.patch("plone.event.utils.guesstz")\n+ @mock.patch("plone.event.utils.utctz")\n def test_pydt__missing_zone_is_None(self, utctz, guesstz):\n from plone.event.utils import pydt\n+\n dt = mock.Mock()\n dt.toZone.return_value = dt\n dt.parts.return_value = (2011, 11, 24, 11, 39, 00)\n guesstz.return_value = None\n import pytz\n- utctz.return_value = pytz.timezone(\'UTC\')\n+\n+ utctz.return_value = pytz.timezone("UTC")\n pydt(dt)\n self.assertTrue(utctz.called)\n \n- @mock.patch(\'plone.event.utils.guesstz\')\n- @mock.patch(\'plone.event.utils.utctz\')\n+ @mock.patch("plone.event.utils.guesstz")\n+ @mock.patch("plone.event.utils.utctz")\n def test_pydt__missing_zone_is_not_None(self, utctz, guesstz):\n from plone.event.utils import pydt\n+\n dt = mock.Mock()\n import pytz\n- utctz.return_value = pytz.timezone(\'UTC\')\n+\n+ utctz.return_value = pytz.timezone("UTC")\n missing_zone = utctz()\n dt.toZone.return_value = dt\n dt.parts.return_value = (2011, 11, 24, 11, 39, 00)\n@@ -48,16 +54,19 @@ def test_pydt__missing_zone_is_not_None(self, utctz, guesstz):\n \n def test_pydt__wrong_type(self):\n from plone.event.utils import pydt\n- self.assertEqual(pydt(\'wrongtype\'), None)\n+\n+ self.assertEqual(pydt("wrongtype"), None)\n \n def test_dt2int_dt_is_None(self):\n from plone.event.utils import dt2int\n+\n self.assertFalse(dt2int(None))\n \n- @mock.patch(\'plone.event.utils.MAX32\', 0)\n- @mock.patch(\'plone.event.utils.utc\')\n+ @mock.patch("plone.event.utils.MAX32", 0)\n+ @mock.patch("plone.event.utils.utc")\n def test_dt2int_less_MAX32(self, utc):\n from plone.event.utils import dt2int\n+\n dt = mock.Mock()\n dd = mock.Mock()\n utc.return_value = dd\n@@ -68,10 +77,11 @@ def test_dt2int_less_MAX32(self, utc):\n dd.minute = 16\n self.assertRaises(OverflowError, lambda: dt2int(dt))\n \n- @mock.patch(\'plone.event.utils.MAX32\', 1077778937)\n- @mock.patch(\'plone.event.utils.utc\')\n+ @mock.patch("plone.event.utils.MAX32", 1077778937)\n+ @mock.patch("plone.event.utils.utc")\n def test_dt2int_more_MAX32(self, utc):\n from plone.event.utils import dt2int\n+\n dt = mock.Mock()\n dd = mock.Mock()\n utc.return_value = dd\ndiff --git a/plone/event/utils.py b/plone/event/utils.py\nindex 0763205..16029d4 100644\n--- a/plone/event/utils.py\n+++ b/plone/event/utils.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from datetime import date\n from datetime import datetime\n from datetime import timedelta\n@@ -59,8 +58,8 @@ def validated_timezone(timezone, fallback=None):\n except Exception:\n if fallback:\n logger.warn(\n- "The timezone {0} is not a valid timezone from the "\n- "Olson database or pytz. Falling back to {1}.".format(\n+ "The timezone {} is not a valid timezone from the "\n+ "Olson database or pytz. Falling back to {}.".format(\n timezone,\n fallback,\n )\n@@ -68,7 +67,7 @@ def validated_timezone(timezone, fallback=None):\n return fallback\n else:\n raise ValueError(\n- "The timezone {0} is not a valid timezone from "\n+ "The timezone {} is not a valid timezone from "\n "the Olson database or pytz.".format(timezone)\n )\n \n@@ -150,7 +149,7 @@ def is_same_time(start, end, exact=False):\n :returns: True, if start and end have the same time, otherwise False.\n :rtype: Boolean.\n \n- >>> from plone.event.utils import is_same_time, pydt\n+ >>> from plone.event.utils import is_same_time\n >>> from datetime import datetime, timedelta\n \n >>> is_same_time(datetime.now(), datetime.now()+timedelta(hours=1))\n@@ -273,7 +272,7 @@ def utcoffset_normalize(date, delta=None, dstmode=DSTAUTO):\n the same relative to UTC. So, 8:00 GMT+1 before will result\n in 7:00 GMT+2 afterwards. This behavior might be what\n machines expect, when recurrence rules are defined.\n- Mode DSTAUTO: If the relative delta between two occurences of\n+ Mode DSTAUTO: If the relative delta between two occurrences of\n a reucurrence sequence is less than a day, DSTKEEP will be\n used - otherwise DSTADJUST. This behavior is the default.\n """\n@@ -509,7 +508,7 @@ def pydt(dt, missing_zone=None, exact=False):\n def guesstz(DT):\n """\'Guess\' pytz from a zope DateTime.\n \n- !!! theres no real good method to guess the timezone.\n+ !!! there is no real good method to guess the timezone.\n DateTime was build somewhere in 1998 long before python had a working\n datetime implementation available and still stucks with this incomplete\n implementation.\n@@ -522,12 +521,12 @@ def guesstz(DT):\n \'Europe/Vienna\'\n \n GMT timezones which are popular with DateTime cannot be guessed,\n- unfortunatly\n+ unfortunately\n >>> guesstz(DateTime(\'2010-01-01 GMT+1\'))\n """\n tzname = DT.timezone()\n \n- # Please note, the GMT offset based timezone informations in DateTime are\n+ # Please note, the GMT offset based timezone information in DateTime are\n # not compatible with Etc/GMT based from pytz. They have different offsets.\n try:\n tz = pytz.timezone(tzname)\n@@ -558,7 +557,7 @@ def dt2int(dt):\n if value > MAX32:\n # value must be integer fitting in the 32bit range\n raise OverflowError(\n- """{0} is not within the range of indexable dates,<<\n+ """{} is not within the range of indexable dates,<<\n exceeding 32bit range.""".format(\n dt\n )\n@@ -663,7 +662,7 @@ def rfc2445dt(dt, mode="utc", date=True, time=True):\n dt = pydt(dt)\n if mode == "utc":\n dt = utc(dt)\n- date = "{0}{1}{2}{3}".format(\n+ date = "{}{}{}{}".format(\n date and dt.strftime("%Y%m%d") or "",\n date and time and "T" or "",\n time and dt.strftime("%H%M%S") or "",\ndiff --git a/plone/event/utils.rst b/plone/event/utils.rst\nindex 5278036..cdac790 100644\n--- a/plone/event/utils.rst\n+++ b/plone/event/utils.rst\n@@ -44,7 +44,7 @@ time in a way, that it\'s value will be the same as before normalizing.\n >>> utcoffset_normalize(date2, dstmode=DSTADJUST)\n datetime.datetime(2010, 11, 10, 0, 0, tzinfo=)\n \n-With DSTKEEP, normalizing will also keep the time as originaly set by UTC\n+With DSTKEEP, normalizing will also keep the time as originally set by UTC\n offset - time\'s value will change.\n >>> utcoffset_normalize(date2, dstmode=DSTKEEP)\n datetime.datetime(2010, 11, 9, 23, 0, tzinfo=)\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..92c3af9 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,64 @@ 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+ # ExtensionClass own provided namespaces\n+ \'ExtensionClass\', \'ComputedAttribute\', \'MethodObject\',\n+ # Zope dependencies\n+ \'AccessControl\', \'Acquisition\', \'AuthEncoding\', \'beautifulsoup4\', \'BTrees\',\n+ \'cffi\', \'Chameleon\', \'DateTime\', \'DocumentTemplate\',\n+ \'MultiMapping\', \'multipart\', \'PasteDeploy\', \'Persistence\', \'persistent\',\n+ \'pycparser\', \'python-gettext\', \'pytz\', \'RestrictedPython\', \'roman\', \'six\',\n+ \'soupsieve\', \'transaction\', \'waitress\', \'WebOb\', \'WebTest\', \'WSGIProxy2\',\n+ \'z3c.pt\', \'zc.lockfile\', \'ZConfig\', \'zExceptions\', \'ZODB\', \'zodbpickle\',\n+ \'zope.annotation\', \'zope.browser\', \'zope.browsermenu\', \'zope.browserpage\',\n+ \'zope.browserresource\', \'zope.cachedescriptors\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.contentprovider\',\n+ \'zope.contenttype\', \'zope.datetime\', \'zope.deferredimport\',\n+ \'zope.deprecation\', \'zope.dottedname\', \'zope.event\', \'zope.exceptions\',\n+ \'zope.filerepresentation\', \'zope.globalrequest\', \'zope.hookable\',\n+ \'zope.i18n\', \'zope.i18nmessageid\', \'zope.interface\', \'zope.lifecycleevent\',\n+ \'zope.location\', \'zope.pagetemplate\', \'zope.processlifetime\', \'zope.proxy\',\n+ \'zope.ptresource\', \'zope.publisher\', \'zope.schema\', \'zope.security\',\n+ \'zope.sequencesort\', \'zope.site\', \'zope.size\', \'zope.structuredtext\',\n+ \'zope.tal\', \'zope.tales\', \'zope.testbrowser\', \'zope.testing\',\n+ \'zope.traversing\', \'zope.viewlet\'\n+]\n+\'Products.CMFCore\' = [\n+ \'docutils\', \'five.localsitemanager\', \'Missing\', \'Products.BTreeFolder2\',\n+ \'Products.GenericSetup\', \'Products.MailHost\', \'Products.PythonScripts\',\n+ \'Products.StandardCacheManagers\', \'Products.ZCatalog\', \'Record\',\n+ \'zope.sendmail\', \'Zope\'\n+]\n+\'plone.base\' = [\n+ \'plone.batching\', \'plone.registry\', \'plone.schema\',\'plone.z3cform\',\n+ \'Products.CMFCore\', \'Products.CMFDynamicViewFTI\',\n+]\n+python-dateutil = [\'dateutil\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 3ee2840..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,9 +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\n-\n-[bdist_wheel]\n-universal = 1\n-\n-[zest.releaser]\n-create-wheel = yes\ndiff --git a/setup.py b/setup.py\nindex 05d6d46..9234b93 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,54 +1,47 @@\n-# -*- coding: utf-8 -*-\n from setuptools import find_packages\n from setuptools import setup\n \n \n-version = \'1.4.3.dev0\'\n+version = "2.0.0.dev0"\n \n setup(\n- name=\'plone.event\',\n+ name="plone.event",\n version=version,\n description="Event and calendaring related tools not bound to Plone",\n- long_description=(\n- open("README.rst").read() + "\\n" + open(("CHANGES.rst")).read()\n- ),\n+ long_description=(open("README.rst").read() + "\\n" + open("CHANGES.rst").read()),\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n "Framework :: Plone",\n- "Framework :: Plone :: 5.1",\n- "Framework :: Plone :: 5.2",\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 :: 2.7",\n- "Programming Language :: Python :: 3.6",\n- "Programming Language :: Python :: 3.7",\n "Programming Language :: Python :: 3.8",\n "Programming Language :: Python :: 3.9",\n "Programming Language :: Python :: 3.10",\n "Programming Language :: Python :: 3.11",\n ],\n- keywords=\'Plone calendar calendaring event recurring\',\n- author=\'Plone Foundation\',\n- author_email=\'plone-developers@lists.sourceforge.net\',\n- url=\'https://github.com/plone/plone.event\',\n- license=\'GPL\',\n+ keywords="Plone calendar calendaring event recurring",\n+ author="Plone Foundation",\n+ author_email="plone-developers@lists.sourceforge.net",\n+ url="https://github.com/plone/plone.event",\n+ license="GPL",\n packages=find_packages(),\n- namespace_packages=[\'plone\'],\n+ namespace_packages=["plone"],\n include_package_data=True,\n zip_safe=False,\n- python_requires=\'>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*\',\n+ python_requires=">=3.8",\n install_requires=[\n- \'setuptools\',\n- \'python-dateutil\', # >4.0.2\n- \'pytz\',\n- \'zope.component\',\n- \'zope.interface\',\n+ "setuptools",\n+ "python-dateutil", # >4.0.2\n+ "pytz",\n+ "zope.component",\n+ "zope.interface",\n ],\n- extras_require={\'test\': [\n- \'DateTime\',\n- \'mock\',\n- \'zope.configuration\',\n- ], },\n+ extras_require={\n+ "test": [\n+ "DateTime",\n+ "zope.configuration",\n+ ],\n+ },\n )\ndiff --git a/tox.ini b/tox.ini\nindex 5b2fe14..c4521cf 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -1,10 +1,68 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [tox]\n+# We need 4.4.0 for constrain_package_deps.\n+min_version = 4.4.0\n envlist =\n- py27,py36,py37,py38\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+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --all --test-path={toxinidir} -s plone.event {posargs}\n+extras =\n+ test\n+\n+[testenv:coverage]\n+usedevelop = true\n+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n deps =\n+ coverage\n zope.testrunner\n- .[test]\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n commands =\n- zope-testrunner --test-path=. {posargs:-pvc}\n+ coverage run {envbindir}/zope-testrunner --all --test-path={toxinidir} -s plone.event {posargs}\n+ coverage report -m --format markdown\n+extras =\n+ test\n' +M src/plone/__init__.py +M src/plone/folder/__init__.py +M src/plone/folder/configure.zcml +M src/plone/folder/default.py +M src/plone/folder/interfaces.py +M src/plone/folder/nogopip.py +M src/plone/folder/ordered.py +M src/plone/folder/partial.py +M src/plone/folder/testing.py +M src/plone/folder/tests/benchmarks.py +M src/plone/folder/tests/test_dict_interface.py +M src/plone/folder/tests/test_integration.py +M src/plone/folder/tests/test_ordering_adapters.py +M src/plone/folder/tests/test_ordersupport.py +M src/plone/folder/tests/test_partialordering.py +M src/plone/folder/tests/test_unorderedordering.py +M src/plone/folder/tests/test_webdav.py +M src/plone/folder/tests/utils.py +M src/plone/folder/unordered.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..1b2346d\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 = "5cc689e5"\ndiff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml\nnew file mode 100644\nindex 0000000..fdafec1\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.3.0\n+ hooks:\n+ - id: black\n+- repo: https://github.com/collective/zpretty\n+ rev: 3.0.3\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.4\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 2dfa069..f6c08ff 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -293,7 +293,7 @@ Fixes:\n dict-like API.\n [optilude]\n \n-- Fix issue with removing non-orderable content for partial ordering suppport.\n+- Fix issue with removing non-orderable content for partial ordering support.\n [witsch]\n \n - Fix ``getObjectPosition`` to return a value representing "no position" for\ndiff --git a/news/1.breaking b/news/1.breaking\nnew file mode 100644\nindex 0000000..174ecbf\n--- /dev/null\n+++ b/news/1.breaking\n@@ -0,0 +1,2 @@\n+Drop python 2.7 support.\n+[gforcada]\ndiff --git a/news/5cc689e5.internal b/news/5cc689e5.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/5cc689e5.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 05b615d..9054002 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,65 @@ 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+ # ExtensionClass own provided namespaces\n+ \'ExtensionClass\', \'ComputedAttribute\', \'MethodObject\',\n+ # Zope dependencies\n+ \'AccessControl\', \'Acquisition\', \'AuthEncoding\', \'beautifulsoup4\', \'BTrees\',\n+ \'cffi\', \'Chameleon\', \'DateTime\', \'DocumentTemplate\',\n+ \'MultiMapping\', \'multipart\', \'PasteDeploy\', \'Persistence\', \'persistent\',\n+ \'pycparser\', \'python-gettext\', \'pytz\', \'RestrictedPython\', \'roman\', \'six\',\n+ \'soupsieve\', \'transaction\', \'waitress\', \'WebOb\', \'WebTest\', \'WSGIProxy2\',\n+ \'z3c.pt\', \'zc.lockfile\', \'ZConfig\', \'zExceptions\', \'ZODB\', \'zodbpickle\',\n+ \'zope.annotation\', \'zope.browser\', \'zope.browsermenu\', \'zope.browserpage\',\n+ \'zope.browserresource\', \'zope.cachedescriptors\', \'zope.component\',\n+ \'zope.configuration\', \'zope.container\', \'zope.contentprovider\',\n+ \'zope.contenttype\', \'zope.datetime\', \'zope.deferredimport\',\n+ \'zope.deprecation\', \'zope.dottedname\', \'zope.event\', \'zope.exceptions\',\n+ \'zope.filerepresentation\', \'zope.globalrequest\', \'zope.hookable\',\n+ \'zope.i18n\', \'zope.i18nmessageid\', \'zope.interface\', \'zope.lifecycleevent\',\n+ \'zope.location\', \'zope.pagetemplate\', \'zope.processlifetime\', \'zope.proxy\',\n+ \'zope.ptresource\', \'zope.publisher\', \'zope.schema\', \'zope.security\',\n+ \'zope.sequencesort\', \'zope.site\', \'zope.size\', \'zope.structuredtext\',\n+ \'zope.tal\', \'zope.tales\', \'zope.testbrowser\', \'zope.testing\',\n+ \'zope.traversing\', \'zope.viewlet\'\n+]\n+\'Products.CMFCore\' = [\n+ \'docutils\', \'five.localsitemanager\', \'Missing\', \'Products.BTreeFolder2\',\n+ \'Products.GenericSetup\', \'Products.MailHost\', \'Products.PythonScripts\',\n+ \'Products.StandardCacheManagers\', \'Products.ZCatalog\', \'Record\',\n+ \'zope.sendmail\', \'Zope\'\n+]\n+\'plone.base\' = [\n+ \'plone.batching\', \'plone.registry\', \'plone.schema\',\'plone.z3cform\',\n+ \'Products.CMFCore\', \'Products.CMFDynamicViewFTI\',\n+]\n+python-dateutil = [\'dateutil\']\n+\'Products.ZCatalog\' = [\'Products.PluginIndexes\']\ndiff --git a/setup.cfg b/setup.cfg\nindex 3e97765..0da8f8f 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -1,9 +1,23 @@\n-[check-manifest]\n-ignore =\n- bootstrap.py\n- *.cfg\n-\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-[bdist_wheel]\n-universal = 1\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 b925890..07c1bd2 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -1,18 +1,19 @@\n-from setuptools import setup, find_packages\n+from setuptools import find_packages\n+from setuptools import setup\n \n-version = \'3.1.1.dev0\'\n+\n+version = "3.1.1.dev0"\n \n setup(\n- name=\'plone.folder\',\n+ name="plone.folder",\n version=version,\n- description=\'BTree-based folder implementation with order support\',\n- long_description=(open("README.rst").read() + "\\n" +\n- open("CHANGES.rst").read()),\n+ description="BTree-based folder implementation with order support",\n+ long_description=(open("README.rst").read() + "\\n" + open("CHANGES.rst").read()),\n classifiers=[\n "Development Status :: 5 - Production/Stable",\n "Environment :: Web Environment",\n "Framework :: Plone",\n- "Framework :: Plone :: 5.2",\n+ "Framework :: Plone :: 6.0",\n "Framework :: Plone :: Core",\n "Framework :: Zope2",\n "Framework :: Zope :: 4",\n@@ -22,38 +23,32 @@\n "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",\n "Operating System :: OS Independent",\n "Programming Language :: Python",\n- "Programming Language :: Python :: 2.7",\n- "Programming Language :: Python :: 3.6",\n- "Programming Language :: Python :: 3.7",\n "Programming Language :: Python :: 3.8",\n+ "Programming Language :: Python :: 3.9",\n+ "Programming Language :: Python :: 3.10",\n+ "Programming Language :: Python :: 3.11",\n ],\n- keywords=\'folder btree order\',\n- author=\'Plone Foundation\',\n- author_email=\'plone-developers@lists.sourceforge.net\',\n- url=\'https://pypi.org/project/plone.folder\',\n- license=\'GPL version 2\',\n- packages=find_packages(\'src\'),\n- package_dir={\'\': \'src\'},\n- namespace_packages=[\'plone\'],\n+ keywords="folder btree order",\n+ author="Plone Foundation",\n+ author_email="plone-developers@lists.sourceforge.net",\n+ url="https://pypi.org/project/plone.folder",\n+ license="GPL version 2",\n+ packages=find_packages("src"),\n+ package_dir={"": "src"},\n+ namespace_packages=["plone"],\n include_package_data=True,\n- platforms=\'Any\',\n+ platforms="Any",\n zip_safe=False,\n+ python_requires=">=3.8",\n install_requires=[\n- \'plone.memoize\',\n- \'Products.BTreeFolder2\',\n- \'Products.CMFCore\',\n- \'Products.ZCatalog\',\n- \'setuptools\',\n- \'six\',\n- \'zope.annotation\',\n- \'zope.component\',\n- \'zope.container\',\n- \'zope.interface\',\n- \'Zope2\',\n+ "Products.CMFCore",\n+ "Products.ZCatalog",\n+ "setuptools",\n ],\n extras_require={\n- \'test\': [\n- \'profilehooks\',\n+ "test": [\n+ "plone.app.testing",\n+ "profilehooks",\n ]\n },\n )\ndiff --git a/src/plone/__init__.py b/src/plone/__init__.py\nindex 68c04af..5284146 100644\n--- a/src/plone/__init__.py\n+++ b/src/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/src/plone/folder/__init__.py b/src/plone/folder/__init__.py\nindex 40a96af..e69de29 100644\n--- a/src/plone/folder/__init__.py\n+++ b/src/plone/folder/__init__.py\n@@ -1 +0,0 @@\n-# -*- coding: utf-8 -*-\ndiff --git a/src/plone/folder/configure.zcml b/src/plone/folder/configure.zcml\nindex 490a8f4..ce40737 100644\n--- a/src/plone/folder/configure.zcml\n+++ b/src/plone/folder/configure.zcml\n@@ -1,11 +1,16 @@\n \n+ i18n_domain="plone.folder"\n+ >\n \n- \n- \n- \n+ \n+ \n+ \n \n-\n\\ No newline at end of file\n+\ndiff --git a/src/plone/folder/default.py b/src/plone/folder/default.py\nindex 84d4c8d..de3f086 100644\n--- a/src/plone/folder/default.py\n+++ b/src/plone/folder/default.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from BTrees.OIBTree import OIBTree\n from persistent.list import PersistentList\n from plone.folder.interfaces import IExplicitOrdering\n@@ -8,14 +7,12 @@\n from zope.container.contained import notifyContainerModified\n from zope.interface import implementer\n \n-import six\n-\n \n @implementer(IExplicitOrdering)\n @adapter(IOrderableFolder)\n-class DefaultOrdering(object):\n- """ This implementation uses annotations to store the order on the\n- object, and supports explicit ordering. """\n+class DefaultOrdering:\n+ """This implementation uses annotations to store the order on the\n+ object, and supports explicit ordering."""\n \n ORDER_KEY = "plone.folder.ordered.order"\n POS_KEY = "plone.folder.ordered.pos"\n@@ -24,14 +21,14 @@ def __init__(self, context):\n self.context = context\n \n def notifyAdded(self, obj_id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n order = self._order(True)\n pos = self._pos(True)\n order.append(obj_id)\n pos[obj_id] = len(order) - 1\n \n def notifyRemoved(self, obj_id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n order = self._order()\n pos = self._pos()\n try:\n@@ -44,24 +41,18 @@ def notifyRemoved(self, obj_id):\n for count, obj_id in enumerate(order):\n pos[obj_id] = count\n \n- def moveObjectsByDelta(\n- self,\n- ids,\n- delta,\n- subset_ids=None,\n- suppress_events=False\n- ):\n- """ see interfaces.py """\n+ def moveObjectsByDelta(self, ids, delta, subset_ids=None, suppress_events=False):\n+ """see interfaces.py"""\n order = self._order()\n pos = self._pos()\n min_position = 0\n- if isinstance(ids, six.string_types):\n+ if isinstance(ids, str):\n ids = [ids]\n if subset_ids is None:\n subset_ids = self.idsInOrder()\n elif not isinstance(subset_ids, list):\n subset_ids = list(subset_ids)\n- if delta > 0: # unify moving direction\n+ if delta > 0: # unify moving direction\n ids = reversed(ids)\n subset_ids.reverse()\n counter = 0\n@@ -94,41 +85,37 @@ def moveObjectsByDelta(\n pos[obj_id] = i\n idx += 1\n except KeyError:\n- raise ValueError(\n- \'No object with id "{0:s}" exists.\'.format(obj_id)\n- )\n+ raise ValueError(f\'No object with id "{obj_id:s}" exists.\')\n if not suppress_events:\n notifyContainerModified(self.context)\n return counter\n \n def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -delta, subset_ids)\n \n def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, delta, subset_ids)\n \n def moveObjectsToTop(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -len(self._order()), subset_ids)\n \n def moveObjectsToBottom(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, len(self._order()), subset_ids)\n \n def moveObjectToPosition(self, obj_id, position, suppress_events=False):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n delta = position - self.getObjectPosition(obj_id)\n if delta:\n return self.moveObjectsByDelta(\n- obj_id,\n- delta,\n- suppress_events=suppress_events\n+ obj_id, delta, suppress_events=suppress_events\n )\n \n def orderObjects(self, key=None, reverse=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n if key is None and not reverse:\n return -1\n order = self._order()\n@@ -138,11 +125,13 @@ def orderObjects(self, key=None, reverse=None):\n # Simply reverse the current ordering.\n order.reverse()\n else:\n+\n def keyfn(obj_id):\n attr = getattr(self.context._getOb(obj_id), key)\n if callable(attr):\n return attr()\n return attr\n+\n # order.sort(cmd=None, key=keyfn, reverse=bool(reverse))\n order = sorted(order, key=keyfn, reverse=bool(reverse))\n self._set_order(order)\n@@ -151,15 +140,18 @@ def keyfn(obj_id):\n return -1\n \n def getObjectPosition(self, obj_id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n pos = self._pos()\n if obj_id in pos:\n return pos[obj_id]\n- raise ValueError(\'No object with id "{0:s}" exists in "{1:s}".\'.format(\n- obj_id, \'/\'.join(self.context.getPhysicalPath())))\n+ raise ValueError(\n+ \'No object with id "{:s}" exists in "{:s}".\'.format(\n+ obj_id, "/".join(self.context.getPhysicalPath())\n+ )\n+ )\n \n def idsInOrder(self):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return list(self._order())\n \n def __getitem__(self, index):\ndiff --git a/src/plone/folder/interfaces.py b/src/plone/folder/interfaces.py\nindex 4f5fef4..d3aab8d 100644\n--- a/src/plone/folder/interfaces.py\n+++ b/src/plone/folder/interfaces.py\n@@ -1,75 +1,74 @@\n-# -*- coding: utf-8 -*-\n from zope.interface import Interface\n \n \n class IOrderable(Interface):\n- """ Marker interface for orderable portal content """\n+ """Marker interface for orderable portal content"""\n \n \n class IFolder(Interface):\n- """ Marker interface for Plone-like folders """\n+ """Marker interface for Plone-like folders"""\n \n \n class IOrderableFolder(IFolder):\n- """ A Plone-like folder with ordering support """\n+ """A Plone-like folder with ordering support"""\n \n def getOrdering():\n- """ return the currently active ordering adapter for this folder """\n+ """return the currently active ordering adapter for this folder"""\n \n- def setOrdering(ordering=u\'\'):\n- """ (re)set ordering adapter to be used for this folder """\n+ def setOrdering(ordering=""):\n+ """(re)set ordering adapter to be used for this folder"""\n \n \n class IOrdering(Interface):\n- """ An adapter providing ordering operations on its context folder.\n+ """An adapter providing ordering operations on its context folder.\n \n- The OrderedBTreeFolderBase mix-in class will adapt self (the\n- folder) to this interface when trying to get object position or\n- find the order of items. There is a default implementation, but\n- you can provide a different policy.\n+ The OrderedBTreeFolderBase mix-in class will adapt self (the\n+ folder) to this interface when trying to get object position or\n+ find the order of items. There is a default implementation, but\n+ you can provide a different policy.\n \n- Your adapter (which should still adapt to IOrdered) can\n- optionally provide IExplicitOrdering, defined below. This is\n- used to support explicit ordering, e.g. through a UI. """\n+ Your adapter (which should still adapt to IOrdered) can\n+ optionally provide IExplicitOrdering, defined below. This is\n+ used to support explicit ordering, e.g. through a UI."""\n \n def notifyAdded(obj_id):\n- """ Inform the ordering implementation that an item was added """\n+ """Inform the ordering implementation that an item was added"""\n \n def notifyRemoved(obj_id):\n- """ Inform the ordering implementation that an item was removed """\n+ """Inform the ordering implementation that an item was removed"""\n \n def getObjectPosition(obj_id):\n- """ Get the position of the given object id """\n+ """Get the position of the given object id"""\n \n def idsInOrder():\n- """ Return all object ids, in the correct order """\n+ """Return all object ids, in the correct order"""\n \n \n class IExplicitOrdering(IOrdering):\n- """ An adapter allowing explicit ordering """\n+ """An adapter allowing explicit ordering"""\n \n def moveObjectsByDelta(ids, delta, subset_ids=None, suppress_events=False):\n- """ Move the specified ids (a sequence, or a single string id)\n- by the given delta (a positive or negative number). By\n- default, this moves the objects within the whole set of\n- sub-items in the context container, but if subset_ids is\n- specified, it gives a subset of ids to consider.\n- Should return the number of objects that changed position. """\n+ """Move the specified ids (a sequence, or a single string id)\n+ by the given delta (a positive or negative number). By\n+ default, this moves the objects within the whole set of\n+ sub-items in the context container, but if subset_ids is\n+ specified, it gives a subset of ids to consider.\n+ Should return the number of objects that changed position."""\n \n def moveObjectsUp(ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects up by delta in container. """\n+ """Move specified sub-objects up by delta in container."""\n \n def moveObjectsDown(ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects down by delta in container. """\n+ """Move specified sub-objects down by delta in container."""\n \n def moveObjectsToTop(ids, subset_ids=None):\n- """ Move specified sub-objects to top of container. """\n+ """Move specified sub-objects to top of container."""\n \n def moveObjectsToBottom(ids, subset_ids=None):\n- """ Move specified sub-objects to bottom of container. """\n+ """Move specified sub-objects to bottom of container."""\n \n def moveObjectToPosition(obj_id, position, suppress_events=False):\n- """ Move specified object to absolute position. """\n+ """Move specified object to absolute position."""\n \n def orderObjects(key, reverse=None):\n- """ Order sub-objects by key and direction. """\n+ """Order sub-objects by key and direction."""\ndiff --git a/src/plone/folder/nogopip.py b/src/plone/folder/nogopip.py\nindex 24d6d2d..d8b25f4 100644\n--- a/src/plone/folder/nogopip.py\n+++ b/src/plone/folder/nogopip.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import aq_base\n from App.special_dtml import DTMLFile\n from inspect import currentframe\n@@ -10,6 +9,7 @@\n from zope.component import getUtility\n from zope.interface import implementer\n \n+\n logger = getLogger(__name__)\n \n \n@@ -20,7 +20,7 @@ def traverse(base, path):\n returns: content at the end or None\n """\n current = base\n- for cid in path.split(\'/\'):\n+ for cid in path.split("/"):\n if not cid:\n continue\n try:\n@@ -32,7 +32,7 @@ def traverse(base, path):\n \n @implementer(IPluggableIndex)\n class StubIndex(SimpleItem):\n- """ stub catalog index doing nothing """\n+ """stub catalog index doing nothing"""\n \n def __init__(self, id, *args, **kw):\n self.id = id\n@@ -64,15 +64,15 @@ def clear(self):\n \n @implementer(ISortIndex)\n class GopipIndex(StubIndex):\n- """ fake index for sorting against `getObjPositionInParent` """\n+ """fake index for sorting against `getObjPositionInParent`"""\n \n- meta_type = \'GopipIndex\'\n- manage_options = dict(label=\'Settings\', action=\'manage_main\'),\n+ meta_type = "GopipIndex"\n+ manage_options = (dict(label="Settings", action="manage_main"),)\n \n keyForDocument = 42\n \n def __init__(self, id, extra=None, caller=None):\n- super(GopipIndex, self).__init__(id)\n+ super().__init__(id)\n self.catalog = aq_base(caller._catalog)\n \n def __len__(self):\n@@ -87,7 +87,7 @@ def documentToKeyMap(self):\n # results themselves. luckily this is only ever called from\n # `sortResults`, so we can get it form there. oh, and lurker\n # says this won\'t work in jython, though! :)\n- rs = currentframe().f_back.f_locals[\'rs\']\n+ rs = currentframe().f_back.f_locals["rs"]\n rids = {}\n items = []\n containers = {}\n@@ -95,17 +95,17 @@ def documentToKeyMap(self):\n root = getUtility(ISiteRoot).getPhysicalRoot()\n for rid in rs:\n path = getpath(rid)\n- parent, id = path.rsplit(\'/\', 1)\n+ parent, id = path.rsplit("/", 1)\n container = containers.get(parent)\n if container is None:\n containers[parent] = container = traverse(root, parent)\n- rids[id] = rid # remember in case of single folder\n+ rids[id] = rid # remember in case of single folder\n items.append((rid, container, id)) # or else for deferred lookup\n pos = {}\n if len(containers) == 1:\n # the usual "all from one folder" case can be optimized\n folder = list(containers.values())[0]\n- if getattr(aq_base(folder), \'getOrdering\', None):\n+ if getattr(aq_base(folder), "getOrdering", None):\n ids = folder.getOrdering().idsInOrder()\n else:\n # site root or old folders\n@@ -117,7 +117,7 @@ def documentToKeyMap(self):\n return pos\n # otherwise the entire map needs to be constructed...\n for rid, container, id in items:\n- if getattr(aq_base(container), \'getObjectPosition\', None):\n+ if getattr(aq_base(container), "getObjectPosition", None):\n pos[rid] = container.getObjectPosition(id)\n else:\n # fallback for unordered folders\n@@ -125,21 +125,11 @@ def documentToKeyMap(self):\n return pos\n \n \n-manage_addGopipForm = DTMLFile(\'dtml/addGopipIndex\', globals())\n+manage_addGopipForm = DTMLFile("dtml/addGopipIndex", globals())\n \n \n-def manage_addGopipIndex(\n- self,\n- identifier,\n- REQUEST=None,\n- RESPONSE=None,\n- URL3=None\n-):\n- """ add a fake gopip index """\n+def manage_addGopipIndex(self, identifier, REQUEST=None, RESPONSE=None, URL3=None):\n+ """add a fake gopip index"""\n return self.manage_addIndex(\n- identifier,\n- \'GopipIndex\',\n- REQUEST=REQUEST,\n- RESPONSE=RESPONSE,\n- URL1=URL3\n+ identifier, "GopipIndex", REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3\n )\ndiff --git a/src/plone/folder/ordered.py b/src/plone/folder/ordered.py\nindex fac2cd6..72edf91 100644\n--- a/src/plone/folder/ordered.py\n+++ b/src/plone/folder/ordered.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from AccessControl import ClassSecurityInfo\n from AccessControl.Permissions import access_contents_information\n from AccessControl.Permissions import manage_properties\n@@ -14,6 +13,8 @@\n from zope.component import getAdapter\n from zope.component import queryAdapter\n from zope.interface import implementer\n+\n+\n try:\n from ZTUtils.Lazy import LazyMap\n except ImportError:\n@@ -29,29 +30,29 @@\n \n @implementer(IOrderedContainer, IOrderableFolder, IAttributeAnnotatable)\n class OrderedBTreeFolderBase(BTreeFolder2Base):\n- """ BTree folder base class with ordering support. The ordering\n- is done by a named adapter (to IOrdering), which makes the policy\n- changeable. """\n+ """BTree folder base class with ordering support. The ordering\n+ is done by a named adapter (to IOrdering), which makes the policy\n+ changeable."""\n \n- _ordering = u\'\' # name of adapter defining ordering policy\n+ _ordering = "" # name of adapter defining ordering policy\n \n security = ClassSecurityInfo()\n \n def __bool__(self):\n- """ a folder is something, even if it\'s empty """\n+ """a folder is something, even if it\'s empty"""\n return True\n \n @security.protected(access_contents_information)\n def getOrdering(self):\n- """ return the currently active ordering adapter for this folder """\n+ """return the currently active ordering adapter for this folder"""\n adapter = queryAdapter(self, IOrdering, name=self._ordering)\n if adapter is None:\n adapter = getAdapter(self, IOrdering)\n return adapter\n \n @security.protected(manage_properties)\n- def setOrdering(self, ordering=u\'\'):\n- """ (re)set ordering adapter to be used for this folder """\n+ def setOrdering(self, ordering=""):\n+ """(re)set ordering adapter to be used for this folder"""\n if ordering:\n # make sure the adapter exists...\n getAdapter(self, IOrdering, name=ordering)\n@@ -60,30 +61,30 @@ def setOrdering(self, ordering=u\'\'):\n # IObjectManager\n \n def _getOb(self, id, default=_marker):\n- """ Return the named object from the folder. """\n+ """Return the named object from the folder."""\n try:\n- return super(OrderedBTreeFolderBase, self)._getOb(id, default)\n+ return super()._getOb(id, default)\n except KeyError as e:\n raise AttributeError(e)\n \n def _setOb(self, id, object):\n- """ Store the named object in the folder. """\n- super(OrderedBTreeFolderBase, self)._setOb(id, object)\n- self.getOrdering().notifyAdded(id) # notify the ordering adapter\n+ """Store the named object in the folder."""\n+ super()._setOb(id, object)\n+ self.getOrdering().notifyAdded(id) # notify the ordering adapter\n \n def _delOb(self, id):\n- """ Remove the named object from the folder. """\n- super(OrderedBTreeFolderBase, self)._delOb(id)\n- self.getOrdering().notifyRemoved(id) # notify the ordering adapter\n+ """Remove the named object from the folder."""\n+ super()._delOb(id)\n+ self.getOrdering().notifyRemoved(id) # notify the ordering adapter\n \n def objectIds(self, spec=None, ordered=True):\n if not ordered:\n- return super(OrderedBTreeFolderBase, self).objectIds(spec)\n+ return super().objectIds(spec)\n ordering = self.getOrdering()\n if spec is None:\n return ordering.idsInOrder()\n else:\n- ids = super(OrderedBTreeFolderBase, self).objectIds(spec)\n+ ids = super().objectIds(spec)\n idxs = []\n for id in ids:\n idxs.append((ordering.getObjectPosition(id), id))\n@@ -99,19 +100,20 @@ def objectItems(self, spec=None):\n # Returns a list of (id, subobject) tuples of the current object.\n # If \'spec\' is specified, returns only objects whose meta_type match\n # \'spec\'\n- return LazyMap(lambda id, _getOb=self._getOb: (id, _getOb(id)),\n- self.objectIds(spec))\n+ return LazyMap(\n+ lambda id, _getOb=self._getOb: (id, _getOb(id)), self.objectIds(spec)\n+ )\n \n # IOrderSupport - mostly deprecated, use the adapter directly instead\n \n @security.protected(access_contents_information)\n def getObjectPosition(self, id):\n- """ Get the position of an object by its id. """\n+ """Get the position of an object by its id."""\n return self.getOrdering().getObjectPosition(id)\n \n @security.protected(manage_properties)\n def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects up by delta in container. """\n+ """Move specified sub-objects up by delta in container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsUp(ids, delta, subset_ids)\n@@ -120,7 +122,7 @@ def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n \n @security.protected(manage_properties)\n def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n- """ Move specified sub-objects down by delta in container. """\n+ """Move specified sub-objects down by delta in container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsDown(ids, delta, subset_ids)\n@@ -129,7 +131,7 @@ def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n \n @security.protected(manage_properties)\n def moveObjectsToTop(self, ids, subset_ids=None):\n- """ Move specified sub-objects to top of container. """\n+ """Move specified sub-objects to top of container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsToTop(ids, subset_ids)\n@@ -138,7 +140,7 @@ def moveObjectsToTop(self, ids, subset_ids=None):\n \n @security.protected(manage_properties)\n def moveObjectsToBottom(self, ids, subset_ids=None):\n- """ Move specified sub-objects to bottom of container. """\n+ """Move specified sub-objects to bottom of container."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectsToBottom(ids, subset_ids)\n@@ -147,7 +149,7 @@ def moveObjectsToBottom(self, ids, subset_ids=None):\n \n @security.protected(ModifyPortalContent)\n def moveObject(self, id, position):\n- """ Move specified object to absolute position. """\n+ """Move specified object to absolute position."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectToPosition(id, position)\n@@ -156,7 +158,7 @@ def moveObject(self, id, position):\n \n @security.protected(manage_properties)\n def moveObjectToPosition(self, id, position, suppress_events=False):\n- """ Move specified object to absolute position. """\n+ """Move specified object to absolute position."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.moveObjectToPosition(id, position, suppress_events)\n@@ -164,24 +166,17 @@ def moveObjectToPosition(self, id, position, suppress_events=False):\n return 0\n \n @security.protected(manage_properties)\n- def moveObjectsByDelta(\n- self, ids, delta, subset_ids=None, suppress_events=False\n- ):\n- """ Move specified sub-objects by delta. """\n+ def moveObjectsByDelta(self, ids, delta, subset_ids=None, suppress_events=False):\n+ """Move specified sub-objects by delta."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n- return ordering.moveObjectsByDelta(\n- ids,\n- delta,\n- subset_ids,\n- suppress_events\n- )\n+ return ordering.moveObjectsByDelta(ids, delta, subset_ids, suppress_events)\n else:\n return 0\n \n @security.protected(manage_properties)\n def orderObjects(self, key=None, reverse=None):\n- """ Order sub-objects by key and direction. """\n+ """Order sub-objects by key and direction."""\n ordering = self.getOrdering()\n if IExplicitOrdering.providedBy(ordering):\n return ordering.orderObjects(key, reverse)\n@@ -194,19 +189,15 @@ def iterkeys(self):\n return iter(self.objectIds())\n \n def manage_renameObject(self, id, new_id, REQUEST=None):\n- """ Rename a particular sub-object without changing its position. """\n+ """Rename a particular sub-object without changing its position."""\n old_position = self.getObjectPosition(id)\n- result = super(OrderedBTreeFolderBase, self).manage_renameObject(\n- id,\n- new_id,\n- REQUEST\n- )\n+ result = super().manage_renameObject(id, new_id, REQUEST)\n if old_position is None:\n return result\n self.moveObjectToPosition(new_id, old_position, suppress_events=True)\n- reindex = getattr(self._getOb(new_id), \'reindexObject\', None)\n+ reindex = getattr(self._getOb(new_id), "reindexObject", None)\n if reindex is not None:\n- reindex(idxs=[\'getObjPositionInParent\'])\n+ reindex(idxs=["getObjPositionInParent"])\n return result\n \n # Dict interface\n@@ -226,11 +217,14 @@ def __getitem__(self, key):\n return value\n \n # WebDAV PUT support\n- if hasattr(self, \'REQUEST\'):\n+ if hasattr(self, "REQUEST"):\n request = self.REQUEST\n- method = request.get(\'REQUEST_METHOD\', \'GET\')\n- if (HAS_WEBDAV and getattr(request, \'maybe_webdav_client\', False)\n- and method not in (\'GET\', \'POST\')):\n+ method = request.get("REQUEST_METHOD", "GET")\n+ if (\n+ HAS_WEBDAV\n+ and getattr(request, "maybe_webdav_client", False)\n+ and method not in ("GET", "POST")\n+ ):\n return NullResource(self, key, request).__of__(self)\n raise KeyError(key)\n \n@@ -241,11 +235,11 @@ def __getitem__(self, key):\n \n \n class CMFOrderedBTreeFolderBase(OrderedBTreeFolderBase, PortalFolderBase):\n- """ BTree folder for CMF sites, with ordering support. The ordering\n- is done by adapter (to IOrdering), which makes the policy\n- changeable. """\n+ """BTree folder for CMF sites, with ordering support. The ordering\n+ is done by adapter (to IOrdering), which makes the policy\n+ changeable."""\n \n- def __init__(self, id, title=\'\'):\n+ def __init__(self, id, title=""):\n PortalFolderBase.__init__(self, id, title)\n BTreeFolder2Base.__init__(self, id)\n \ndiff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex 5ef625d..d1ab5d0 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -1,23 +1,21 @@\n from Acquisition import aq_base\n-from zope.interface import implementer\n-from zope.component import adapts\n-from zope.container.contained import notifyContainerModified\n-\n+from plone.folder.interfaces import IExplicitOrdering\n from plone.folder.interfaces import IOrderable\n from plone.folder.interfaces import IOrderableFolder\n-from plone.folder.interfaces import IExplicitOrdering\n-\n-import six\n+from zope.component import adapts\n+from zope.container.contained import notifyContainerModified\n+from zope.interface import implementer\n \n \n-ORDER_ATTR = \'_objectordering\'\n+ORDER_ATTR = "_objectordering"\n \n \n @implementer(IExplicitOrdering)\n-class PartialOrdering(object):\n- """ this implementation uses a list to store order information on a\n- regular attribute of the folderish object; explicit ordering\n- is supported """\n+class PartialOrdering:\n+ """this implementation uses a list to store order information on a\n+ regular attribute of the folderish object; explicit ordering\n+ is supported"""\n+\n adapts(IOrderableFolder)\n \n def __init__(self, context):\n@@ -39,24 +37,24 @@ def order(self, value):\n setattr(context, ORDER_ATTR, value)\n \n def notifyAdded(self, id):\n- """ see interfaces.py """\n- assert not id in self.order\n+ """see interfaces.py"""\n+ assert id not in self.order\n context = aq_base(self.context)\n obj = context._getOb(id)\n if IOrderable.providedBy(obj):\n self.order.append(id)\n- self.context._p_changed = True # the order was changed\n+ self.context._p_changed = True # the order was changed\n \n def notifyRemoved(self, id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n try:\n self.order.remove(id)\n- self.context._p_changed = True # the order was changed\n- except ValueError: # removing non-orderable items is okay\n+ self.context._p_changed = True # the order was changed\n+ except ValueError: # removing non-orderable items is okay\n pass\n \n def idsInOrder(self, onlyOrderables=False):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n ordered = list(self.order)\n ordered_set = set(ordered)\n if not onlyOrderables:\n@@ -66,17 +64,16 @@ def idsInOrder(self, onlyOrderables=False):\n ordered.append(id)\n return ordered\n \n- def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n- suppress_events=False):\n- """ see interfaces.py """\n+ def moveObjectsByDelta(self, ids, delta, subset_ids=None, suppress_events=False):\n+ """see interfaces.py"""\n min_position = 0\n- if isinstance(ids, six.string_types):\n+ if isinstance(ids, str):\n ids = [ids]\n if subset_ids is None:\n subset_ids = self.idsInOrder(onlyOrderables=True)\n elif not isinstance(subset_ids, list):\n subset_ids = list(subset_ids)\n- if delta > 0: # unify moving direction\n+ if delta > 0: # unify moving direction\n ids = reversed(ids)\n subset_ids.reverse()\n counter = 0\n@@ -107,38 +104,39 @@ def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n except KeyError:\n raise ValueError(\'No object with id "%s" exists.\' % id)\n if idx > 0:\n- self.context._p_changed = True # the order was changed\n+ self.context._p_changed = True # the order was changed\n if not suppress_events:\n notifyContainerModified(self.context)\n return counter\n \n def moveObjectsUp(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -delta, subset_ids)\n \n def moveObjectsDown(self, ids, delta=1, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, delta, subset_ids)\n \n def moveObjectsToTop(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, -len(self.order), subset_ids)\n \n def moveObjectsToBottom(self, ids, subset_ids=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n return self.moveObjectsByDelta(ids, len(self.order), subset_ids)\n \n def moveObjectToPosition(self, id, position, suppress_events=False):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n old_position = self.getObjectPosition(id)\n if old_position is not None:\n delta = position - old_position\n if delta:\n- return self.moveObjectsByDelta(id, delta,\n- suppress_events=suppress_events)\n+ return self.moveObjectsByDelta(\n+ id, delta, suppress_events=suppress_events\n+ )\n \n def orderObjects(self, key=None, reverse=None):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n if key is None:\n if not reverse:\n return -1\n@@ -146,17 +144,19 @@ def orderObjects(self, key=None, reverse=None):\n # Simply reverse the current ordering.\n self.order.reverse()\n else:\n+\n def keyfn(id):\n attr = getattr(self.context._getOb(id), key)\n if callable(attr):\n return attr()\n return attr\n+\n self.order = sorted(self.order, key=keyfn, reverse=bool(reverse))\n- self.context._p_changed = True # the order was changed\n+ self.context._p_changed = True # the order was changed\n return -1\n \n def getObjectPosition(self, id):\n- """ see interfaces.py """\n+ """see interfaces.py"""\n try:\n # using `index` here might not be that efficient for very large\n # lists, but the idea behind this adapter is to use it when the\ndiff --git a/src/plone/folder/testing.py b/src/plone/folder/testing.py\nindex b14476f..9927242 100644\n--- a/src/plone/folder/testing.py\n+++ b/src/plone/folder/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@@ -8,7 +7,6 @@\n \n \n class PloneFolderLayer(PloneSandboxLayer):\n-\n defaultBases = (PLONE_FIXTURE,)\n \n def setUpZope(self, app, configurationContext):\n@@ -18,11 +16,9 @@ def setUpZope(self, app, configurationContext):\n PLONEFOLDER_FIXTURE = PloneFolderLayer()\n \n PLONEFOLDER_INTEGRATION_TESTING = IntegrationTesting(\n- bases=(PLONEFOLDER_FIXTURE,),\n- name=\'PloneFolderLayer:IntegrationTesting\'\n+ bases=(PLONEFOLDER_FIXTURE,), name="PloneFolderLayer:IntegrationTesting"\n )\n \n PLONEFOLDER_FUNCTIONAL_TESTING = FunctionalTesting(\n- bases=(PLONEFOLDER_FIXTURE,),\n- name=\'PloneFolderLayer:FunctionalTesting\'\n+ bases=(PLONEFOLDER_FIXTURE,), name="PloneFolderLayer:FunctionalTesting"\n )\ndiff --git a/src/plone/folder/tests/benchmarks.py b/src/plone/folder/tests/benchmarks.py\nindex ab36afd..a788f58 100644\n--- a/src/plone/folder/tests/benchmarks.py\n+++ b/src/plone/folder/tests/benchmarks.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n # simple benchmarking tests related to plip191\n # to run individual tests using:\n # $ bin/instance test -s plone.folder --tests-pattern=benchmarks -t \n@@ -8,26 +7,25 @@\n from plone.folder.tests.layer import PloneFolderLayer\n from plone.folder.tests.utils import DummyObject\n from profilehooks import timecall\n-from six.moves import range\n from unittest import defaultTestLoader\n from unittest import TestCase\n \n \n class BenchmarkTests(TestCase):\n-\n layer = PloneFolderLayer\n \n def testDeleteSpeed(self):\n folder = OrderedBTreeFolderBase("f1")\n for idx in range(100000):\n- id = \'foo-%s\' % idx\n- folder[id] = DummyObject(id, \'bar\')\n+ id = "foo-%s" % idx\n+ folder[id] = DummyObject(id, "bar")\n last = reversed(folder.keys()[-100:])\n \n @timecall\n def delete():\n for id in last:\n del folder[id]\n+\n delete()\n \n \ndiff --git a/src/plone/folder/tests/test_dict_interface.py b/src/plone/folder/tests/test_dict_interface.py\nindex 5917e88..489604e 100644\n--- a/src/plone/folder/tests/test_dict_interface.py\n+++ b/src/plone/folder/tests/test_dict_interface.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import aq_base\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n@@ -8,80 +7,80 @@\n \n \n class DictInterfaceTests(unittest.TestCase):\n- """ tests for dict style interface """\n+ """tests for dict style interface"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def test_getitem(self):\n folder = OrderedBTreeFolderBase("f1")\n- foo = DummyObject(\'foo\')\n- folder._setOb(\'foo\', foo)\n- self.assertEqual(folder[\'foo\'], foo)\n- self.assertEqual(folder.__getitem__(\'foo\'), foo)\n- self.assertRaises(KeyError, folder.__getitem__, \'bar\')\n+ foo = DummyObject("foo")\n+ folder._setOb("foo", foo)\n+ self.assertEqual(folder["foo"], foo)\n+ self.assertEqual(folder.__getitem__("foo"), foo)\n+ self.assertRaises(KeyError, folder.__getitem__, "bar")\n \n def test_setitem(self):\n folder = OrderedBTreeFolderBase("f1")\n- foo = DummyObject(\'foo\')\n- folder[\'foo\'] = foo\n- self.assertEqual(folder._getOb(\'foo\'), foo)\n+ foo = DummyObject("foo")\n+ folder["foo"] = foo\n+ self.assertEqual(folder._getOb("foo"), foo)\n \n def test_contains(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder._setOb(\'foo\', DummyObject(\'foo\'))\n- folder._setOb(\'bar\', DummyObject(\'bar\'))\n- self.assertTrue(\'foo\' in folder)\n- self.assertTrue(\'bar\' in folder)\n+ folder._setOb("foo", DummyObject("foo"))\n+ folder._setOb("bar", DummyObject("bar"))\n+ self.assertTrue("foo" in folder)\n+ self.assertTrue("bar" in folder)\n \n def test_delitem(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder._setOb(\'foo\', DummyObject(\'foo\'))\n- folder._setOb(\'bar\', DummyObject(\'bar\'))\n- self.assertEquals(len(folder.objectIds()), 2)\n- del folder[\'foo\']\n- del folder[\'bar\']\n- self.assertEquals(len(folder.objectIds()), 0)\n+ folder._setOb("foo", DummyObject("foo"))\n+ folder._setOb("bar", DummyObject("bar"))\n+ self.assertEqual(len(folder.objectIds()), 2)\n+ del folder["foo"]\n+ del folder["bar"]\n+ self.assertEqual(len(folder.objectIds()), 0)\n \n def test_len_empty_folder(self):\n folder = OrderedBTreeFolderBase("f1")\n- self.assertEquals(len(folder), 0)\n+ self.assertEqual(len(folder), 0)\n \n def test_len_one_child(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder[\'child\'] = DummyObject(\'child\')\n- self.assertEquals(len(folder), 1)\n+ folder["child"] = DummyObject("child")\n+ self.assertEqual(len(folder), 1)\n \n def test_to_verify_ticket_9120(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder[\'ob1\'] = ob1 = DummyObject(\'ob1\')\n- folder[\'ob2\'] = DummyObject(\'ob2\')\n- folder[\'ob3\'] = DummyObject(\'ob3\')\n- folder[\'ob4\'] = ob4 = DummyObject(\'ob4\')\n- del folder[\'ob2\']\n- del folder[\'ob3\']\n- self.assertEquals(folder.keys(), [\'ob1\', \'ob4\'])\n- self.assertEquals(list(map(aq_base, folder.values())), [ob1, ob4])\n- self.assertEquals([key in folder for key in folder], [True, True])\n+ folder["ob1"] = ob1 = DummyObject("ob1")\n+ folder["ob2"] = DummyObject("ob2")\n+ folder["ob3"] = DummyObject("ob3")\n+ folder["ob4"] = ob4 = DummyObject("ob4")\n+ del folder["ob2"]\n+ del folder["ob3"]\n+ self.assertEqual(folder.keys(), ["ob1", "ob4"])\n+ self.assertEqual(list(map(aq_base, folder.values())), [ob1, ob4])\n+ self.assertEqual([key in folder for key in folder], [True, True])\n \n \n class RelatedToDictInterfaceTests(unittest.TestCase):\n- """ various tests which are related to the dict-like interface """\n+ """various tests which are related to the dict-like interface"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n folder = OrderedBTreeFolderBase("f1")\n- folder._setOb(\'o1\', DummyObject(\'o1\', \'mt1\'))\n- folder._setOb(\'o2\', DummyObject(\'o2\', \'mt2\'))\n- folder._setOb(\'o3\', DummyObject(\'o3\', \'mt1\'))\n- folder._setOb(\'o4\', DummyObject(\'o4\', \'mt2\'))\n+ folder._setOb("o1", DummyObject("o1", "mt1"))\n+ folder._setOb("o2", DummyObject("o2", "mt2"))\n+ folder._setOb("o3", DummyObject("o3", "mt1"))\n+ folder._setOb("o4", DummyObject("o4", "mt2"))\n return folder\n \n def testObjectIdsWithSpec(self):\n folder = self.create()\n- self.assertEquals([\'o1\', \'o3\'], folder.objectIds(spec=\'mt1\'))\n- self.assertEquals([\'o2\', \'o4\'], folder.objectIds(spec=\'mt2\'))\n- folder.moveObjectsToTop([\'o3\'])\n- folder.moveObjectsDown([\'o2\'])\n- self.assertEquals([\'o3\', \'o1\'], folder.objectIds(spec=\'mt1\'))\n- self.assertEquals([\'o4\', \'o2\'], folder.objectIds(spec=\'mt2\'))\n+ self.assertEqual(["o1", "o3"], folder.objectIds(spec="mt1"))\n+ self.assertEqual(["o2", "o4"], folder.objectIds(spec="mt2"))\n+ folder.moveObjectsToTop(["o3"])\n+ folder.moveObjectsDown(["o2"])\n+ self.assertEqual(["o3", "o1"], folder.objectIds(spec="mt1"))\n+ self.assertEqual(["o4", "o2"], folder.objectIds(spec="mt2"))\ndiff --git a/src/plone/folder/tests/test_integration.py b/src/plone/folder/tests/test_integration.py\nindex 959c627..d4b3371 100644\n--- a/src/plone/folder/tests/test_integration.py\n+++ b/src/plone/folder/tests/test_integration.py\n@@ -1,9 +1,8 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import Implicit\n+from io import BytesIO\n from plone.folder.interfaces import IOrderable\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_FUNCTIONAL_TESTING\n-from six import BytesIO\n from transaction import savepoint\n from zope.interface import implementer\n \n@@ -12,23 +11,22 @@\n \n @implementer(IOrderable)\n class DummyFolder(OrderedBTreeFolderBase, Implicit):\n- """ we need to mix in acquisition """\n+ """we need to mix in acquisition"""\n \n- meta_type = \'DummyFolder\'\n+ meta_type = "DummyFolder"\n \n \n class IntegrationTests(unittest.TestCase):\n-\n layer = PLONEFOLDER_FUNCTIONAL_TESTING\n \n def testExportDoesntIncludeParent(self):\n- self.app = self.layer[\'app\']\n- self.app._setOb(\'foo\', DummyFolder(\'foo\'))\n+ self.app = self.layer["app"]\n+ self.app._setOb("foo", DummyFolder("foo"))\n foo = self.app.foo\n- foo[\'bar\'] = DummyFolder(\'bar\')\n- savepoint(optimistic=True) # savepoint assigns oids\n+ foo["bar"] = DummyFolder("bar")\n+ savepoint(optimistic=True) # savepoint assigns oids\n # now let\'s export to a buffer and check the objects...\n exp = BytesIO()\n self.app._p_jar.exportFile(foo.bar._p_oid, exp)\n- self.assertTrue(b\'bar\' in exp.getvalue())\n- self.assertFalse(b\'foo\' in exp.getvalue())\n+ self.assertTrue(b"bar" in exp.getvalue())\n+ self.assertFalse(b"foo" in exp.getvalue())\ndiff --git a/src/plone/folder/tests/test_ordering_adapters.py b/src/plone/folder/tests/test_ordering_adapters.py\nindex 3efe323..6a4b174 100644\n--- a/src/plone/folder/tests/test_ordering_adapters.py\n+++ b/src/plone/folder/tests/test_ordering_adapters.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from plone.folder.default import DefaultOrdering\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n@@ -9,7 +8,7 @@\n \n \n class OrderingAdapterTests(unittest.TestCase):\n- """ tests regarding available ordering adapters """\n+ """tests regarding available ordering adapters"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n@@ -19,21 +18,21 @@ def testDefaultAdapter(self):\n \n def testUnorderedOrdering(self):\n folder = OrderedBTreeFolderBase()\n- folder._ordering = \'unordered\'\n+ folder._ordering = "unordered"\n self.assertTrue(isinstance(folder.getOrdering(), UnorderedOrdering))\n \n def testUnknownOrdering(self):\n folder = OrderedBTreeFolderBase()\n- folder._ordering = \'foo\'\n+ folder._ordering = "foo"\n self.assertTrue(isinstance(folder.getOrdering(), DefaultOrdering))\n \n def testSetOrdering(self):\n folder = OrderedBTreeFolderBase()\n- folder.setOrdering(\'unordered\')\n+ folder.setOrdering("unordered")\n self.assertTrue(isinstance(folder.getOrdering(), UnorderedOrdering))\n folder.setOrdering()\n self.assertTrue(isinstance(folder.getOrdering(), DefaultOrdering))\n \n def testSetUnknownOrdering(self):\n folder = OrderedBTreeFolderBase()\n- self.assertRaises(ComponentLookupError, folder.setOrdering, \'foo\')\n+ self.assertRaises(ComponentLookupError, folder.setOrdering, "foo")\ndiff --git a/src/plone/folder/tests/test_ordersupport.py b/src/plone/folder/tests/test_ordersupport.py\nindex 0808e1b..c05001d 100644\n--- a/src/plone/folder/tests/test_ordersupport.py\n+++ b/src/plone/folder/tests/test_ordersupport.py\n@@ -1,11 +1,9 @@\n-# -*- coding: utf-8 -*-\n from OFS.Traversable import Traversable\n from plone.folder.interfaces import IOrdering\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n from plone.folder.tests.utils import DummyObject\n \n-import six\n import unittest\n \n \n@@ -17,75 +15,61 @@ def getId(self):\n \n \n class OFSOrderSupportTests(unittest.TestCase):\n- """ tests borrowed from OFS.tests.testOrderSupport """\n+ """tests borrowed from OFS.tests.testOrderSupport"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n- folder = TestFolder(\'f1\')\n- folder[\'o1\'] = DummyObject(\'o1\', \'mt1\')\n- folder[\'o2\'] = DummyObject(\'o2\', \'mt2\')\n- folder[\'o3\'] = DummyObject(\'o3\', \'mt1\')\n- folder[\'o4\'] = DummyObject(\'o4\', \'mt2\')\n+ folder = TestFolder("f1")\n+ folder["o1"] = DummyObject("o1", "mt1")\n+ folder["o2"] = DummyObject("o2", "mt2")\n+ folder["o3"] = DummyObject("o3", "mt1")\n+ folder["o4"] = DummyObject("o4", "mt2")\n return folder\n \n # Test for ordering of basic methods\n \n def test_objectIdsOrdered(self):\n folder = self.create()\n- self.assertEquals(["o1", "o2", "o3", "o4"], folder.objectIds())\n+ self.assertEqual(["o1", "o2", "o3", "o4"], folder.objectIds())\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(["o2", "o1", "o3", "o4"], folder.objectIds())\n+ self.assertEqual(["o2", "o1", "o3", "o4"], folder.objectIds())\n \n def test_objectValuesOrdered(self):\n folder = self.create()\n- self.assertEquals(\n- ["o1", "o2", "o3", "o4"],\n- [x.id for x in folder.objectValues()]\n+ self.assertEqual(\n+ ["o1", "o2", "o3", "o4"], [x.id for x in folder.objectValues()]\n )\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(\n- ["o2", "o1", "o3", "o4"],\n- [x.id for x in folder.objectValues()]\n+ self.assertEqual(\n+ ["o2", "o1", "o3", "o4"], [x.id for x in folder.objectValues()]\n )\n \n def test_objectItemsOrdered(self):\n folder = self.create()\n- self.assertEquals(\n- ["o1", "o2", "o3", "o4"],\n- [x for x, y in folder.objectItems()]\n- )\n+ self.assertEqual(["o1", "o2", "o3", "o4"], [x for x, y in folder.objectItems()])\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(\n- ["o2", "o1", "o3", "o4"],\n- [x for x, y in folder.objectItems()]\n- )\n+ self.assertEqual(["o2", "o1", "o3", "o4"], [x for x, y in folder.objectItems()])\n \n def test_iterkeys(self):\n folder = self.create()\n- self.assertEquals(\n- ["o1", "o2", "o3", "o4"],\n- [x for x in six.iterkeys(folder)]\n- )\n+ self.assertEqual(["o1", "o2", "o3", "o4"], [x for x in folder.keys()])\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(\n- ["o2", "o1", "o3", "o4"],\n- [x for x in six.iterkeys(folder)]\n- )\n+ self.assertEqual(["o2", "o1", "o3", "o4"], [x for x in folder.keys()])\n \n def test_iter(self):\n folder = self.create()\n- self.assertEquals(["o1", "o2", "o3", "o4"], [x for x in folder])\n+ self.assertEqual(["o1", "o2", "o3", "o4"], [x for x in folder])\n folder.moveObjectsUp(("o2",), 1)\n- self.assertEquals(["o2", "o1", "o3", "o4"], [x for x in folder])\n+ self.assertEqual(["o2", "o1", "o3", "o4"], [x for x in folder])\n \n def test_getitem(self):\n ordering = IOrdering(self.create())\n- self.assertEquals(ordering[1], \'o2\')\n- self.assertEquals(ordering[-1], \'o4\')\n- self.assertEquals(ordering[1:2], [\'o2\'])\n- self.assertEquals(ordering[1:-1], [\'o2\', \'o3\'])\n- self.assertEquals(ordering[1:], [\'o2\', \'o3\', \'o4\'])\n+ self.assertEqual(ordering[1], "o2")\n+ self.assertEqual(ordering[-1], "o4")\n+ self.assertEqual(ordering[1:2], ["o2"])\n+ self.assertEqual(ordering[1:-1], ["o2", "o3"])\n+ self.assertEqual(ordering[1:], ["o2", "o3", "o4"])\n \n # Tests borrowed from OFS.tests.testsOrderSupport\n \n@@ -93,271 +77,279 @@ def runTableTests(self, methodname, table):\n for args, order, rval in table:\n f = self.create()\n method = getattr(f, methodname)\n- if rval == \'ValueError\':\n+ if rval == "ValueError":\n self.assertRaises(ValueError, method, *args)\n else:\n self.assertEqual(method(*args), rval)\n self.assertEqual(f.objectIds(), order)\n \n def test_moveObjectsUp(self):\n- self.runTableTests(\'moveObjectsUp\',\n- ( ( ( \'o4\', 1 ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1 )\n- , ( ( \'o4\', 2 ), [\'o1\', \'o4\', \'o2\', \'o3\'], 1 )\n- , ( ( (\'o1\', \'o3\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o1\', \'o3\'), 9 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), 1 ), [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1)\n- , ( ( (\'o3\', \'o1\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsUp",\n+ (\n+ (("o4", 1), ["o1", "o2", "o4", "o3"], 1),\n+ (("o4", 2), ["o1", "o4", "o2", "o3"], 1),\n+ ((("o1", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o1", "o3"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o2", "o3", "o1", "o4"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o2", "o3", "o1", "o4"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o3", "o1"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def test_moveObjectsDown(self):\n- self.runTableTests(\'moveObjectsDown\',\n- ( ( ( \'o1\', 1 ), [\'o2\', \'o1\', \'o3\', \'o4\'], 1 )\n- , ( ( \'o1\', 2 ), [\'o2\', \'o3\', \'o1\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o4\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o4\'), 9 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), 1 ), [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), 1 ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1)\n- , ( ( (\'o4\', \'o2\'), 1 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsDown",\n+ (\n+ (("o1", 1), ["o2", "o1", "o3", "o4"], 1),\n+ (("o1", 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("o2", "o4"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o4"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o1", "o4", "o2", "o3"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o1", "o4", "o2", "o3"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"), 1), ["o1", "o2", "o4", "o3"], 1),\n+ ((("o4", "o2"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def test_moveObjectsToTop(self):\n- self.runTableTests(\'moveObjectsToTop\',\n- ( ( ( \'o4\', ), [\'o4\', \'o1\', \'o2\', \'o3\'], 1 )\n- , ( ( (\'o1\', \'o3\'), ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), ), [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o2\', \'o3\', \'o1\', \'o4\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), ), [\'o3\', \'o1\', \'o2\', \'o4\'], 1)\n- , ( ( (\'o3\', \'o1\'), ), [\'o3\', \'o1\', \'o2\', \'o4\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsToTop",\n+ (\n+ (("o4",), ["o4", "o1", "o2", "o3"], 1),\n+ ((("o1", "o3"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"),), ["o3", "o1", "o2", "o4"], 1),\n+ ((("o3", "o1"),), ["o3", "o1", "o2", "o4"], 1),\n+ ),\n+ )\n \n def test_moveObjectsToBottom(self):\n- self.runTableTests(\'moveObjectsToBottom\',\n- ( ( ( \'o1\', ), [\'o2\', \'o3\', \'o4\', \'o1\'], 1 )\n- , ( ( (\'o2\', \'o4\'), ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1 )\n- , ( ( (\'o2\', \'o3\'), ), [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\') ),\n- [\'o1\', \'o4\', \'o2\', \'o3\'], 2 )\n- , ( ( (\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\') ),\n- [\'o1\', \'o2\', \'o3\', \'o4\'], 0 )\n- , ( ( (\'n2\', \'o3\'), ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1)\n- , ( ( (\'o4\', \'o2\'), ), [\'o1\', \'o3\', \'o4\', \'o2\'], 1 )\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectsToBottom",\n+ (\n+ (("o1",), ["o2", "o3", "o4", "o1"], 1),\n+ ((("o2", "o4"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("n2", "o3"),), ["o1", "o2", "o4", "o3"], 1),\n+ ((("o4", "o2"),), ["o1", "o3", "o4", "o2"], 1),\n+ ),\n+ )\n \n def test_orderObjects(self):\n- self.runTableTests(\'orderObjects\',\n- ( ( ( \'id\', \'id\' ), [\'o4\', \'o3\', \'o2\', \'o1\'], -1)\n- , ( ( \'meta_type\', \'\' ), [\'o1\', \'o3\', \'o2\', \'o4\'], -1)\n- # for the next line the sort order is different from the\n- # original test in OFS, since the current implementation\n- # keeps the original order as much as possible, i.e. minimize\n- # exchange operations within the list; this is correct as\n- # far as the test goes, since it didn\'t specify a secondary\n- # sort key...\n- , ( ( \'meta_type\', \'n\' ), [\'o2\', \'o4\', \'o1\', \'o3\'], -1)\n- )\n- )\n+ self.runTableTests(\n+ "orderObjects",\n+ (\n+ (("id", "id"), ["o4", "o3", "o2", "o1"], -1),\n+ (("meta_type", ""), ["o1", "o3", "o2", "o4"], -1)\n+ # for the next line the sort order is different from the\n+ # original test in OFS, since the current implementation\n+ # keeps the original order as much as possible, i.e. minimize\n+ # exchange operations within the list; this is correct as\n+ # far as the test goes, since it didn\'t specify a secondary\n+ # sort key...\n+ ,\n+ (("meta_type", "n"), ["o2", "o4", "o1", "o3"], -1),\n+ ),\n+ )\n \n def test_getObjectPosition(self):\n- self.runTableTests(\'getObjectPosition\',\n- ( ( ( \'o2\', ), [\'o1\', \'o2\', \'o3\', \'o4\'], 1)\n- , ( ( \'o4\', ), [\'o1\', \'o2\', \'o3\', \'o4\'], 3)\n- , ( ( \'n2\', ), [\'o1\', \'o2\', \'o3\', \'o4\'], \'ValueError\')\n- )\n- )\n+ self.runTableTests(\n+ "getObjectPosition",\n+ (\n+ (("o2",), ["o1", "o2", "o3", "o4"], 1),\n+ (("o4",), ["o1", "o2", "o3", "o4"], 3),\n+ (("n2",), ["o1", "o2", "o3", "o4"], "ValueError"),\n+ ),\n+ )\n \n def test_moveObjectToPosition(self):\n- self.runTableTests(\'moveObjectToPosition\',\n- ( ( ( \'o2\', 2 ), [\'o1\', \'o3\', \'o2\', \'o4\'], 1)\n- , ( ( \'o4\', 2 ), [\'o1\', \'o2\', \'o4\', \'o3\'], 1)\n- , ( ( \'n2\', 2 ), [\'o1\', \'o2\', \'o3\', \'o4\'], \'ValueError\')\n- )\n- )\n+ self.runTableTests(\n+ "moveObjectToPosition",\n+ (\n+ (("o2", 2), ["o1", "o3", "o2", "o4"], 1),\n+ (("o4", 2), ["o1", "o2", "o4", "o3"], 1),\n+ (("n2", 2), ["o1", "o2", "o3", "o4"], "ValueError"),\n+ ),\n+ )\n \n def test_getObjectPosition_error_message(self):\n folder = self.create()\n try:\n- folder.getObjectPosition(\'n4\')\n+ folder.getObjectPosition("n4")\n self.assertFail()\n except ValueError as err:\n- self.assertEqual(\n- str(err), \'No object with id "n4" exists in "f1".\')\n+ self.assertEqual(str(err), \'No object with id "n4" exists in "f1".\')\n \n \n class PloneOrderSupportTests(unittest.TestCase):\n- """ tests borrowed from Products.CMFPlone.tests.testOrderSupport """\n+ """tests borrowed from Products.CMFPlone.tests.testOrderSupport"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def setUp(self):\n self.folder = OrderedBTreeFolderBase("f1")\n- self.folder[\'foo\'] = DummyObject(\'foo\', \'mt1\')\n- self.folder[\'bar\'] = DummyObject(\'bar\', \'mt1\')\n- self.folder[\'baz\'] = DummyObject(\'baz\', \'mt1\')\n+ self.folder["foo"] = DummyObject("foo", "mt1")\n+ self.folder["bar"] = DummyObject("bar", "mt1")\n+ self.folder["baz"] = DummyObject("baz", "mt1")\n \n def testGetObjectPosition(self):\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObject(self):\n- self.folder.moveObjectToPosition(\'foo\', 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("foo", 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectToSamePos(self):\n- self.folder.moveObjectToPosition(\'bar\', 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("bar", 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectToFirstPos(self):\n- self.folder.moveObjectToPosition(\'bar\', 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("bar", 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectToLastPos(self):\n- self.folder.moveObjectToPosition(\'bar\', 2)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectToPosition("bar", 2)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveObjectOutLowerBounds(self):\n # Pos will be normalized to 0\n- self.folder.moveObjectToPosition(\'bar\', -1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectToPosition("bar", -1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectOutUpperBounds(self):\n # Pos will be normalized to 2\n- self.folder.moveObjectToPosition(\'bar\', 3)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectToPosition("bar", 3)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveObjectsUp(self):\n- self.folder.moveObjectsUp([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectsUp(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectsDown(self):\n- self.folder.moveObjectsDown([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsDown(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveObjectsToTop(self):\n- self.folder.moveObjectsToTop([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectsToTop(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testMoveObjectsToBottom(self):\n- self.folder.moveObjectsToBottom([\'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsToBottom(["bar"])\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveTwoObjectsUp(self):\n- self.folder.moveObjectsUp([\'bar\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.moveObjectsUp(["bar", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testMoveTwoObjectsDown(self):\n- self.folder.moveObjectsDown([\'foo\', \'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsDown(["foo", "bar"])\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testMoveTwoObjectsToTop(self):\n- self.folder.moveObjectsToTop([\'bar\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.moveObjectsToTop(["bar", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testMoveTwoObjectsToBottom(self):\n- self.folder.moveObjectsToBottom([\'foo\', \'bar\'])\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsToBottom(["foo", "bar"])\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testOrderObjects(self):\n- self.folder.orderObjects(\'id\')\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.orderObjects("id")\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testOrderObjectsReverse(self):\n- self.folder.orderObjects(\'id\', reverse=True)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.orderObjects("id", reverse=True)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testOrderObjectsByMethod(self):\n- self.folder.orderObjects(\'dummy_method\')\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.orderObjects("dummy_method")\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testOrderObjectsOnlyReverse(self):\n self.folder.orderObjects(reverse=True)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testSubsetIds(self):\n- self.folder.moveObjectsByDelta([\'baz\'], -1, [\'foo\', \'bar\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 2)\n+ self.folder.moveObjectsByDelta(["baz"], -1, ["foo", "bar", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 2)\n \n def testSkipObjectsNotInSubsetIds(self):\n- self.folder.moveObjectsByDelta([\'baz\'], -1, [\'foo\', \'baz\'])\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 1) # no move\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 2)\n+ self.folder.moveObjectsByDelta(["baz"], -1, ["foo", "baz"])\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 1) # no move\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 2)\n \n def testIgnoreNonObjects(self):\n # Fix for (http://dev.plone.org/plone/ticket/3959) non\n # contentish objects cause errors, we should just ignore them\n- self.folder.moveObjectsByDelta([\'bar\', \'blah\'], -1)\n- self.assertEqual(self.folder.getObjectPosition(\'bar\'), 0)\n- self.assertEqual(self.folder.getObjectPosition(\'foo\'), 1)\n- self.assertEqual(self.folder.getObjectPosition(\'baz\'), 2)\n+ self.folder.moveObjectsByDelta(["bar", "blah"], -1)\n+ self.assertEqual(self.folder.getObjectPosition("bar"), 0)\n+ self.assertEqual(self.folder.getObjectPosition("foo"), 1)\n+ self.assertEqual(self.folder.getObjectPosition("baz"), 2)\n \n def testNotifyRemoved(self):\n ordering = self.folder.getOrdering()\n- self.assertEqual(\n- ordering.idsInOrder(),\n- [\'foo\', \'bar\', \'baz\']\n- )\n+ self.assertEqual(ordering.idsInOrder(), ["foo", "bar", "baz"])\n \n # make sure notifyRemoved with non-existent id does not throw error\n- ordering.notifyRemoved(\'foobar\')\n+ ordering.notifyRemoved("foobar")\n \n # normal\n- ordering.notifyRemoved(\'foo\')\n- self.assertEqual(\n- ordering.idsInOrder(),\n- [\'bar\', \'baz\']\n- )\n+ ordering.notifyRemoved("foo")\n+ self.assertEqual(ordering.idsInOrder(), ["bar", "baz"])\ndiff --git a/src/plone/folder/tests/test_partialordering.py b/src/plone/folder/tests/test_partialordering.py\nindex 8468c63..eca9544 100644\n--- a/src/plone/folder/tests/test_partialordering.py\n+++ b/src/plone/folder/tests/test_partialordering.py\n@@ -1,32 +1,33 @@\n-from transaction import savepoint\n from Acquisition import Implicit\n-from zope.interface import implementer\n from plone.folder.interfaces import IOrderable\n from plone.folder.ordered import OrderedBTreeFolderBase\n from plone.folder.partial import PartialOrdering\n-from plone.folder.tests.utils import Orderable, Chaoticle\n-from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n from plone.folder.testing import PLONEFOLDER_FUNCTIONAL_TESTING\n+from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n+from plone.folder.tests.utils import Chaoticle\n+from plone.folder.tests.utils import Orderable\n+from transaction import savepoint\n+from zope.interface import implementer\n \n import unittest\n \n \n class PartialOrderingTests(unittest.TestCase):\n- """ tests regarding order-support for only items marked orderable """\n+ """tests regarding order-support for only items marked orderable"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n container = OrderedBTreeFolderBase()\n- container.setOrdering(u\'partial\')\n- container[\'o1\'] = Orderable(\'o1\', \'mt1\')\n- container[\'o2\'] = Orderable(\'o2\', \'mt2\')\n- container[\'c1\'] = Chaoticle(\'c1\', \'mt3\')\n- container[\'o3\'] = Orderable(\'o3\', \'mt1\')\n- container[\'c2\'] = Chaoticle(\'c2\', \'mt2\')\n- container[\'c3\'] = Chaoticle(\'c3\', \'mt1\')\n- container[\'o4\'] = Orderable(\'o4\', \'mt2\')\n- self.unordered = [\'c1\', \'c2\', \'c3\']\n+ container.setOrdering("partial")\n+ container["o1"] = Orderable("o1", "mt1")\n+ container["o2"] = Orderable("o2", "mt2")\n+ container["c1"] = Chaoticle("c1", "mt3")\n+ container["o3"] = Orderable("o3", "mt1")\n+ container["c2"] = Chaoticle("c2", "mt2")\n+ container["c3"] = Chaoticle("c3", "mt1")\n+ container["o4"] = Orderable("o4", "mt2")\n+ self.unordered = ["c1", "c2", "c3"]\n ordering = container.getOrdering()\n return container, ordering\n \n@@ -37,43 +38,29 @@ def testAdapter(self):\n def testNotifyAdded(self):\n container, ordering = self.create()\n self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o3\', \'o4\'] + self.unordered\n+ ordering.idsInOrder(), ["o1", "o2", "o3", "o4"] + self.unordered\n )\n- container[\'o5\'] = Orderable(\'o5\')\n+ container["o5"] = Orderable("o5")\n self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o3\', \'o4\', \'o5\'] + self.unordered\n+ ordering.idsInOrder(), ["o1", "o2", "o3", "o4", "o5"] + self.unordered\n )\n self.assertEqual(\n- set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\', \'o5\', \'c1\', \'c2\', \'c3\'])\n+ set(container.objectIds()), {"o1", "o2", "o3", "o4", "o5", "c1", "c2", "c3"}\n )\n \n def testNotifyRemoved(self):\n container, ordering = self.create()\n self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o3\', \'o4\'] + self.unordered\n- )\n- container._delOb(\'o3\')\n- self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o1\', \'o2\', \'o4\'] + self.unordered\n- )\n- self.assertEqual(\n- set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o4\', \'c1\', \'c2\', \'c3\'])\n- )\n- container._delOb(\'o1\')\n- self.assertEqual(\n- ordering.idsInOrder(),\n- [\'o2\', \'o4\'] + self.unordered\n+ ordering.idsInOrder(), ["o1", "o2", "o3", "o4"] + self.unordered\n )\n+ container._delOb("o3")\n+ self.assertEqual(ordering.idsInOrder(), ["o1", "o2", "o4"] + self.unordered)\n self.assertEqual(\n- set(container.objectIds()),\n- set([\'o2\', \'o4\', \'c1\', \'c2\', \'c3\'])\n+ set(container.objectIds()), {"o1", "o2", "o4", "c1", "c2", "c3"}\n )\n+ container._delOb("o1")\n+ self.assertEqual(ordering.idsInOrder(), ["o2", "o4"] + self.unordered)\n+ self.assertEqual(set(container.objectIds()), {"o2", "o4", "c1", "c2", "c3"})\n \n def runTableTests(self, action, tests):\n for args, order, rval in tests:\n@@ -85,132 +72,175 @@ def runTableTests(self, action, tests):\n else:\n self.assertEqual(method(*args), rval)\n self.assertEqual(ordering.idsInOrder(), order + self.unordered)\n- self.assertEqual(set(container.objectIds()), ids) # all here?\n+ self.assertEqual(set(container.objectIds()), ids) # all here?\n \n def testMoveObjectsByDelta(self):\n- self.runTableTests(\'moveObjectsByDelta\', (\n- ((\'o1\', 1), [\'o2\', \'o1\', \'o3\', \'o4\'], 1),\n- ((\'o1\', 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'o2\', \'o4\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o4\'), 9), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'), 1), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o1\'), 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'c1\', \'o3\'), 1), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- (((\'n2\', \'o2\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o4\', \'o2\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsByDelta",\n+ (\n+ (("o1", 1), ["o2", "o1", "o3", "o4"], 1),\n+ (("o1", 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("o2", "o4"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o4"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o1", "o4", "o2", "o3"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o1", "o4", "o2", "o3"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o1"), 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("c1", "o3"), 1), ["o1", "o2", "o4", "o3"], 1),\n+ ((("n2", "o2"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o4", "o2"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsDown(self):\n- self.runTableTests(\'moveObjectsDown\', (\n- ((\'o1\',), [\'o2\', \'o1\', \'o3\', \'o4\'], 1),\n- ((\'o1\', 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'o2\', \'o4\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o4\'), 9), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'),), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o1\'), 2), [\'o2\', \'o3\', \'o1\', \'o4\'], 1),\n- (((\'c1\', \'o3\'),), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- (((\'n2\', \'o2\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o4\', \'o2\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsDown",\n+ (\n+ (("o1",), ["o2", "o1", "o3", "o4"], 1),\n+ (("o1", 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("o2", "o4"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o4"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o1", "o4", "o2", "o3"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o1", "o4", "o2", "o3"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o1"), 2), ["o2", "o3", "o1", "o4"], 1),\n+ ((("c1", "o3"),), ["o1", "o2", "o4", "o3"], 1),\n+ ((("n2", "o2"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o4", "o2"),), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsUp(self):\n- self.runTableTests(\'moveObjectsUp\', (\n- ((\'o4\',), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- ((\'o4\', 1), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- ((\'o4\', 2), [\'o1\', \'o4\', \'o2\', \'o3\'], 1),\n- (((\'o1\', \'o3\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o1\', \'o3\'), 9), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'), 1), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), 1, (\'o2\', \'o3\', \'o4\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o4\'), 2), [\'o1\', \'o4\', \'o2\', \'o3\'], 1),\n- (((\'c1\', \'o3\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'n2\', \'o3\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o3\', \'o1\'), 1), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsUp",\n+ (\n+ (("o4",), ["o1", "o2", "o4", "o3"], 1),\n+ (("o4", 1), ["o1", "o2", "o4", "o3"], 1),\n+ (("o4", 2), ["o1", "o4", "o2", "o3"], 1),\n+ ((("o1", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o1", "o3"), 9), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"), 1), ["o2", "o3", "o1", "o4"], 2),\n+ (\n+ (("o2", "o3"), 1, ("o1", "o2", "o3", "o4")),\n+ ["o2", "o3", "o1", "o4"],\n+ 2,\n+ ),\n+ ((("o2", "o3"), 1, ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o4"), 2), ["o1", "o4", "o2", "o3"], 1),\n+ ((("c1", "o3"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("n2", "o3"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o3", "o1"), 1), ["o1", "o3", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsToTop(self):\n- self.runTableTests(\'moveObjectsToTop\', (\n- ((\'o4\',), [\'o4\', \'o1\', \'o2\', \'o3\'], 1),\n- (((\'o1\', \'o3\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'),), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o2\', \'o3\', \'o1\', \'o4\'], 2),\n- (((\'o2\', \'o3\'), (\'o2\', \'o3\', \'o4\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o4\'),), [\'o4\', \'o1\', \'o2\', \'o3\'], 1),\n- (((\'c1\', \'o3\'),), [\'o3\', \'o1\', \'o2\', \'o4\'], 1),\n- (((\'n2\', \'o3\'),), [\'o3\', \'o1\', \'o2\', \'o4\'], 1),\n- (((\'o3\', \'o1\'),), [\'o3\', \'o1\', \'o2\', \'o4\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsToTop",\n+ (\n+ (("o4",), ["o4", "o1", "o2", "o3"], 1),\n+ ((("o1", "o3"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o2", "o3", "o1", "o4"], 2),\n+ ((("o2", "o3"), ("o2", "o3", "o4")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o4"),), ["o4", "o1", "o2", "o3"], 1),\n+ ((("c1", "o3"),), ["o3", "o1", "o2", "o4"], 1),\n+ ((("n2", "o3"),), ["o3", "o1", "o2", "o4"], 1),\n+ ((("o3", "o1"),), ["o3", "o1", "o2", "o4"], 1),\n+ ),\n+ )\n \n def testMoveObjectsToBottom(self):\n- self.runTableTests(\'moveObjectsToBottom\', (\n- ((\'o1\',), [\'o2\', \'o3\', \'o4\', \'o1\'], 1),\n- (((\'o2\', \'o4\'),), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- (((\'o2\', \'o3\'),), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\', \'o4\')), [\'o1\', \'o4\', \'o2\', \'o3\'], 2),\n- (((\'o2\', \'o3\'), (\'o1\', \'o2\', \'o3\')), [\'o1\', \'o2\', \'o3\', \'o4\'], 0),\n- (((\'c1\', \'o1\'),), [\'o2\', \'o3\', \'o4\', \'o1\'], 1),\n- (((\'c1\', \'o2\'),), [\'o1\', \'o3\', \'o4\', \'o2\'], 1),\n- (((\'n2\', \'o3\'),), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- (((\'o4\', \'o2\'),), [\'o1\', \'o3\', \'o4\', \'o2\'], 1),\n- ))\n+ self.runTableTests(\n+ "moveObjectsToBottom",\n+ (\n+ (("o1",), ["o2", "o3", "o4", "o1"], 1),\n+ ((("o2", "o4"),), ["o1", "o3", "o2", "o4"], 1),\n+ ((("o2", "o3"),), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3", "o4")), ["o1", "o4", "o2", "o3"], 2),\n+ ((("o2", "o3"), ("o1", "o2", "o3")), ["o1", "o2", "o3", "o4"], 0),\n+ ((("c1", "o1"),), ["o2", "o3", "o4", "o1"], 1),\n+ ((("c1", "o2"),), ["o1", "o3", "o4", "o2"], 1),\n+ ((("n2", "o3"),), ["o1", "o2", "o4", "o3"], 1),\n+ ((("o4", "o2"),), ["o1", "o3", "o4", "o2"], 1),\n+ ),\n+ )\n \n def testMoveObjectToPosition(self):\n- self.runTableTests(\'moveObjectToPosition\', (\n- ((\'o2\', 2), [\'o1\', \'o3\', \'o2\', \'o4\'], 1),\n- ((\'o4\', 2), [\'o1\', \'o2\', \'o4\', \'o3\'], 1),\n- ((\'c1\', 2), [\'o1\', \'o2\', \'o3\', \'o4\'], None), # existent, but non-orderable\n- ((\'n2\', 2), [\'o1\', \'o2\', \'o3\', \'o4\'], ValueError),\n- ))\n+ self.runTableTests(\n+ "moveObjectToPosition",\n+ (\n+ (("o2", 2), ["o1", "o3", "o2", "o4"], 1),\n+ (("o4", 2), ["o1", "o2", "o4", "o3"], 1),\n+ (\n+ ("c1", 2),\n+ ["o1", "o2", "o3", "o4"],\n+ None,\n+ ), # existent, but non-orderable\n+ (("n2", 2), ["o1", "o2", "o3", "o4"], ValueError),\n+ ),\n+ )\n \n def testOrderObjects(self):\n- self.runTableTests(\'orderObjects\', (\n- ((\'id\', \'id\'), [\'o4\', \'o3\', \'o2\', \'o1\'], -1),\n- ((\'meta_type\', \'\'), [\'o1\', \'o3\', \'o2\', \'o4\'], -1),\n- # for the next line the sort order is different from the\n- # original test in OFS, since the current implementation\n- # keeps the original order as much as possible, i.e. minimize\n- # exchange operations within the list; this is correct as\n- # far as the test goes, since it didn\'t specify a secondary\n- # sort key...\n- ((\'meta_type\', \'n\'), [\'o2\', \'o4\', \'o1\', \'o3\'], -1),\n- ))\n+ self.runTableTests(\n+ "orderObjects",\n+ (\n+ (("id", "id"), ["o4", "o3", "o2", "o1"], -1),\n+ (("meta_type", ""), ["o1", "o3", "o2", "o4"], -1),\n+ # for the next line the sort order is different from the\n+ # original test in OFS, since the current implementation\n+ # keeps the original order as much as possible, i.e. minimize\n+ # exchange operations within the list; this is correct as\n+ # far as the test goes, since it didn\'t specify a secondary\n+ # sort key...\n+ (("meta_type", "n"), ["o2", "o4", "o1", "o3"], -1),\n+ ),\n+ )\n \n def testGetObjectPosition(self):\n- self.runTableTests(\'getObjectPosition\', (\n- ((\'o2\',), [\'o1\', \'o2\', \'o3\', \'o4\'], 1),\n- ((\'o4\',), [\'o1\', \'o2\', \'o3\', \'o4\'], 3),\n- ((\'n2\',), [\'o1\', \'o2\', \'o3\', \'o4\'], ValueError),\n- ((\'c2\',), [\'o1\', \'o2\', \'o3\', \'o4\'], None), # existent, but non-orderable\n- ))\n+ self.runTableTests(\n+ "getObjectPosition",\n+ (\n+ (("o2",), ["o1", "o2", "o3", "o4"], 1),\n+ (("o4",), ["o1", "o2", "o3", "o4"], 3),\n+ (("n2",), ["o1", "o2", "o3", "o4"], ValueError),\n+ (\n+ ("c2",),\n+ ["o1", "o2", "o3", "o4"],\n+ None,\n+ ), # existent, but non-orderable\n+ ),\n+ )\n \n \n @implementer(IOrderable)\n class DummyFolder(OrderedBTreeFolderBase, Implicit):\n- """ we need to mix in acquisition """\n+ """we need to mix in acquisition"""\n \n- meta_type = \'DummyFolder\'\n- _ordering = u\'partial\'\n+ meta_type = "DummyFolder"\n+ _ordering = "partial"\n \n def dummy_method(self):\n return self.id\n \n \n class PartialOrderingIntegrationTests(unittest.TestCase):\n-\n layer = PLONEFOLDER_FUNCTIONAL_TESTING\n \n def setUp(self):\n- self.app = self.layer[\'app\']\n+ self.app = self.layer["app"]\n context = self.app\n- context._setOb(\'foo\', DummyFolder(\'foo\')) # not pythonic in 2.10 :(\n- context.foo[\'bar1\'] = DummyFolder(\'bar1\')\n- context.foo[\'bar2\'] = DummyFolder(\'bar2\')\n- context.foo[\'bar3\'] = DummyFolder(\'bar3\')\n+ context._setOb("foo", DummyFolder("foo")) # not pythonic in 2.10 :(\n+ context.foo["bar1"] = DummyFolder("bar1")\n+ context.foo["bar2"] = DummyFolder("bar2")\n+ context.foo["bar3"] = DummyFolder("bar3")\n savepoint(optimistic=True)\n self.assertEqual(self.registered, [])\n \n@@ -220,36 +250,38 @@ def registered(self):\n \n def testAddObjectChangesOrderInfo(self):\n foo = self.app.foo\n- foo[\'bar23\'] = DummyFolder(\'bar23\')\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar2\', \'bar3\', \'bar23\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo["bar23"] = DummyFolder("bar23")\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar2", "bar3", "bar23"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n \n def testRemoveObjectChangesOrderInfo(self):\n foo = self.app.foo\n- foo._delOb(\'bar2\',)\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar3\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo._delOb(\n+ "bar2",\n+ )\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar3"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n \n def testMoveObjectChangesOrderInfo(self):\n foo = self.app.foo\n- foo.moveObjectsUp((\'bar2\',))\n- self.assertEqual(foo.objectIds(), [\'bar2\', \'bar1\', \'bar3\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo.moveObjectsUp(("bar2",))\n+ self.assertEqual(foo.objectIds(), ["bar2", "bar1", "bar3"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n \n def testOrderObjectsChangesOrderInfo(self):\n foo = self.app.foo\n- foo.orderObjects(\'id\', reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar3\', \'bar2\', \'bar1\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo.orderObjects("id", reverse=True)\n+ self.assertEqual(foo.objectIds(), ["bar3", "bar2", "bar1"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n # Reverse the current ordering.\n foo.orderObjects(reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar2\', \'bar3\'])\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar2", "bar3"])\n \n def testOrderObjectsByMethodChangesOrderInfo(self):\n foo = self.app.foo\n- foo.orderObjects(\'dummy_method\', reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar3\', \'bar2\', \'bar1\'])\n- self.assertTrue(foo in self.registered, \'not registered?\')\n+ foo.orderObjects("dummy_method", reverse=True)\n+ self.assertEqual(foo.objectIds(), ["bar3", "bar2", "bar1"])\n+ self.assertTrue(foo in self.registered, "not registered?")\n # Reverse the current ordering.\n foo.orderObjects(reverse=True)\n- self.assertEqual(foo.objectIds(), [\'bar1\', \'bar2\', \'bar3\'])\n+ self.assertEqual(foo.objectIds(), ["bar1", "bar2", "bar3"])\ndiff --git a/src/plone/folder/tests/test_unorderedordering.py b/src/plone/folder/tests/test_unorderedordering.py\nindex bfeb54e..f780870 100644\n--- a/src/plone/folder/tests/test_unorderedordering.py\n+++ b/src/plone/folder/tests/test_unorderedordering.py\n@@ -1,23 +1,23 @@\n from plone.folder.ordered import OrderedBTreeFolderBase\n-from plone.folder.unordered import UnorderedOrdering\n-from plone.folder.tests.utils import DummyObject\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n+from plone.folder.tests.utils import DummyObject\n+from plone.folder.unordered import UnorderedOrdering\n \n import unittest\n \n \n class UnorderedOrderingTests(unittest.TestCase):\n- """ tests regarding order-support for folders with unordered ordering """\n+ """tests regarding order-support for folders with unordered ordering"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n def create(self):\n container = OrderedBTreeFolderBase()\n- container._ordering = u\'unordered\'\n- container._setOb(\'o1\', DummyObject(\'o1\', \'mt1\'))\n- container._setOb(\'o2\', DummyObject(\'o2\', \'mt2\'))\n- container._setOb(\'o3\', DummyObject(\'o3\', \'mt1\'))\n- container._setOb(\'o4\', DummyObject(\'o4\', \'mt2\'))\n+ container._ordering = "unordered"\n+ container._setOb("o1", DummyObject("o1", "mt1"))\n+ container._setOb("o2", DummyObject("o2", "mt2"))\n+ container._setOb("o3", DummyObject("o3", "mt1"))\n+ container._setOb("o4", DummyObject("o4", "mt2"))\n return container\n \n def testAdapter(self):\n@@ -27,28 +27,16 @@ def testAdapter(self):\n \n def testNotifyAdded(self):\n container = self.create()\n- self.assertEqual(\n- set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\'])\n- )\n- container._setOb(\'o5\', DummyObject(\'o5\', \'mt1\'))\n- self.assertEqual(\n- set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\', \'o5\'])\n- )\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o3", "o4"})\n+ container._setOb("o5", DummyObject("o5", "mt1"))\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o3", "o4", "o5"})\n \n def testNotifyRemoved(self):\n container = self.create()\n- self.assertEqual(\n- set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o3\', \'o4\'])\n- )\n- container._delOb(\'o3\')\n- self.assertEqual(\n- set(container.objectIds()),\n- set([\'o1\', \'o2\', \'o4\'])\n- )\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o3", "o4"})\n+ container._delOb("o3")\n+ self.assertEqual(set(container.objectIds()), {"o1", "o2", "o4"})\n \n def testGetObjectPosition(self):\n container = self.create()\n- self.assertEqual(container.getObjectPosition(\'o2\'), None)\n+ self.assertEqual(container.getObjectPosition("o2"), None)\ndiff --git a/src/plone/folder/tests/test_webdav.py b/src/plone/folder/tests/test_webdav.py\nindex 05b8da0..d4a9637 100644\n--- a/src/plone/folder/tests/test_webdav.py\n+++ b/src/plone/folder/tests/test_webdav.py\n@@ -1,11 +1,9 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import Explicit\n from plone.folder.ordered import CMFOrderedBTreeFolderBase\n from plone.folder.testing import PLONEFOLDER_INTEGRATION_TESTING\n from plone.folder.tests.utils import DummyObject\n from zope.publisher.browser import TestRequest\n \n-import pkg_resources\n import unittest\n \n \n@@ -17,12 +15,11 @@\n \n \n class TestRequestContainer(Explicit):\n-\n REQUEST = TestRequest()\n \n \n class WebDAVTests(unittest.TestCase):\n- """ tests regarding support for WebDAV NullResources """\n+ """tests regarding support for WebDAV NullResources"""\n \n layer = PLONEFOLDER_INTEGRATION_TESTING\n \n@@ -31,28 +28,28 @@ def test_getitem_not_dav_request(self):\n folder = CMFOrderedBTreeFolderBase("f1").__of__(root)\n \n root.REQUEST.maybe_webdav_client = False\n- root.REQUEST._environ[\'REQUEST_METHOD\'] = \'GET\'\n+ root.REQUEST._environ["REQUEST_METHOD"] = "GET"\n \n- foo = DummyObject(\'foo\')\n- folder[\'foo\'] = foo\n+ foo = DummyObject("foo")\n+ folder["foo"] = foo\n \n- self.assertEquals(folder[\'foo\'], foo)\n+ self.assertEqual(folder["foo"], foo)\n try:\n- folder[\'bar\']\n+ folder["bar"]\n self.fail()\n except KeyError:\n pass\n \n- @unittest.skipUnless(HAS_WEBDAV, \'ZServer is optional\')\n+ @unittest.skipUnless(HAS_WEBDAV, "ZServer is optional")\n def test_getitem_dav_request(self):\n root = TestRequestContainer()\n folder = CMFOrderedBTreeFolderBase("f1").__of__(root)\n \n root.REQUEST.maybe_webdav_client = True\n- root.REQUEST._environ[\'REQUEST_METHOD\'] = \'PUT\'\n+ root.REQUEST._environ["REQUEST_METHOD"] = "PUT"\n \n- foo = DummyObject(\'foo\')\n- folder[\'foo\'] = foo\n+ foo = DummyObject("foo")\n+ folder["foo"] = foo\n \n- self.assertEquals(folder[\'foo\'], foo)\n- self.assertTrue(isinstance(folder[\'bar\'], NullResource))\n+ self.assertEqual(folder["foo"], foo)\n+ self.assertTrue(isinstance(folder["bar"], NullResource))\ndiff --git a/src/plone/folder/tests/utils.py b/src/plone/folder/tests/utils.py\nindex 5c2015b..aa1e79f 100644\n--- a/src/plone/folder/tests/utils.py\n+++ b/src/plone/folder/tests/utils.py\n@@ -1,10 +1,8 @@\n-# -*- coding: utf-8 -*-\n from plone.folder.interfaces import IOrderable\n from zope.interface import implementer\n \n \n-class DummyObject(object):\n-\n+class DummyObject:\n def __init__(self, id, meta_type=None):\n self.id = id\n self.meta_type = meta_type\n@@ -21,8 +19,8 @@ def dummy_method(self):\n \n @implementer(IOrderable)\n class Orderable(DummyObject):\n- """ orderable mock object """\n+ """orderable mock object"""\n \n \n class Chaoticle(DummyObject):\n- """ non-orderable mock object; this does not implement `IOrderable` """\n+ """non-orderable mock object; this does not implement `IOrderable`"""\ndiff --git a/src/plone/folder/unordered.py b/src/plone/folder/unordered.py\nindex 14d9ae8..751443b 100644\n--- a/src/plone/folder/unordered.py\n+++ b/src/plone/folder/unordered.py\n@@ -1,4 +1,3 @@\n-# -*- coding: utf-8 -*-\n from Acquisition import aq_base\n from plone.folder.interfaces import IOrderableFolder\n from plone.folder.interfaces import IOrdering\n@@ -8,8 +7,8 @@\n \n @implementer(IOrdering)\n @adapter(IOrderableFolder)\n-class UnorderedOrdering(object):\n- """ This implementation provides no ordering. """\n+class UnorderedOrdering:\n+ """This implementation provides no ordering."""\n \n def __init__(self, context):\n self.context = context\ndiff --git a/tox.ini b/tox.ini\nnew file mode 100644\nindex 0000000..21289b5\n--- /dev/null\n+++ b/tox.ini\n@@ -0,0 +1,68 @@\n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n+[tox]\n+# We need 4.4.0 for constrain_package_deps.\n+min_version = 4.4.0\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+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n+deps =\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ zope-testrunner --all --test-path={toxinidir}/src -s plone.folder {posargs}\n+extras =\n+ test\n+\n+[testenv:coverage]\n+usedevelop = true\n+constrain_package_deps = true\n+set_env = ROBOT_BROWSER=headlesschrome\n+deps =\n+ coverage\n+ zope.testrunner\n+ -c https://dist.plone.org/release/6.0-dev/constraints.txt\n+commands =\n+ coverage run {envbindir}/zope-testrunner --all --test-path={toxinidir}/src -s plone.folder {posargs}\n+ coverage report -m --format markdown\n+extras =\n+ test\n'