From ffffd471a800d21ee653698135863f0c83bd097f Mon Sep 17 00:00:00 2001 From: gforcada Date: Sat, 15 Apr 2023 10:34:35 +0200 Subject: [PATCH] [fc] Repository: plone.versioncheck Branch: refs/heads/master Date: 2023-04-14T16:04:17+02:00 Author: Maurits van Rees (mauritsvanrees) Commit: https://github.com/plone/plone.versioncheck/commit/5774bd8c3dce5adf70884a22308af3dd7b2a8372 Ignore invalid versions. Needed for `setuptools` 66 and higher when checking a package that has invalid versions on PyPI. Fixes https://github.com/plone/plone.versioncheck/issues/52. For example it fails on parsing `collective.recipe.template` because it has a version `1.4dev-r93307`. See https://pypi.org/simple/collective-recipe-template/ Files changed: M CHANGES.rst M src/plone/versioncheck/pypi.py Repository: plone.versioncheck Branch: refs/heads/master Date: 2023-04-14T16:26:22+02:00 Author: Maurits van Rees (mauritsvanrees) Commit: https://github.com/plone/plone.versioncheck/commit/98b9d9e1b09bf10cc4a0a10ac366b15d73967f8f Fix linting Files changed: M setup.cfg M setup.py M src/plone/versioncheck/analyser.py M src/plone/versioncheck/formatter.py M src/plone/versioncheck/utils.py M tox.ini Repository: plone.versioncheck Branch: refs/heads/master Date: 2023-04-14T16:38:27+02:00 Author: Maurits van Rees (mauritsvanrees) Commit: https://github.com/plone/plone.versioncheck/commit/887051e6de71a3b314b63d13cb2912d0a048a61c Add classifiers for Python 3.8-3.11. Files changed: M setup.py M tox.ini Repository: plone.versioncheck Branch: refs/heads/master Date: 2023-04-15T10:34:35+02:00 Author: Gil Forcada Codinachs (gforcada) Commit: https://github.com/plone/plone.versioncheck/commit/79b429089d42fb15f094047443ac3c39e2c532f5 Merge pull request #53 from plone/maurits-ignore-invalid-version Ignore invalid versions Files changed: M CHANGES.rst M setup.cfg M setup.py M src/plone/versioncheck/analyser.py M src/plone/versioncheck/formatter.py M src/plone/versioncheck/pypi.py M src/plone/versioncheck/utils.py M tox.ini --- last_commit.txt | 89 ++++++++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/last_commit.txt b/last_commit.txt index a5cf1aacaf..bd6d990780 100644 --- a/last_commit.txt +++ b/last_commit.txt @@ -1,61 +1,82 @@ -Repository: plone.base +Repository: plone.versioncheck -Branch: refs/heads/main -Date: 2023-04-11T13:26:35+02:00 -Author: Jens W. Klein (jensens) -Commit: https://github.com/plone/plone.base/commit/3fa57152dfeb80a49c0c2528fca08be3cf1e1db6 +Branch: refs/heads/master +Date: 2023-04-14T16:04:17+02:00 +Author: Maurits van Rees (mauritsvanrees) +Commit: https://github.com/plone/plone.versioncheck/commit/5774bd8c3dce5adf70884a22308af3dd7b2a8372 -Configuring with plone/meta +Ignore invalid versions. + +Needed for `setuptools` 66 and higher when checking a package that has invalid versions on PyPI. +Fixes https://github.com/plone/plone.versioncheck/issues/52. + +For example it fails on parsing `collective.recipe.template` because it has a version `1.4dev-r93307`. +See https://pypi.org/simple/collective-recipe-template/ + +Files changed: +M CHANGES.rst +M src/plone/versioncheck/pypi.py + +b'diff --git a/CHANGES.rst b/CHANGES.rst\nindex 0253e00..d165d2d 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -4,7 +4,10 @@ Changelog\n 1.7.1 (unreleased)\n ------------------\n \n-- Nothing changed yet.\n+- Ignore invalid versions.\n+ Needed for ``setuptools`` 66 and higher when checking a package that has invalid versions on PyPI.\n+ Fixes `issue 52 `_.\n+ [maurits]\n \n \n 1.7.0 (2019-03-08)\ndiff --git a/src/plone/versioncheck/pypi.py b/src/plone/versioncheck/pypi.py\nindex 0602a35..88b3e04 100644\n--- a/src/plone/versioncheck/pypi.py\n+++ b/src/plone/versioncheck/pypi.py\n@@ -74,7 +74,13 @@ def check(name, version, session): # noqa: C901\n releases = sorted(data["releases"])\n for release in releases:\n # major check (overall)\n- rel_v = parse_version(release)\n+ try:\n+ rel_v = parse_version(release)\n+ except Exception:\n+ # likely pkg_resources.extern.packaging.version.InvalidVersion\n+ # but really any exception can be ignored.\n+ # See https://github.com/plone/plone.versioncheck/issues/52\n+ continue\n if rel_v <= version:\n continue\n rel_vtuple = mmbp_tuple(rel_v)\n' + +Repository: plone.versioncheck + + +Branch: refs/heads/master +Date: 2023-04-14T16:26:22+02:00 +Author: Maurits van Rees (mauritsvanrees) +Commit: https://github.com/plone/plone.versioncheck/commit/98b9d9e1b09bf10cc4a0a10ac366b15d73967f8f + +Fix linting Files changed: -A news/3333c742.internal -M .gitignore -M .meta.toml -M pyproject.toml M setup.cfg -M src/plone/base/interfaces/__init__.py -M src/plone/base/permissions.py +M setup.py +M src/plone/versioncheck/analyser.py +M src/plone/versioncheck/formatter.py +M src/plone/versioncheck/utils.py M tox.ini -b'diff --git a/.gitignore b/.gitignore\nindex e9bb955..9281265 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,3 +1,4 @@\n *.egg-info\n __pycache__\n-venv\n\\ No newline at end of file\n+venv\n+.tox\ndiff --git a/.meta.toml b/.meta.toml\nindex 8560e56..dbe0027 100644\n--- a/.meta.toml\n+++ b/.meta.toml\n@@ -2,12 +2,7 @@\n # https://github.com/plone/meta/tree/master/config/default\n [meta]\n template = "default"\n-commit-id = "13d8d6c0"\n+commit-id = "3333c742"\n \n [codespell]\n additional-ignores = "ist,discreet"\n-\n-[dependencies]\n-mappings = [\n- "Zope = [\'Products.Five\', \'Products.PageTemplates\', \'ZTUtils\']",\n- ]\ndiff --git a/news/3333c742.internal b/news/3333c742.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/3333c742.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 7415149..f573fb5 100644\n--- a/pyproject.toml\n+++ b/pyproject.toml\n@@ -46,4 +46,39 @@ target-version = ["py38"]\n ignore-words-list = "ist,discreet"\n \n [tool.dependencychecker]\n-Zope = [\'Products.Five\', \'Products.PageTemplates\', \'ZTUtils\']\n+Zope = [\n+ # Zope own provided namespaces\n+ \'App\', \'OFS\', \'Products.Five\', \'Products.OFSP\', \'Products.PageTemplates\',\n+ \'Products.SiteAccess\', \'Shared\', \'Testing\', \'ZPublisher\', \'ZTUtils\',\n+ \'Zope2\', \'webdav\', \'zmi\',\n+ # Zope dependencies\n+ \'AccessControl\', \'Acquisition\', \'AuthEncoding\', \'beautifulsoup4\', \'BTrees\',\n+ \'cffi\', \'Chameleon\', \'DateTime\', \'DocumentTemplate\', \'ExtensionClass\',\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 8409376..c444ef0 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -30,26 +30,14 @@ python_requires = >=3.8\n install_requires =\n setuptools\n # be aware to _not_ add dependencies to plone.app.* or Plones Products.* packages!\n- AccessControl\n- Acquisition\n- ZODB\n- Zope>=5\n+ # do not add transitive depndencies covered by CMFCore (which includes Zope)\n+ # see pyproject.toml tool.dependencychecker section for details\n plone.batching\n plone.registry\n plone.schema\n plone.z3cform\n- Products.BTreeFolder2\n Products.CMFCore\n Products.CMFDynamicViewFTI\n- transaction\n- zExceptions\n- zope.component\n- zope.deprecation\n- zope.i18n\n- zope.i18nmessageid\n- zope.interface\n- zope.publisher\n- zope.schema\n namespace_packages =\n plone\n \n@@ -61,27 +49,19 @@ zip_safe = False\n [options.extras_require]\n test =\n plone.subrequest\n- zope.tal\n+ plone.portlets # transitive undeclared by plone.protect (over plone.subrequest)\n+ # remove when https://github.com/plone/plone.protect/pull/99\n+ # is merged and released\n \n [options.packages.find]\n where =\n src\n \n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [bdist_wheel]\n universal = 0\n \n-[check-manifest]\n-ignore =\n- *.cfg\n- *.json\n- *.yml\n- .coveragerc\n- .editorconfig\n- .gitattributes\n- .meta.toml\n- .pre-commit-config.yaml\n- tox.ini\n-\n [flake8]\n doctests = 1\n ignore =\n@@ -93,6 +73,10 @@ ignore =\n E203,\n # black takes care of spaces after commas\n E231,\n-per-file-ignores =\n- src/plone/base/interfaces/__init__.py:F401\n- src/plone/base/permissions.py:F401,E402\n+\n+[check-manifest]\n+ignore =\n+ .editorconfig\n+ .meta.toml\n+ .pre-commit-config.yaml\n+ tox.ini\ndiff --git a/src/plone/base/interfaces/__init__.py b/src/plone/base/interfaces/__init__.py\nindex 23a2530..6cb90ec 100644\n--- a/src/plone/base/interfaces/__init__.py\n+++ b/src/plone/base/interfaces/__init__.py\n@@ -1,63 +1,63 @@\n-from .basetool import IPloneBaseTool\n-from .basetool import IPloneCatalogTool\n-from .basetool import IPloneTool\n-from .breadcrumbs import IHideFromBreadcrumbs\n-from .constrains import IConstrainTypes\n-from .constrains import ISelectableConstrainTypes\n-from .controlpanel import IActionSchema\n-from .controlpanel import IControlPanel\n-from .controlpanel import IDateAndTimeSchema\n-from .controlpanel import IEditingSchema\n-from .controlpanel import IFilterSchema\n-from .controlpanel import IImagingSchema\n-from .controlpanel import ILinkSchema\n-from .controlpanel import ILoginSchema\n-from .controlpanel import IMailSchema\n-from .controlpanel import IMaintenanceSchema\n-from .controlpanel import IMarkupSchema\n-from .controlpanel import INavigationSchema\n-from .controlpanel import INewActionSchema\n-from .controlpanel import ISearchSchema\n-from .controlpanel import ISecuritySchema\n-from .controlpanel import ISiteSchema\n-from .controlpanel import ISocialMediaSchema\n-from .controlpanel import ITinyMCEAdvancedSchema\n-from .controlpanel import ITinyMCELayoutSchema\n-from .controlpanel import ITinyMCEPluginSchema\n-from .controlpanel import ITinyMCEResourceTypesSchema\n-from .controlpanel import ITinyMCESchema\n-from .controlpanel import ITinyMCESpellCheckerSchema\n-from .controlpanel import ITypesSchema\n-from .controlpanel import IUserGroupsSettingsSchema\n-from .events import IConfigurationChangedEvent\n-from .events import IReorderedEvent\n-from .events import ISiteManagerCreatedEvent\n-from .images import IImageScalesAdapter\n-from .images import IImageScalesFieldAdapter\n-from .installable import INonInstallable\n-from .interface import IInterfaceTool\n-from .language import ILanguage\n-from .login import IForcePasswordChange\n-from .login import IInitialLogin\n-from .login import ILogin\n-from .login import ILoginForm\n-from .login import ILoginFormSchema\n-from .login import ILoginHelpForm\n-from .login import ILoginHelpFormSchema\n-from .login import IRedirectAfterLogin\n-from .migration import IMigrationTool\n-from .password_reset import IPasswordResetToolView\n-from .password_reset import IPWResetTool\n-from .patterns import IPatternsSettings\n-from .properties import IPropertiesTool\n-from .properties import ISimpleItemWithProperties\n-from .resources import IBundleRegistry\n-from .resources import IResourceRegistry\n-from .siteroot import IMigratingPloneSiteRoot\n-from .siteroot import INavigationRoot\n-from .siteroot import IPloneSiteRoot\n-from .siteroot import ITestCasePloneSiteRoot\n-from .structure import INonStructuralFolder\n-from .syndication import ISiteSyndicationSettings\n-from .translationservice import ITranslationServiceTool\n-from .workflow import IWorkflowChain\n+from .basetool import IPloneBaseTool # noqa: F401\n+from .basetool import IPloneCatalogTool # noqa: F401\n+from .basetool import IPloneTool # noqa: F401\n+from .breadcrumbs import IHideFromBreadcrumbs # noqa: F401\n+from .constrains import IConstrainTypes # noqa: F401\n+from .constrains import ISelectableConstrainTypes # noqa: F401\n+from .controlpanel import IActionSchema # noqa: F401\n+from .controlpanel import IControlPanel # noqa: F401\n+from .controlpanel import IDateAndTimeSchema # noqa: F401\n+from .controlpanel import IEditingSchema # noqa: F401\n+from .controlpanel import IFilterSchema # noqa: F401\n+from .controlpanel import IImagingSchema # noqa: F401\n+from .controlpanel import ILinkSchema # noqa: F401\n+from .controlpanel import ILoginSchema # noqa: F401\n+from .controlpanel import IMailSchema # noqa: F401\n+from .controlpanel import IMaintenanceSchema # noqa: F401\n+from .controlpanel import IMarkupSchema # noqa: F401\n+from .controlpanel import INavigationSchema # noqa: F401\n+from .controlpanel import INewActionSchema # noqa: F401\n+from .controlpanel import ISearchSchema # noqa: F401\n+from .controlpanel import ISecuritySchema # noqa: F401\n+from .controlpanel import ISiteSchema # noqa: F401\n+from .controlpanel import ISocialMediaSchema # noqa: F401\n+from .controlpanel import ITinyMCEAdvancedSchema # noqa: F401\n+from .controlpanel import ITinyMCELayoutSchema # noqa: F401\n+from .controlpanel import ITinyMCEPluginSchema # noqa: F401\n+from .controlpanel import ITinyMCEResourceTypesSchema # noqa: F401\n+from .controlpanel import ITinyMCESchema # noqa: F401\n+from .controlpanel import ITinyMCESpellCheckerSchema # noqa: F401\n+from .controlpanel import ITypesSchema # noqa: F401\n+from .controlpanel import IUserGroupsSettingsSchema # noqa: F401\n+from .events import IConfigurationChangedEvent # noqa: F401\n+from .events import IReorderedEvent # noqa: F401\n+from .events import ISiteManagerCreatedEvent # noqa: F401\n+from .images import IImageScalesAdapter # noqa: F401\n+from .images import IImageScalesFieldAdapter # noqa: F401\n+from .installable import INonInstallable # noqa: F401\n+from .interface import IInterfaceTool # noqa: F401\n+from .language import ILanguage # noqa: F401\n+from .login import IForcePasswordChange # noqa: F401\n+from .login import IInitialLogin # noqa: F401\n+from .login import ILogin # noqa: F401\n+from .login import ILoginForm # noqa: F401\n+from .login import ILoginFormSchema # noqa: F401\n+from .login import ILoginHelpForm # noqa: F401\n+from .login import ILoginHelpFormSchema # noqa: F401\n+from .login import IRedirectAfterLogin # noqa: F401\n+from .migration import IMigrationTool # noqa: F401\n+from .password_reset import IPasswordResetToolView # noqa: F401\n+from .password_reset import IPWResetTool # noqa: F401\n+from .patterns import IPatternsSettings # noqa: F401\n+from .properties import IPropertiesTool # noqa: F401\n+from .properties import ISimpleItemWithProperties # noqa: F401\n+from .resources import IBundleRegistry # noqa: F401\n+from .resources import IResourceRegistry # noqa: F401\n+from .siteroot import IMigratingPloneSiteRoot # noqa: F401\n+from .siteroot import INavigationRoot # noqa: F401\n+from .siteroot import IPloneSiteRoot # noqa: F401\n+from .siteroot import ITestCasePloneSiteRoot # noqa: F401\n+from .structure import INonStructuralFolder # noqa: F401\n+from .syndication import ISiteSyndicationSettings # noqa: F401\n+from .translationservice import ITranslationServiceTool # noqa: F401\n+from .workflow import IWorkflowChain # noqa: F401\ndiff --git a/src/plone/base/permissions.py b/src/plone/base/permissions.py\nindex d00040f..e04f288 100644\n--- a/src/plone/base/permissions.py\n+++ b/src/plone/base/permissions.py\n@@ -1,3 +1,4 @@\n+# flake8: noqa\n """ CMFPlone product permissions """\n from AccessControl import ModuleSecurityInfo\n \ndiff --git a/tox.ini b/tox.ini\nindex c079715..903851b 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -1,6 +1,8 @@\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@@ -37,15 +39,30 @@ deps =\n graphviz # optional dependency of pipdeptree\n commands =\n dependencychecker\n- sh -c \'pipdeptree --exclude setuptools,pipdeptree,wheel,pipdeptree,z3c.dependencychecker,zope.interface,zope.component --graph-output svg > dependencies.svg\'\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- plone.portlets # undeclared dependency of plone.protect\n -c https://dist.plone.org/release/6.0-dev/constraints.txt\n commands =\n- zope-testrunner --test-path={toxinidir}/src -s plone.base\n+ zope-testrunner --all --test-path={toxinidir}/src -s plone.base {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.base {posargs}\n+ coverage report -m --format markdown\n extras =\n test\n' +b'diff --git a/setup.cfg b/setup.cfg\nindex c23bfde..ae840bc 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -27,26 +27,7 @@ norecursedirs =\n xfail_strict = True\n \n [isort]\n-# Plone Import Coding Conventions settings\n-# (see: https://docs.plone.org/develop/styleguide/python.html#about-imports).\n-# For all possible settings on isort see:\n-# http://isort.readthedocs.io/en/latest/#configuring-isort /\n-# https://github.com/timothycrosley/isort/wiki/isort-Settings\n-force_alphabetical_sort = True\n-force_single_line = True\n-\n-# We want two empty lines after import sections\n-lines_after_imports = 2\n-\n-#\n-line_length = 200\n-\n-# We do not want any files skiped in Plone context, so include __init__.py\n-# which would be excluded by default.\n-not_skip =\n- __init__.py\n-\n-skip =\n+profile = plone\n \n [flake8]\n exclude =\ndiff --git a/setup.py b/setup.py\nindex c6864d4..3a38a3e 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -3,7 +3,7 @@\n from setuptools import setup\n \n \n-version = \'1.7.1.dev0\'\n+version = "1.7.1.dev0"\n \n long_description = "{0}\\n\\n{1}".format(\n open("README.rst").read(), open("CHANGES.rst").read()\ndiff --git a/src/plone/versioncheck/analyser.py b/src/plone/versioncheck/analyser.py\nindex cc07111..28eefa4 100644\n--- a/src/plone/versioncheck/analyser.py\n+++ b/src/plone/versioncheck/analyser.py\n@@ -39,7 +39,7 @@ def is_cfgidx_newer(pkginfo, target_idx):\n \n \n def is_cfg_newer(pkginfo):\n- """ checks if one of the cfg is newer\n+ """checks if one of the cfg is newer\n \n returns boolean\n """\ndiff --git a/src/plone/versioncheck/formatter.py b/src/plone/versioncheck/formatter.py\nindex 91a612d..fc105d9 100644\n--- a/src/plone/versioncheck/formatter.py\n+++ b/src/plone/versioncheck/formatter.py\n@@ -1,5 +1,6 @@\n # -*- coding: utf-8 -*-\n from __future__ import print_function\n+\n from collections import OrderedDict\n from fnmatch import fnmatch\n from jinja2 import Environment\ndiff --git a/src/plone/versioncheck/utils.py b/src/plone/versioncheck/utils.py\nindex 4baea92..a089ec0 100644\n--- a/src/plone/versioncheck/utils.py\n+++ b/src/plone/versioncheck/utils.py\n@@ -79,8 +79,7 @@ def requests_session(nocache=False):\n \n \n def find_relative(extend, relative=""):\n- """the base dir or url and the actual filename as tuple\n- """\n+ """the base dir or url and the actual filename as tuple"""\n if "://" in extend:\n parts = list(urlparse(extend))\n path = parts[2].split("/")\n@@ -98,11 +97,11 @@ def find_relative(extend, relative=""):\n \n \n def get_terminal_size():\n- """ getTerminalSize()\n- - get width and height of console\n- - works on linux,os x,windows,cygwin(windows)\n- originally retrieved from:\n- http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python\n+ """getTerminalSize()\n+ - get width and height of console\n+ - works on linux,os x,windows,cygwin(windows)\n+ originally retrieved from:\n+ http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python\n """\n current_os = platform.system()\n tuple_xy = None\n@@ -120,7 +119,8 @@ def get_terminal_size():\n \n def _get_terminal_size_windows():\n try:\n- from ctypes import windll, create_string_buffer\n+ from ctypes import create_string_buffer\n+ from ctypes import windll\n \n # stdin handle is -10\n # stdout handle is -11\ndiff --git a/tox.ini b/tox.ini\nindex aaf4649..41d160e 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -42,13 +42,13 @@ commands =\n coverage xml\n \n [testenv:isort-apply]\n-basepython = python3.6\n+basepython = python3.8\n skip_install = true\n deps =\n isort\n \n commands =\n- isort --apply --recursive {toxinidir}/src {toxinidir}/tests {posargs}\n+ isort src tests setup.py {posargs}\n \n [testenv:autopep8]\n basepython = python3.6\n@@ -61,16 +61,17 @@ commands =\n autopep8 --verbose --in-place --recursive --aggressive --aggressive {toxinidir}/src {toxinidir}/tests setup.py\n docformatter --in-place --recursive {toxinidir}/src {toxinidir}/tests setup.py\n \n-[lint]\n+[testenv:lint]\n skip_install = true\n-basepython = python3.6\n+basepython = python3.8\n \n deps =\n isort\n- black\n+ black==21.12b0\n+ click<8.1\n \n commands =\n- isort --check-only --recursive {toxinidir}/src {toxinidir}/tests setup.py\n+ isort --check-only src tests setup.py\n black --check src tests setup.py\n \n whitelist_externals =\n@@ -87,7 +88,7 @@ commands =\n \n [testenv:release]\n skip_install = true\n-basepython = python3.6\n+basepython = python3.8\n \n deps =\n zest.releaser[recommended]\n' -Repository: plone.base +Repository: plone.versioncheck -Branch: refs/heads/main -Date: 2023-04-13T17:38:23+02:00 -Author: Jens W. Klein (jensens) -Commit: https://github.com/plone/plone.base/commit/d4562955897ea90f2c930ba734d676738395a73a +Branch: refs/heads/master +Date: 2023-04-14T16:38:27+02:00 +Author: Maurits van Rees (mauritsvanrees) +Commit: https://github.com/plone/plone.versioncheck/commit/887051e6de71a3b314b63d13cb2912d0a048a61c -configure flake8 ignores in setup.cfg (fragile) +Add classifiers for Python 3.8-3.11. Files changed: -M setup.cfg -M src/plone/base/interfaces/__init__.py -M src/plone/base/permissions.py +M setup.py +M tox.ini -b'diff --git a/setup.cfg b/setup.cfg\nindex c444ef0..e35fcef 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -73,6 +73,9 @@ ignore =\n E203,\n # black takes care of spaces after commas\n E231,\n+per-file-ignores =\n+ src/plone/base/interfaces/__init__.py:F401\n+ src/plone/base/permissions.py:F401,E402\n \n [check-manifest]\n ignore =\ndiff --git a/src/plone/base/interfaces/__init__.py b/src/plone/base/interfaces/__init__.py\nindex 6cb90ec..23a2530 100644\n--- a/src/plone/base/interfaces/__init__.py\n+++ b/src/plone/base/interfaces/__init__.py\n@@ -1,63 +1,63 @@\n-from .basetool import IPloneBaseTool # noqa: F401\n-from .basetool import IPloneCatalogTool # noqa: F401\n-from .basetool import IPloneTool # noqa: F401\n-from .breadcrumbs import IHideFromBreadcrumbs # noqa: F401\n-from .constrains import IConstrainTypes # noqa: F401\n-from .constrains import ISelectableConstrainTypes # noqa: F401\n-from .controlpanel import IActionSchema # noqa: F401\n-from .controlpanel import IControlPanel # noqa: F401\n-from .controlpanel import IDateAndTimeSchema # noqa: F401\n-from .controlpanel import IEditingSchema # noqa: F401\n-from .controlpanel import IFilterSchema # noqa: F401\n-from .controlpanel import IImagingSchema # noqa: F401\n-from .controlpanel import ILinkSchema # noqa: F401\n-from .controlpanel import ILoginSchema # noqa: F401\n-from .controlpanel import IMailSchema # noqa: F401\n-from .controlpanel import IMaintenanceSchema # noqa: F401\n-from .controlpanel import IMarkupSchema # noqa: F401\n-from .controlpanel import INavigationSchema # noqa: F401\n-from .controlpanel import INewActionSchema # noqa: F401\n-from .controlpanel import ISearchSchema # noqa: F401\n-from .controlpanel import ISecuritySchema # noqa: F401\n-from .controlpanel import ISiteSchema # noqa: F401\n-from .controlpanel import ISocialMediaSchema # noqa: F401\n-from .controlpanel import ITinyMCEAdvancedSchema # noqa: F401\n-from .controlpanel import ITinyMCELayoutSchema # noqa: F401\n-from .controlpanel import ITinyMCEPluginSchema # noqa: F401\n-from .controlpanel import ITinyMCEResourceTypesSchema # noqa: F401\n-from .controlpanel import ITinyMCESchema # noqa: F401\n-from .controlpanel import ITinyMCESpellCheckerSchema # noqa: F401\n-from .controlpanel import ITypesSchema # noqa: F401\n-from .controlpanel import IUserGroupsSettingsSchema # noqa: F401\n-from .events import IConfigurationChangedEvent # noqa: F401\n-from .events import IReorderedEvent # noqa: F401\n-from .events import ISiteManagerCreatedEvent # noqa: F401\n-from .images import IImageScalesAdapter # noqa: F401\n-from .images import IImageScalesFieldAdapter # noqa: F401\n-from .installable import INonInstallable # noqa: F401\n-from .interface import IInterfaceTool # noqa: F401\n-from .language import ILanguage # noqa: F401\n-from .login import IForcePasswordChange # noqa: F401\n-from .login import IInitialLogin # noqa: F401\n-from .login import ILogin # noqa: F401\n-from .login import ILoginForm # noqa: F401\n-from .login import ILoginFormSchema # noqa: F401\n-from .login import ILoginHelpForm # noqa: F401\n-from .login import ILoginHelpFormSchema # noqa: F401\n-from .login import IRedirectAfterLogin # noqa: F401\n-from .migration import IMigrationTool # noqa: F401\n-from .password_reset import IPasswordResetToolView # noqa: F401\n-from .password_reset import IPWResetTool # noqa: F401\n-from .patterns import IPatternsSettings # noqa: F401\n-from .properties import IPropertiesTool # noqa: F401\n-from .properties import ISimpleItemWithProperties # noqa: F401\n-from .resources import IBundleRegistry # noqa: F401\n-from .resources import IResourceRegistry # noqa: F401\n-from .siteroot import IMigratingPloneSiteRoot # noqa: F401\n-from .siteroot import INavigationRoot # noqa: F401\n-from .siteroot import IPloneSiteRoot # noqa: F401\n-from .siteroot import ITestCasePloneSiteRoot # noqa: F401\n-from .structure import INonStructuralFolder # noqa: F401\n-from .syndication import ISiteSyndicationSettings # noqa: F401\n-from .translationservice import ITranslationServiceTool # noqa: F401\n-from .workflow import IWorkflowChain # noqa: F401\n+from .basetool import IPloneBaseTool\n+from .basetool import IPloneCatalogTool\n+from .basetool import IPloneTool\n+from .breadcrumbs import IHideFromBreadcrumbs\n+from .constrains import IConstrainTypes\n+from .constrains import ISelectableConstrainTypes\n+from .controlpanel import IActionSchema\n+from .controlpanel import IControlPanel\n+from .controlpanel import IDateAndTimeSchema\n+from .controlpanel import IEditingSchema\n+from .controlpanel import IFilterSchema\n+from .controlpanel import IImagingSchema\n+from .controlpanel import ILinkSchema\n+from .controlpanel import ILoginSchema\n+from .controlpanel import IMailSchema\n+from .controlpanel import IMaintenanceSchema\n+from .controlpanel import IMarkupSchema\n+from .controlpanel import INavigationSchema\n+from .controlpanel import INewActionSchema\n+from .controlpanel import ISearchSchema\n+from .controlpanel import ISecuritySchema\n+from .controlpanel import ISiteSchema\n+from .controlpanel import ISocialMediaSchema\n+from .controlpanel import ITinyMCEAdvancedSchema\n+from .controlpanel import ITinyMCELayoutSchema\n+from .controlpanel import ITinyMCEPluginSchema\n+from .controlpanel import ITinyMCEResourceTypesSchema\n+from .controlpanel import ITinyMCESchema\n+from .controlpanel import ITinyMCESpellCheckerSchema\n+from .controlpanel import ITypesSchema\n+from .controlpanel import IUserGroupsSettingsSchema\n+from .events import IConfigurationChangedEvent\n+from .events import IReorderedEvent\n+from .events import ISiteManagerCreatedEvent\n+from .images import IImageScalesAdapter\n+from .images import IImageScalesFieldAdapter\n+from .installable import INonInstallable\n+from .interface import IInterfaceTool\n+from .language import ILanguage\n+from .login import IForcePasswordChange\n+from .login import IInitialLogin\n+from .login import ILogin\n+from .login import ILoginForm\n+from .login import ILoginFormSchema\n+from .login import ILoginHelpForm\n+from .login import ILoginHelpFormSchema\n+from .login import IRedirectAfterLogin\n+from .migration import IMigrationTool\n+from .password_reset import IPasswordResetToolView\n+from .password_reset import IPWResetTool\n+from .patterns import IPatternsSettings\n+from .properties import IPropertiesTool\n+from .properties import ISimpleItemWithProperties\n+from .resources import IBundleRegistry\n+from .resources import IResourceRegistry\n+from .siteroot import IMigratingPloneSiteRoot\n+from .siteroot import INavigationRoot\n+from .siteroot import IPloneSiteRoot\n+from .siteroot import ITestCasePloneSiteRoot\n+from .structure import INonStructuralFolder\n+from .syndication import ISiteSyndicationSettings\n+from .translationservice import ITranslationServiceTool\n+from .workflow import IWorkflowChain\ndiff --git a/src/plone/base/permissions.py b/src/plone/base/permissions.py\nindex e04f288..d00040f 100644\n--- a/src/plone/base/permissions.py\n+++ b/src/plone/base/permissions.py\n@@ -1,4 +1,3 @@\n-# flake8: noqa\n """ CMFPlone product permissions """\n from AccessControl import ModuleSecurityInfo\n \n' +b'diff --git a/setup.py b/setup.py\nindex 3a38a3e..4f07bb2 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -28,6 +28,10 @@\n "Programming Language :: Python :: 3",\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 "Programming Language :: Python",\n "Topic :: Software Development :: Build Tools",\n "Topic :: Software Development :: Quality Assurance",\ndiff --git a/tox.ini b/tox.ini\nindex 41d160e..953c178 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -3,6 +3,11 @@ envlist =\n py27,\n py36,\n py37,\n+ py38,\n+ py39,\n+# These currently fail because they get setuptools 66+:\n+# py310,\n+# py311,\n pypy,\n lint,\n coverage-report,\n' -Repository: plone.base +Repository: plone.versioncheck -Branch: refs/heads/main -Date: 2023-04-15T09:41:34+02:00 +Branch: refs/heads/master +Date: 2023-04-15T10:34:35+02:00 Author: Gil Forcada Codinachs (gforcada) -Commit: https://github.com/plone/plone.base/commit/08f2a275bf95d9c5764f4e6e57ce37a2720f4ab5 +Commit: https://github.com/plone/plone.versioncheck/commit/79b429089d42fb15f094047443ac3c39e2c532f5 -Merge pull request #34 from plone/config-with-default-template-38fe6d57 +Merge pull request #53 from plone/maurits-ignore-invalid-version -Configuring with plone/meta +Ignore invalid versions Files changed: -A news/3333c742.internal -M .gitignore -M .meta.toml -M pyproject.toml +M CHANGES.rst M setup.cfg +M setup.py +M src/plone/versioncheck/analyser.py +M src/plone/versioncheck/formatter.py +M src/plone/versioncheck/pypi.py +M src/plone/versioncheck/utils.py M tox.ini -b'diff --git a/.gitignore b/.gitignore\nindex e9bb955..9281265 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,3 +1,4 @@\n *.egg-info\n __pycache__\n-venv\n\\ No newline at end of file\n+venv\n+.tox\ndiff --git a/.meta.toml b/.meta.toml\nindex 8560e56..dbe0027 100644\n--- a/.meta.toml\n+++ b/.meta.toml\n@@ -2,12 +2,7 @@\n # https://github.com/plone/meta/tree/master/config/default\n [meta]\n template = "default"\n-commit-id = "13d8d6c0"\n+commit-id = "3333c742"\n \n [codespell]\n additional-ignores = "ist,discreet"\n-\n-[dependencies]\n-mappings = [\n- "Zope = [\'Products.Five\', \'Products.PageTemplates\', \'ZTUtils\']",\n- ]\ndiff --git a/news/3333c742.internal b/news/3333c742.internal\nnew file mode 100644\nindex 0000000..c08f539\n--- /dev/null\n+++ b/news/3333c742.internal\n@@ -0,0 +1,2 @@\n+Update configuration files.\n+[plone devs]\ndiff --git a/pyproject.toml b/pyproject.toml\nindex 7415149..f573fb5 100644\n--- a/pyproject.toml\n+++ b/pyproject.toml\n@@ -46,4 +46,39 @@ target-version = ["py38"]\n ignore-words-list = "ist,discreet"\n \n [tool.dependencychecker]\n-Zope = [\'Products.Five\', \'Products.PageTemplates\', \'ZTUtils\']\n+Zope = [\n+ # Zope own provided namespaces\n+ \'App\', \'OFS\', \'Products.Five\', \'Products.OFSP\', \'Products.PageTemplates\',\n+ \'Products.SiteAccess\', \'Shared\', \'Testing\', \'ZPublisher\', \'ZTUtils\',\n+ \'Zope2\', \'webdav\', \'zmi\',\n+ # Zope dependencies\n+ \'AccessControl\', \'Acquisition\', \'AuthEncoding\', \'beautifulsoup4\', \'BTrees\',\n+ \'cffi\', \'Chameleon\', \'DateTime\', \'DocumentTemplate\', \'ExtensionClass\',\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 8409376..e35fcef 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -30,26 +30,14 @@ python_requires = >=3.8\n install_requires =\n setuptools\n # be aware to _not_ add dependencies to plone.app.* or Plones Products.* packages!\n- AccessControl\n- Acquisition\n- ZODB\n- Zope>=5\n+ # do not add transitive depndencies covered by CMFCore (which includes Zope)\n+ # see pyproject.toml tool.dependencychecker section for details\n plone.batching\n plone.registry\n plone.schema\n plone.z3cform\n- Products.BTreeFolder2\n Products.CMFCore\n Products.CMFDynamicViewFTI\n- transaction\n- zExceptions\n- zope.component\n- zope.deprecation\n- zope.i18n\n- zope.i18nmessageid\n- zope.interface\n- zope.publisher\n- zope.schema\n namespace_packages =\n plone\n \n@@ -61,27 +49,19 @@ zip_safe = False\n [options.extras_require]\n test =\n plone.subrequest\n- zope.tal\n+ plone.portlets # transitive undeclared by plone.protect (over plone.subrequest)\n+ # remove when https://github.com/plone/plone.protect/pull/99\n+ # is merged and released\n \n [options.packages.find]\n where =\n src\n \n+# Generated from:\n+# https://github.com/plone/meta/tree/master/config/default\n [bdist_wheel]\n universal = 0\n \n-[check-manifest]\n-ignore =\n- *.cfg\n- *.json\n- *.yml\n- .coveragerc\n- .editorconfig\n- .gitattributes\n- .meta.toml\n- .pre-commit-config.yaml\n- tox.ini\n-\n [flake8]\n doctests = 1\n ignore =\n@@ -96,3 +76,10 @@ ignore =\n per-file-ignores =\n src/plone/base/interfaces/__init__.py:F401\n src/plone/base/permissions.py:F401,E402\n+\n+[check-manifest]\n+ignore =\n+ .editorconfig\n+ .meta.toml\n+ .pre-commit-config.yaml\n+ tox.ini\ndiff --git a/tox.ini b/tox.ini\nindex c079715..903851b 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -1,6 +1,8 @@\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@@ -37,15 +39,30 @@ deps =\n graphviz # optional dependency of pipdeptree\n commands =\n dependencychecker\n- sh -c \'pipdeptree --exclude setuptools,pipdeptree,wheel,pipdeptree,z3c.dependencychecker,zope.interface,zope.component --graph-output svg > dependencies.svg\'\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- plone.portlets # undeclared dependency of plone.protect\n -c https://dist.plone.org/release/6.0-dev/constraints.txt\n commands =\n- zope-testrunner --test-path={toxinidir}/src -s plone.base\n+ zope-testrunner --all --test-path={toxinidir}/src -s plone.base {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.base {posargs}\n+ coverage report -m --format markdown\n extras =\n test\n' +b'diff --git a/CHANGES.rst b/CHANGES.rst\nindex 0253e00..d165d2d 100644\n--- a/CHANGES.rst\n+++ b/CHANGES.rst\n@@ -4,7 +4,10 @@ Changelog\n 1.7.1 (unreleased)\n ------------------\n \n-- Nothing changed yet.\n+- Ignore invalid versions.\n+ Needed for ``setuptools`` 66 and higher when checking a package that has invalid versions on PyPI.\n+ Fixes `issue 52 `_.\n+ [maurits]\n \n \n 1.7.0 (2019-03-08)\ndiff --git a/setup.cfg b/setup.cfg\nindex c23bfde..ae840bc 100644\n--- a/setup.cfg\n+++ b/setup.cfg\n@@ -27,26 +27,7 @@ norecursedirs =\n xfail_strict = True\n \n [isort]\n-# Plone Import Coding Conventions settings\n-# (see: https://docs.plone.org/develop/styleguide/python.html#about-imports).\n-# For all possible settings on isort see:\n-# http://isort.readthedocs.io/en/latest/#configuring-isort /\n-# https://github.com/timothycrosley/isort/wiki/isort-Settings\n-force_alphabetical_sort = True\n-force_single_line = True\n-\n-# We want two empty lines after import sections\n-lines_after_imports = 2\n-\n-#\n-line_length = 200\n-\n-# We do not want any files skiped in Plone context, so include __init__.py\n-# which would be excluded by default.\n-not_skip =\n- __init__.py\n-\n-skip =\n+profile = plone\n \n [flake8]\n exclude =\ndiff --git a/setup.py b/setup.py\nindex c6864d4..4f07bb2 100644\n--- a/setup.py\n+++ b/setup.py\n@@ -3,7 +3,7 @@\n from setuptools import setup\n \n \n-version = \'1.7.1.dev0\'\n+version = "1.7.1.dev0"\n \n long_description = "{0}\\n\\n{1}".format(\n open("README.rst").read(), open("CHANGES.rst").read()\n@@ -28,6 +28,10 @@\n "Programming Language :: Python :: 3",\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 "Programming Language :: Python",\n "Topic :: Software Development :: Build Tools",\n "Topic :: Software Development :: Quality Assurance",\ndiff --git a/src/plone/versioncheck/analyser.py b/src/plone/versioncheck/analyser.py\nindex cc07111..28eefa4 100644\n--- a/src/plone/versioncheck/analyser.py\n+++ b/src/plone/versioncheck/analyser.py\n@@ -39,7 +39,7 @@ def is_cfgidx_newer(pkginfo, target_idx):\n \n \n def is_cfg_newer(pkginfo):\n- """ checks if one of the cfg is newer\n+ """checks if one of the cfg is newer\n \n returns boolean\n """\ndiff --git a/src/plone/versioncheck/formatter.py b/src/plone/versioncheck/formatter.py\nindex 91a612d..fc105d9 100644\n--- a/src/plone/versioncheck/formatter.py\n+++ b/src/plone/versioncheck/formatter.py\n@@ -1,5 +1,6 @@\n # -*- coding: utf-8 -*-\n from __future__ import print_function\n+\n from collections import OrderedDict\n from fnmatch import fnmatch\n from jinja2 import Environment\ndiff --git a/src/plone/versioncheck/pypi.py b/src/plone/versioncheck/pypi.py\nindex 0602a35..88b3e04 100644\n--- a/src/plone/versioncheck/pypi.py\n+++ b/src/plone/versioncheck/pypi.py\n@@ -74,7 +74,13 @@ def check(name, version, session): # noqa: C901\n releases = sorted(data["releases"])\n for release in releases:\n # major check (overall)\n- rel_v = parse_version(release)\n+ try:\n+ rel_v = parse_version(release)\n+ except Exception:\n+ # likely pkg_resources.extern.packaging.version.InvalidVersion\n+ # but really any exception can be ignored.\n+ # See https://github.com/plone/plone.versioncheck/issues/52\n+ continue\n if rel_v <= version:\n continue\n rel_vtuple = mmbp_tuple(rel_v)\ndiff --git a/src/plone/versioncheck/utils.py b/src/plone/versioncheck/utils.py\nindex 4baea92..a089ec0 100644\n--- a/src/plone/versioncheck/utils.py\n+++ b/src/plone/versioncheck/utils.py\n@@ -79,8 +79,7 @@ def requests_session(nocache=False):\n \n \n def find_relative(extend, relative=""):\n- """the base dir or url and the actual filename as tuple\n- """\n+ """the base dir or url and the actual filename as tuple"""\n if "://" in extend:\n parts = list(urlparse(extend))\n path = parts[2].split("/")\n@@ -98,11 +97,11 @@ def find_relative(extend, relative=""):\n \n \n def get_terminal_size():\n- """ getTerminalSize()\n- - get width and height of console\n- - works on linux,os x,windows,cygwin(windows)\n- originally retrieved from:\n- http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python\n+ """getTerminalSize()\n+ - get width and height of console\n+ - works on linux,os x,windows,cygwin(windows)\n+ originally retrieved from:\n+ http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python\n """\n current_os = platform.system()\n tuple_xy = None\n@@ -120,7 +119,8 @@ def get_terminal_size():\n \n def _get_terminal_size_windows():\n try:\n- from ctypes import windll, create_string_buffer\n+ from ctypes import create_string_buffer\n+ from ctypes import windll\n \n # stdin handle is -10\n # stdout handle is -11\ndiff --git a/tox.ini b/tox.ini\nindex aaf4649..953c178 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -3,6 +3,11 @@ envlist =\n py27,\n py36,\n py37,\n+ py38,\n+ py39,\n+# These currently fail because they get setuptools 66+:\n+# py310,\n+# py311,\n pypy,\n lint,\n coverage-report,\n@@ -42,13 +47,13 @@ commands =\n coverage xml\n \n [testenv:isort-apply]\n-basepython = python3.6\n+basepython = python3.8\n skip_install = true\n deps =\n isort\n \n commands =\n- isort --apply --recursive {toxinidir}/src {toxinidir}/tests {posargs}\n+ isort src tests setup.py {posargs}\n \n [testenv:autopep8]\n basepython = python3.6\n@@ -61,16 +66,17 @@ commands =\n autopep8 --verbose --in-place --recursive --aggressive --aggressive {toxinidir}/src {toxinidir}/tests setup.py\n docformatter --in-place --recursive {toxinidir}/src {toxinidir}/tests setup.py\n \n-[lint]\n+[testenv:lint]\n skip_install = true\n-basepython = python3.6\n+basepython = python3.8\n \n deps =\n isort\n- black\n+ black==21.12b0\n+ click<8.1\n \n commands =\n- isort --check-only --recursive {toxinidir}/src {toxinidir}/tests setup.py\n+ isort --check-only src tests setup.py\n black --check src tests setup.py\n \n whitelist_externals =\n@@ -87,7 +93,7 @@ commands =\n \n [testenv:release]\n skip_install = true\n-basepython = python3.6\n+basepython = python3.8\n \n deps =\n zest.releaser[recommended]\n'