Skip to content

Commit

Permalink
Preliminary support for Python 3.14a2. (#335)
Browse files Browse the repository at this point in the history
This means that `.common.builtins.IByteString` and `.common.collections.IByteString` are no longer available from this Python version onwards as Python 3.14 dropped `collections.abc.ByteString`.


---------

Co-authored-by: Jens Vagelpohl <[email protected]>
  • Loading branch information
icemac and dataflake authored Nov 28, 2024
1 parent 7e0be48 commit 682b658
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 28 deletions.
21 changes: 20 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ jobs:
- "3.11"
- "3.12"
- "3.13"
- "3.14"
os: [ubuntu-latest, macos-latest, windows-latest]
exclude:
- os: macos-latest
Expand Down Expand Up @@ -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: >
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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: |
Expand All @@ -255,6 +271,7 @@ jobs:
- "3.11"
- "3.12"
- "3.13"
- "3.14"
os: [ubuntu-latest, macos-latest, windows-latest]
exclude:
- os: macos-latest
Expand Down Expand Up @@ -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: >
Expand Down
13 changes: 10 additions & 3 deletions .manylinux-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ tox_env_map() {
*"cp311"*) echo 'py311';;
*"cp312"*) echo 'py312';;
*"cp313"*) echo 'py313';;
*"cp314"*) echo 'py314';;
*) echo 'py';;
esac
}
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions .meta.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
7.1.2 (unreleased)
==================

- Add preliminary support for Python 3.14a2, this means that
``.common.builtins.IByteString`` and ``.common.collections.IByteString`` are
no longer available from this Python version onwards as Python 3.14 dropped
``collections.abc.ByteString``.


7.1.1 (2024-10-23)
==================
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
3 changes: 3 additions & 0 deletions src/zope/interface/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import sys


PY313_OR_OLDER = sys.version_info < (3, 14)


def _normalize_name(name):
if isinstance(name, bytes):
name = str(name, 'ascii')
Expand Down
20 changes: 11 additions & 9 deletions src/zope/interface/common/builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"""

from zope.interface import classImplements
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
Expand Down Expand Up @@ -67,17 +68,18 @@ class ITextString(collections.ISequence):
extra_classes = (str,)


class IByteString(collections.IByteString):
"""
Interface for immutable byte strings.
if PY313_OR_OLDER:
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):
Expand Down
16 changes: 9 additions & 7 deletions src/zope/interface/common/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from collections import UserString
from collections import abc

from zope.interface._compat import PY313_OR_OLDER
from zope.interface.common import ABCInterface
from zope.interface.common import optional

Expand Down Expand Up @@ -190,13 +191,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 PY313_OR_OLDER:
class IByteString(ISequence):
"""
This unifies `bytes` and `bytearray`.
"""
abc = _new_in_ver(
'ByteString', True, (ISequence.getABC(),), (bytes, bytearray),
)


class ISet(ICollection):
Expand Down
13 changes: 10 additions & 3 deletions src/zope/interface/common/tests/test_builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import unittest

from zope.interface._compat import PY313_OR_OLDER
from zope.interface.common import builtins

from . import VerifyClassMixin
Expand All @@ -24,16 +25,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 PY313_OR_OLDER:
VERIFY_TESTS.append(
(builtins.IByteString, (bytes,))
)

add_verify_tests(TestVerifyClass, tuple(VERIFY_TESTS))


class TestVerifyObject(VerifyObjectMixin,
Expand Down
2 changes: 2 additions & 0 deletions src/zope/interface/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
7 changes: 5 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 682b658

Please sign in to comment.