diff --git a/.editorconfig b/.editorconfig index 27282ae..9d3c4f2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -28,7 +28,7 @@ max_line_length = off # 4 space indentation indent_size = 4 -[*.{yml,zpt,pt,dtml}] +[*.{yml,zpt,pt,dtml,zcml}] # 2 space indentation indent_size = 2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6ef90c0..af8c46f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -92,24 +92,26 @@ jobs: # with `test`, and `docs` must use a subset. runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: python-version: - - 2.7 - - 3.5 - - pypy-2.7 - - pypy-3.6 - - 3.6 - - 3.7 - - 3.8 - - 3.9 + - "2.7" + - "3.5" + - "pypy-2.7" + - "pypy-3.7" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + - "3.10" os: [ubuntu-20.04, macos-latest] exclude: - os: macos-latest - python-version: pypy-2.7 + python-version: "pypy-2.7" - os: macos-latest - python-version: pypy-3.6 + python-version: "pypy-3.7" - os: macos-latest - python-version: 3.5 + python-version: "3.5" steps: - name: checkout @@ -167,7 +169,7 @@ jobs: # We cannot 'uses: pypa/gh-action-pypi-publish@v1.4.1' because # that's apparently a container action, and those don't run on # the Mac. - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') && startsWith(runner.os, 'Mac') + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') && startsWith(runner.os, 'Mac') && !startsWith(matrix.python-version, 'pypy') env: TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} run: | @@ -177,24 +179,26 @@ jobs: needs: build-package runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: python-version: - - 2.7 - - 3.5 - - pypy-2.7 - - pypy-3.6 - - 3.6 - - 3.7 - - 3.8 - - 3.9 + - "2.7" + - "3.5" + - "pypy-2.7" + - "pypy-3.7" + - "3.6" + - "3.7" + - "3.8" + - "3.9" + - "3.10" os: [ubuntu-20.04, macos-latest] exclude: - os: macos-latest - python-version: pypy-2.7 + python-version: "pypy-2.7" - os: macos-latest - python-version: pypy-3.6 + python-version: "pypy-3.7" - os: macos-latest - python-version: 3.5 + python-version: "3.5" steps: - name: checkout @@ -270,7 +274,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.9] + python-version: ["3.9"] os: [ubuntu-20.04] steps: @@ -309,8 +313,6 @@ jobs: pip install -U wheel pip install -U coverage pip install -U "`ls dist/zope.interface-*.whl`[docs]" - # Until repoze.sphinx.autointerface supports Sphinx 4.x we cannot use it: - pip install -U "Sphinx < 4" - name: Build docs env: ZOPE_INTERFACE_STRICT_IRO: 1 @@ -318,13 +320,12 @@ jobs: sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest - lint: needs: build-package runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.9] + python-version: ["3.9"] os: [ubuntu-20.04] steps: @@ -376,7 +377,7 @@ jobs: # We use a regular Python matrix entry to share as much code as possible. strategy: matrix: - python-version: [3.9] + python-version: ["3.9"] image: [manylinux2010_x86_64, manylinux2010_i686, manylinux2014_aarch64] steps: @@ -415,13 +416,13 @@ jobs: # The 2010 image is the most recent spec that comes with Python 2.7, # and only up through the tag 2021-02-06-3d322a5 env: - DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }}:2021-02-06-3d322a5 + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }} run: | bash .manylinux.sh - name: Build zope.interface (i686) if: matrix.image == 'manylinux2010_i686' env: - DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }}:2021-02-06-3d322a5 + DOCKER_IMAGE: quay.io/pypa/${{ matrix.image }} PRE_CMD: linux32 run: | bash .manylinux.sh diff --git a/.gitignore b/.gitignore index 24ccc4e..20b2128 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ # Generated from: # https://github.com/zopefoundation/meta/tree/master/config/c-code +*.dll *.egg-info/ *.profraw *.pyc *.pyo +*.so .coverage .coverage.* .eggs/ diff --git a/.manylinux-install.sh b/.manylinux-install.sh index 9287306..3b47736 100755 --- a/.manylinux-install.sh +++ b/.manylinux-install.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code set -e -x @@ -21,14 +23,19 @@ fi ls -ld /cache ls -ld /cache/pip +# We need some libraries because we build wheels from scratch: +yum -y install libffi-devel + # Compile wheels for PYBIN in /opt/python/*/bin; do - if [[ "${PYBIN}" == *"cp27"* ]] || \ + if \ + [[ "${PYBIN}" == *"cp27"* ]] || \ [[ "${PYBIN}" == *"cp35"* ]] || \ [[ "${PYBIN}" == *"cp36"* ]] || \ [[ "${PYBIN}" == *"cp37"* ]] || \ [[ "${PYBIN}" == *"cp38"* ]] || \ - [[ "${PYBIN}" == *"cp39"* ]]; then + [[ "${PYBIN}" == *"cp39"* ]] || \ + [[ "${PYBIN}" == *"cp310"* ]] ; then "${PYBIN}/pip" install -e /io/ "${PYBIN}/pip" wheel /io/ -w wheelhouse/ if [ `uname -m` == 'aarch64' ]; then diff --git a/.manylinux.sh b/.manylinux.sh index 520d68e..ea4ef41 100755 --- a/.manylinux.sh +++ b/.manylinux.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# Generated from: +# https://github.com/zopefoundation/meta/tree/master/config/c-code set -e -x diff --git a/.meta.toml b/.meta.toml index 77e115f..5ff5122 100644 --- a/.meta.toml +++ b/.meta.toml @@ -2,44 +2,30 @@ # https://github.com/zopefoundation/meta/tree/master/config/c-code [meta] template = "c-code" -commit-id = "3ddccc7a1430600364f48f37e4f24a275e1bbb85" +commit-id = "23625f0c67c2171441dbe2069830d3b3fdb17757" [python] with-appveyor = true with-pypy = true with-legacy-python = true -with-docs = false -with-sphinx-doctests = false +with-sphinx-doctests = true +with-windows = false +with-future-python = false +with-docs = true [tox] use-flake8 = false -additional-envlist = [ - "docs", - ] testenv-commands = [ - "coverage run -p -m unittest discover -s src", + "coverage run -p -m unittest discover -s src {posargs}", ] testenv-deps = [ ] testenv-setenv = [ "ZOPE_INTERFACE_STRICT_IRO=1", ] -testenv-additional = [ - "", - "[testenv:docs]", - "basepython = python3", - "# Until repoze.sphinx.autointerface supports Sphinx 4.x we cannot use it:", - "deps =", - " Sphinx < 4", - " coverage", - "extras = docs", - "commands =", - " sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html", - " coverage run -p -m sphinx -b doctest -d docs/_build/doctrees docs docs/_build/doctest", - ] coverage-command = "coverage combine" coverage-additional = [ - "depends = py27,py27-pure,py35,py35-pure,py36,py36-pure,py37,py37-pure,py38,py38-pure,py39,py39-pure,pypy,pypy3,docs", + "depends = py27,py27-pure,py35,py35-pure,py36,py36-pure,py37,py37-pure,py38,py38-pure,py39,py39-pure,py310,py310-pure,pypy,pypy3,docs", "parallel_show_output = true", ] @@ -102,19 +88,6 @@ global-env-vars = [ " TWINE_PASSWORD:", " secure: aoZC/+rvJKg8B5GMGIxd1X2q2bz7SMl8G3810BID9U8PXFqM0FbWaK9fZ9qcU0UyG2xJsK56Fb6+L6g27I0Lg8UFNhlU1zLAuMSgJQbHsqawFgSY067IdJB68pp34d/oEyxMrJvAKENHH77Fe4KGDssLlk5WnnYS3DA9b66p5imP+1DTtkq5/gMtoG4nZTBtVos7J2kkYTQ5t4BjzTQxPMC3bStNnvuuB0orX4AoCyTrOR1wdZFiNKLzbVnrJCNn24t/n3kG9WrxbnKlrbOm4A==", ] -build-script = [ - "- python -W ignore setup.py -q bdist_wheel", - ] test-steps = [ "- python -m unittest discover -s src", ] -additional-lines = [ - "artifacts:", - " - path: 'dist\\*.whl'", - " name: wheel", - "", - "deploy_script:", - " - ps: if ($env:APPVEYOR_REPO_TAG -eq $TRUE) { pip install twine; twine upload --skip-existing dist/* }", - "", - "deploy: on", - ] diff --git a/CHANGES.rst b/CHANGES.rst index 3b4ce94..c650816 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,9 +2,11 @@ Changes ========= -5.4.1 (unreleased) +5.5.0 (unreleased) ================== +- Add support for Python 3.10. + - Add missing Trove classifier showing support for Python 3.9. - Add some more entries to ``zope.interface.interfaces.__all__``. diff --git a/MANIFEST.in b/MANIFEST.in index 7f39b4e..19b3bbd 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,6 +7,11 @@ include tox.ini include appveyor.yml include .coveragerc +recursive-include docs *.py +recursive-include docs *.rst +recursive-include docs *.txt +recursive-include docs Makefile + recursive-include src *.py include *.cmd include *.sh diff --git a/appveyor.yml b/appveyor.yml index 87316b9..40460ef 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,9 @@ # Generated from: # https://github.com/zopefoundation/meta/tree/master/config/c-code environment: - # Currently the builds use @mgedmin's Appveyor account. The PyPI token # belongs to zope.wheelbuilder, which is managed by @mgedmin and @dataflake. - + global: TWINE_USERNAME: __token__ TWINE_PASSWORD: @@ -23,6 +22,8 @@ environment: - python: 38-x64 - python: 39 - python: 39-x64 + - python: 310 + - python: 310-x64 install: - "SET PYTHONVERSION=%PYTHON%" @@ -47,14 +48,11 @@ build_script: test_script: - python -m unittest discover -s src - -on_success: - - echo Build succesful! artifacts: - path: 'dist\*.whl' name: wheel deploy_script: - - ps: if ($env:APPVEYOR_REPO_TAG -eq $TRUE) { pip install twine; twine upload --skip-existing dist/* } + - ps: if ($env:APPVEYOR_REPO_TAG -eq $TRUE) { pip install twine; twine upload --skip-existing dist\*.whl } deploy: on diff --git a/setup.cfg b/setup.cfg index d3ac42a..ce0d540 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,6 +3,9 @@ [bdist_wheel] universal = 1 +[zest.releaser] +create-wheel = no + [flake8] doctests = 1 @@ -10,6 +13,8 @@ doctests = 1 ignore = .editorconfig .meta.toml + docs/_build/html/_sources/* + docs/_build/doctest/* docs/_build/doctest/output.txt docs/_build/html/_sources/* docs/_build/html/_sources/api/* diff --git a/setup.py b/setup.py index b8b8b4a..d92ab8f 100644 --- a/setup.py +++ b/setup.py @@ -100,7 +100,7 @@ long_description = ( ) setup(name='zope.interface', - version='5.4.1.dev0', + version='5.5.0.dev0', url='https://github.com/zopefoundation/zope.interface', license='ZPL 2.1', description='Interfaces for Python', @@ -121,6 +121,7 @@ setup(name='zope.interface', "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Framework :: Zope :: 3", diff --git a/src/zope/interface/common/tests/__init__.py b/src/zope/interface/common/tests/__init__.py index b285ad7..b3bd5be 100644 --- a/src/zope/interface/common/tests/__init__.py +++ b/src/zope/interface/common/tests/__init__.py @@ -81,16 +81,17 @@ def add_verify_tests(cls, iface_classes_iter): sro = implements.__sro__ self.assertIs(sro[-1], Interface) - # Check that we got the strict C3 resolution order, unless we - # know we cannot. Note that 'Interface' is virtual base that doesn't - # necessarily appear at the same place in the calculated SRO as in the - # final SRO. - strict = stdlib_class not in self.NON_STRICT_RO - isro = ro.ro(implements, strict=strict) - isro.remove(Interface) - isro.append(Interface) + if stdlib_class not in self.UNVERIFIABLE_RO: + # Check that we got the strict C3 resolution order, unless + # we know we cannot. Note that 'Interface' is virtual base + # that doesn't necessarily appear at the same place in the + # calculated SRO as in the final SRO. + strict = stdlib_class not in self.NON_STRICT_RO + isro = ro.ro(implements, strict=strict) + isro.remove(Interface) + isro.append(Interface) - self.assertEqual(tuple(isro), sro) + self.assertEqual(tuple(isro), sro) name = 'test_auto_ro_' + suffix test_ro.__name__ = name @@ -101,6 +102,7 @@ class VerifyClassMixin(unittest.TestCase): verifier = staticmethod(verifyClass) UNVERIFIABLE = () NON_STRICT_RO = () + UNVERIFIABLE_RO = () def _adjust_object_before_verify(self, iface, x): return x diff --git a/src/zope/interface/common/tests/test_collections.py b/src/zope/interface/common/tests/test_collections.py index 81eea0e..152626b 100644 --- a/src/zope/interface/common/tests/test_collections.py +++ b/src/zope/interface/common/tests/test_collections.py @@ -11,6 +11,7 @@ ############################################################################## +import array import unittest try: import collections.abc as abc @@ -93,6 +94,10 @@ class TestVerifyClass(VerifyClassMixin, unittest.TestCase): # It's imported because...? Coverage imports it, but why do we have it without # coverage? 'Row', + # In Python 3.10 ``array.array`` appears as ``IMutableSequence`` but it + # does not provide a ``clear()`` method and it cannot be instantiated + # using ``array.array()``. + array.array, } if PYPY: @@ -121,6 +126,14 @@ class TestVerifyClass(VerifyClassMixin, unittest.TestCase): }) NON_STRICT_RO = { } + else: + UNVERIFIABLE_RO = { + # ``array.array`` fails the ``test_auto_ro_*`` tests with and + # without strict RO but only on Windows (AppVeyor) on Python 3.10.0 + # (in older versions ``array.array`` does not appear as + # ``IMutableSequence``). + array.array, + } add_abc_interface_tests(TestVerifyClass, collections.ISet.__module__) @@ -158,3 +171,11 @@ class TestVerifyObject(VerifyObjectMixin, CONSTRUCTORS.update({ collections.IValuesView: {}.viewvalues, }) + else: + UNVERIFIABLE_RO = { + # ``array.array`` fails the ``test_auto_ro_*`` tests with and + # without strict RO but only on Windows (AppVeyor) on Python 3.10.0 + # (in older versions ``array.array`` does not appear as + # ``IMutableSequence``). + array.array, + } diff --git a/tox.ini b/tox.ini index 026d567..f614f3f 100644 --- a/tox.ini +++ b/tox.ini @@ -10,10 +10,11 @@ envlist = py37,py37-pure py38,py38-pure py39,py39-pure + py310,py310-pure pypy pypy3 - coverage docs + coverage [testenv] usedevelop = true @@ -23,20 +24,11 @@ setenv = !pure-!pypy-!pypy3: PURE_PYTHON=0 ZOPE_INTERFACE_STRICT_IRO=1 commands = - coverage run -p -m unittest discover -s src + coverage run -p -m unittest discover -s src {posargs} + !py27-!pypy: sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest extras = test - -[testenv:docs] -basepython = python3 -# Until repoze.sphinx.autointerface supports Sphinx 4.x we cannot use it: -deps = - Sphinx < 4 - coverage -extras = docs -commands = - sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html - coverage run -p -m sphinx -b doctest -d docs/_build/doctrees docs docs/_build/doctest + docs [testenv:coverage] basepython = python3 @@ -44,12 +36,14 @@ allowlist_externals = mkdir deps = coverage +setenv = + PURE_PYTHON=1 commands = mkdir -p {toxinidir}/parts/htmlcov coverage combine coverage html -i coverage report -i -m --fail-under=99 -depends = py27,py27-pure,py35,py35-pure,py36,py36-pure,py37,py37-pure,py38,py38-pure,py39,py39-pure,pypy,pypy3,docs +depends = py27,py27-pure,py35,py35-pure,py36,py36-pure,py37,py37-pure,py38,py38-pure,py39,py39-pure,py310,py310-pure,pypy,pypy3,docs parallel_show_output = true [testenv:lint] @@ -57,7 +51,16 @@ basepython = python3 skip_install = true deps = check-manifest - check-python-versions + check-python-versions >= 0.19.1 + wheel commands = check-manifest check-python-versions + +[testenv:docs] +basepython = python3 +skip_install = false +commands_pre = +commands = + sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html + sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest