From ebb6cd9054b519005fb32124cd2ac0d461ca0c00 Mon Sep 17 00:00:00 2001 From: Michael Howitz Date: Tue, 26 Nov 2024 09:12:25 +0100 Subject: [PATCH 1/4] Preliminary support for Python 3.14a2. Fixes #334. --- .github/workflows/tests.yml | 21 +++++++++++++++- .manylinux-install.sh | 13 +++++++--- .meta.toml | 4 +-- CHANGES.rst | 1 + pyproject.toml | 2 +- src/zope/interface/_compat.py | 8 ++++++ src/zope/interface/common/builtins.py | 25 ++++++++++++------- src/zope/interface/common/collections.py | 21 ++++++++++------ .../interface/common/tests/test_builtins.py | 18 ++++++++++--- src/zope/interface/interface.py | 2 ++ tox.ini | 7 ++++-- 11 files changed, 94 insertions(+), 28 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index dccee042..120e9b7e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -103,6 +103,7 @@ jobs: - "3.11" - "3.12" - "3.13" + - "3.14" os: [ubuntu-latest, macos-latest, windows-latest] exclude: - os: macos-latest @@ -152,10 +153,16 @@ jobs: restore-keys: | ${{ runner.os }}-pip- + - name: Install Build Dependencies (3.14) + if: matrix.python-version == '3.14' + run: | + pip install -U pip + pip install -U "setuptools < 74" wheel twine - name: Install Build Dependencies + if: matrix.python-version != '3.14' run: | pip install -U pip - pip install -U "setuptools <74" wheel twine + pip install -U "setuptools < 74" wheel twine - name: Build zope.interface (macOS x86_64) if: > @@ -193,7 +200,15 @@ jobs: python setup.py build_ext -i python setup.py bdist_wheel + - name: Install zope.interface and dependencies (3.14) + if: matrix.python-version == '3.14' + run: | + # Install to collect dependencies into the (pip) cache. + # Use "--pre" here because dependencies with support for this future + # Python release may only be available as pre-releases + pip install --pre .[test] - name: Install zope.interface and dependencies + if: matrix.python-version != '3.14' run: | # Install to collect dependencies into the (pip) cache. pip install .[test] @@ -236,6 +251,7 @@ jobs: && startsWith(github.ref, 'refs/tags') && !startsWith(runner.os, 'Linux') && !startsWith(matrix.python-version, 'pypy') + && !startsWith(matrix.python-version, '3.14') env: TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} run: | @@ -255,6 +271,7 @@ jobs: - "3.11" - "3.12" - "3.13" + - "3.14" os: [ubuntu-latest, macos-latest, windows-latest] exclude: - os: macos-latest @@ -507,6 +524,8 @@ jobs: name: manylinux_${{ matrix.image }}_wheels.zip - name: Restore pip cache permissions run: sudo chown -R $(whoami) ${{ steps.pip-cache-default.outputs.dir }} + - name: Prevent publishing wheels for unreleased Python versions + run: VER=$(echo '3.14' | tr -d .) && ls -al wheelhouse && sudo rm -f wheelhouse/*-cp${VER}*.whl && ls -al wheelhouse - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 if: > diff --git a/.manylinux-install.sh b/.manylinux-install.sh index 7efbd2ed..7a338397 100755 --- a/.manylinux-install.sh +++ b/.manylinux-install.sh @@ -34,6 +34,7 @@ tox_env_map() { *"cp311"*) echo 'py311';; *"cp312"*) echo 'py312';; *"cp313"*) echo 'py313';; + *"cp314"*) echo 'py314';; *) echo 'py';; esac } @@ -46,9 +47,15 @@ for PYBIN in /opt/python/*/bin; do [[ "${PYBIN}" == *"cp310/"* ]] || \ [[ "${PYBIN}" == *"cp311/"* ]] || \ [[ "${PYBIN}" == *"cp312/"* ]] || \ - [[ "${PYBIN}" == *"cp313/"* ]] ; then - "${PYBIN}/pip" install -e /io/ - "${PYBIN}/pip" wheel /io/ -w wheelhouse/ + [[ "${PYBIN}" == *"cp313/"* ]] || \ + [[ "${PYBIN}" == *"cp314/"* ]] ; then + if [[ "${PYBIN}" == *"cp314/"* ]] ; then + "${PYBIN}/pip" install --pre -e /io/ + "${PYBIN}/pip" wheel /io/ --pre -w wheelhouse/ + else + "${PYBIN}/pip" install -e /io/ + "${PYBIN}/pip" wheel /io/ -w wheelhouse/ + fi if [ `uname -m` == 'aarch64' ]; then cd /io/ ${PYBIN}/pip install tox diff --git a/.meta.toml b/.meta.toml index 67fe6188..3fe4302d 100644 --- a/.meta.toml +++ b/.meta.toml @@ -2,13 +2,13 @@ # https://github.com/zopefoundation/meta/tree/master/config/c-code [meta] template = "c-code" -commit-id = "85622de1" +commit-id = "baf6089f" [python] with-pypy = true with-sphinx-doctests = true with-windows = true -with-future-python = false +with-future-python = true with-docs = true with-macos = false diff --git a/CHANGES.rst b/CHANGES.rst index 31355bbd..5a680c26 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,7 @@ 7.1.2 (unreleased) ================== +- Add preliminary support for Python 3.14a2. 7.1.1 (2024-10-23) ================== diff --git a/pyproject.toml b/pyproject.toml index 17da486f..c787aa9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ # https://github.com/zopefoundation/meta/tree/master/config/c-code [build-system] -requires = ["setuptools<74"] +requires = ["setuptools < 74"] build-backend = "setuptools.build_meta" [tool.coverage.run] diff --git a/src/zope/interface/_compat.py b/src/zope/interface/_compat.py index bc3f8671..9ea64442 100644 --- a/src/zope/interface/_compat.py +++ b/src/zope/interface/_compat.py @@ -22,6 +22,14 @@ import sys +PY38 = (3, 8) <= sys.version_info < (3, 9) +PY39 = (3, 9) <= sys.version_info < (3, 10) +PY310 = (3, 10) <= sys.version_info < (3, 11) +PY311 = (3, 11) <= sys.version_info < (3, 12) +PY312 = (3, 12) <= sys.version_info < (3, 13) +PY313 = (3, 13) <= sys.version_info < (3, 14) + + def _normalize_name(name): if isinstance(name, bytes): name = str(name, 'ascii') diff --git a/src/zope/interface/common/builtins.py b/src/zope/interface/common/builtins.py index 09de5b3b..a24fee20 100644 --- a/src/zope/interface/common/builtins.py +++ b/src/zope/interface/common/builtins.py @@ -19,6 +19,12 @@ """ from zope.interface import classImplements +from zope.interface._compat import PY38 +from zope.interface._compat import PY39 +from zope.interface._compat import PY310 +from zope.interface._compat import PY311 +from zope.interface._compat import PY312 +from zope.interface._compat import PY313 from zope.interface.common import collections from zope.interface.common import io from zope.interface.common import numbers @@ -67,17 +73,18 @@ class ITextString(collections.ISequence): extra_classes = (str,) -class IByteString(collections.IByteString): - """ - Interface for immutable byte strings. +if PY38 or PY39 or PY310 or PY311 or PY312 or PY313: + class IByteString(collections.IByteString): + """ + Interface for immutable byte strings. - On all Python versions this is :class:`bytes`. + On all Python versions this is :class:`bytes`. - Unlike :class:`zope.interface.common.collections.IByteString` - (the parent of this interface) this does *not* include - :class:`bytearray`. - """ - extra_classes = (bytes,) + Unlike :class:`zope.interface.common.collections.IByteString` + (the parent of this interface) this does *not* include + :class:`bytearray`. + """ + extra_classes = (bytes,) class INativeString(ITextString): diff --git a/src/zope/interface/common/collections.py b/src/zope/interface/common/collections.py index 543266d9..4d96a31c 100644 --- a/src/zope/interface/common/collections.py +++ b/src/zope/interface/common/collections.py @@ -38,6 +38,12 @@ from collections import UserString from collections import abc +from zope.interface._compat import PY38 +from zope.interface._compat import PY39 +from zope.interface._compat import PY310 +from zope.interface._compat import PY311 +from zope.interface._compat import PY312 +from zope.interface._compat import PY313 from zope.interface.common import ABCInterface from zope.interface.common import optional @@ -190,13 +196,14 @@ class IMutableSequence(ISequence): extra_classes = (UserList,) -class IByteString(ISequence): - """ - This unifies `bytes` and `bytearray`. - """ - abc = _new_in_ver( - 'ByteString', True, (ISequence.getABC(),), (bytes, bytearray), - ) +if PY38 or PY39 or PY310 or PY311 or PY312 or PY313: + class IByteString(ISequence): + """ + This unifies `bytes` and `bytearray`. + """ + abc = _new_in_ver( + 'ByteString', True, (ISequence.getABC(),), (bytes, bytearray), + ) class ISet(ICollection): diff --git a/src/zope/interface/common/tests/test_builtins.py b/src/zope/interface/common/tests/test_builtins.py index cf7019bf..fe0755f2 100644 --- a/src/zope/interface/common/tests/test_builtins.py +++ b/src/zope/interface/common/tests/test_builtins.py @@ -12,6 +12,12 @@ import unittest +from zope.interface._compat import PY38 +from zope.interface._compat import PY39 +from zope.interface._compat import PY310 +from zope.interface._compat import PY311 +from zope.interface._compat import PY312 +from zope.interface._compat import PY313 from zope.interface.common import builtins from . import VerifyClassMixin @@ -24,16 +30,22 @@ class TestVerifyClass(VerifyClassMixin, pass -add_verify_tests(TestVerifyClass, ( +VERIFY_TESTS = [ (builtins.IList, (list,)), (builtins.ITuple, (tuple,)), (builtins.ITextString, (str,)), - (builtins.IByteString, (bytes,)), (builtins.INativeString, (str,)), (builtins.IBool, (bool,)), (builtins.IDict, (dict,)), (builtins.IFile, ()), -)) + +] +if PY38 or PY39 or PY310 or PY311 or PY312 or PY313: + VERIFY_TESTS.append( + (builtins.IByteString, (bytes,)) + ) + +add_verify_tests(TestVerifyClass, tuple(VERIFY_TESTS)) class TestVerifyObject(VerifyObjectMixin, diff --git a/src/zope/interface/interface.py b/src/zope/interface/interface.py index e5dddb88..ad8a7de6 100644 --- a/src/zope/interface/interface.py +++ b/src/zope/interface/interface.py @@ -825,6 +825,8 @@ def update_value(aname, aval): # __firstlineno__: Python 3.13b1+ # https://github.com/python/cpython/pull/118475 '__firstlineno__', + # __classdictcell__: Python 3.14 + '__classdictcell__', ) and aval is not _decorator_non_return # noqa W503 } diff --git a/tox.ini b/tox.ini index ed7830b5..1a686364 100644 --- a/tox.ini +++ b/tox.ini @@ -10,13 +10,16 @@ envlist = py311,py311-pure py312,py312-pure py313,py313-pure + py314,py314-pure pypy3 docs coverage [testenv] +pip_pre = py314: true deps = - setuptools <74 + setuptools < 74 + Sphinx setenv = pure: PURE_PYTHON=1 !pure-!pypy3: PURE_PYTHON=0 @@ -55,7 +58,7 @@ description = ensure that the distribution is ready to release basepython = python3 skip_install = true deps = - setuptools <74 + setuptools < 74 twine build check-manifest From 1f6009f86af7b05a4f7f24cf50e1e46b6aae3283 Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Wed, 27 Nov 2024 09:12:42 +0100 Subject: [PATCH 2/4] - simplify version check for Python 3.14 --- src/zope/interface/_compat.py | 7 +------ src/zope/interface/common/builtins.py | 9 ++------- src/zope/interface/common/collections.py | 9 ++------- src/zope/interface/common/tests/test_builtins.py | 9 ++------- 4 files changed, 7 insertions(+), 27 deletions(-) diff --git a/src/zope/interface/_compat.py b/src/zope/interface/_compat.py index 9ea64442..fb147e15 100644 --- a/src/zope/interface/_compat.py +++ b/src/zope/interface/_compat.py @@ -22,12 +22,7 @@ import sys -PY38 = (3, 8) <= sys.version_info < (3, 9) -PY39 = (3, 9) <= sys.version_info < (3, 10) -PY310 = (3, 10) <= sys.version_info < (3, 11) -PY311 = (3, 11) <= sys.version_info < (3, 12) -PY312 = (3, 12) <= sys.version_info < (3, 13) -PY313 = (3, 13) <= sys.version_info < (3, 14) +PY314_OR_GREATER = sys.version_info >= (3, 14) def _normalize_name(name): diff --git a/src/zope/interface/common/builtins.py b/src/zope/interface/common/builtins.py index a24fee20..bb473de2 100644 --- a/src/zope/interface/common/builtins.py +++ b/src/zope/interface/common/builtins.py @@ -19,12 +19,7 @@ """ from zope.interface import classImplements -from zope.interface._compat import PY38 -from zope.interface._compat import PY39 -from zope.interface._compat import PY310 -from zope.interface._compat import PY311 -from zope.interface._compat import PY312 -from zope.interface._compat import PY313 +from zope.interface._compat import PY314_OR_GREATER from zope.interface.common import collections from zope.interface.common import io from zope.interface.common import numbers @@ -73,7 +68,7 @@ class ITextString(collections.ISequence): extra_classes = (str,) -if PY38 or PY39 or PY310 or PY311 or PY312 or PY313: +if not PY314_OR_GREATER: class IByteString(collections.IByteString): """ Interface for immutable byte strings. diff --git a/src/zope/interface/common/collections.py b/src/zope/interface/common/collections.py index 4d96a31c..25ab31d1 100644 --- a/src/zope/interface/common/collections.py +++ b/src/zope/interface/common/collections.py @@ -38,12 +38,7 @@ from collections import UserString from collections import abc -from zope.interface._compat import PY38 -from zope.interface._compat import PY39 -from zope.interface._compat import PY310 -from zope.interface._compat import PY311 -from zope.interface._compat import PY312 -from zope.interface._compat import PY313 +from zope.interface._compat import PY314_OR_GREATER from zope.interface.common import ABCInterface from zope.interface.common import optional @@ -196,7 +191,7 @@ class IMutableSequence(ISequence): extra_classes = (UserList,) -if PY38 or PY39 or PY310 or PY311 or PY312 or PY313: +if not PY314_OR_GREATER: class IByteString(ISequence): """ This unifies `bytes` and `bytearray`. diff --git a/src/zope/interface/common/tests/test_builtins.py b/src/zope/interface/common/tests/test_builtins.py index fe0755f2..3397839b 100644 --- a/src/zope/interface/common/tests/test_builtins.py +++ b/src/zope/interface/common/tests/test_builtins.py @@ -12,12 +12,7 @@ import unittest -from zope.interface._compat import PY38 -from zope.interface._compat import PY39 -from zope.interface._compat import PY310 -from zope.interface._compat import PY311 -from zope.interface._compat import PY312 -from zope.interface._compat import PY313 +from zope.interface._compat import PY314_OR_GREATER from zope.interface.common import builtins from . import VerifyClassMixin @@ -40,7 +35,7 @@ class TestVerifyClass(VerifyClassMixin, (builtins.IFile, ()), ] -if PY38 or PY39 or PY310 or PY311 or PY312 or PY313: +if not PY314_OR_GREATER: VERIFY_TESTS.append( (builtins.IByteString, (bytes,)) ) From b4b4fcd72cf3a9b2f71f08d2a015b87222807e0e Mon Sep 17 00:00:00 2001 From: Michael Howitz Date: Thu, 28 Nov 2024 08:54:31 +0100 Subject: [PATCH 3/4] Rework version dependent code + add change log. --- CHANGES.rst | 6 +++++- src/zope/interface/_compat.py | 2 +- src/zope/interface/common/builtins.py | 4 ++-- src/zope/interface/common/collections.py | 4 ++-- src/zope/interface/common/tests/test_builtins.py | 4 ++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 5a680c26..46595a81 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,11 @@ 7.1.2 (unreleased) ================== -- Add preliminary support for Python 3.14a2. +- Add preliminary support for Python 3.14a2, this means that + ``.common.builtins.IByteString`` and ``.common.collections.IByteString`` are + no longer available from this version onwards as Python 3.14 dropped + ``collections.abc.ByteString``. + 7.1.1 (2024-10-23) ================== diff --git a/src/zope/interface/_compat.py b/src/zope/interface/_compat.py index fb147e15..38032953 100644 --- a/src/zope/interface/_compat.py +++ b/src/zope/interface/_compat.py @@ -22,7 +22,7 @@ import sys -PY314_OR_GREATER = sys.version_info >= (3, 14) +PY313_OR_OLDER = sys.version_info < (3, 14) def _normalize_name(name): diff --git a/src/zope/interface/common/builtins.py b/src/zope/interface/common/builtins.py index bb473de2..9e543c83 100644 --- a/src/zope/interface/common/builtins.py +++ b/src/zope/interface/common/builtins.py @@ -19,7 +19,7 @@ """ from zope.interface import classImplements -from zope.interface._compat import PY314_OR_GREATER +from zope.interface._compat import PY313_OR_OLDER from zope.interface.common import collections from zope.interface.common import io from zope.interface.common import numbers @@ -68,7 +68,7 @@ class ITextString(collections.ISequence): extra_classes = (str,) -if not PY314_OR_GREATER: +if PY313_OR_OLDER: class IByteString(collections.IByteString): """ Interface for immutable byte strings. diff --git a/src/zope/interface/common/collections.py b/src/zope/interface/common/collections.py index 25ab31d1..defa8a15 100644 --- a/src/zope/interface/common/collections.py +++ b/src/zope/interface/common/collections.py @@ -38,7 +38,7 @@ from collections import UserString from collections import abc -from zope.interface._compat import PY314_OR_GREATER +from zope.interface._compat import PY313_OR_OLDER from zope.interface.common import ABCInterface from zope.interface.common import optional @@ -191,7 +191,7 @@ class IMutableSequence(ISequence): extra_classes = (UserList,) -if not PY314_OR_GREATER: +if PY313_OR_OLDER: class IByteString(ISequence): """ This unifies `bytes` and `bytearray`. diff --git a/src/zope/interface/common/tests/test_builtins.py b/src/zope/interface/common/tests/test_builtins.py index 3397839b..3c764392 100644 --- a/src/zope/interface/common/tests/test_builtins.py +++ b/src/zope/interface/common/tests/test_builtins.py @@ -12,7 +12,7 @@ import unittest -from zope.interface._compat import PY314_OR_GREATER +from zope.interface._compat import PY313_OR_OLDER from zope.interface.common import builtins from . import VerifyClassMixin @@ -35,7 +35,7 @@ class TestVerifyClass(VerifyClassMixin, (builtins.IFile, ()), ] -if not PY314_OR_GREATER: +if PY313_OR_OLDER: VERIFY_TESTS.append( (builtins.IByteString, (bytes,)) ) From 1ae3475264cd7652fc82d4bd7b1c7225b748b198 Mon Sep 17 00:00:00 2001 From: Michael Howitz Date: Thu, 28 Nov 2024 08:56:21 +0100 Subject: [PATCH 4/4] Improve change log. --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 46595a81..87afbc6e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,7 +7,7 @@ - Add preliminary support for Python 3.14a2, this means that ``.common.builtins.IByteString`` and ``.common.collections.IByteString`` are - no longer available from this version onwards as Python 3.14 dropped + no longer available from this Python version onwards as Python 3.14 dropped ``collections.abc.ByteString``.