diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 325ae0e..9cf4fde 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -15,6 +15,9 @@ env: jobs: pre-commit: + permissions: + contents: read + pull-requests: write name: linting runs-on: ubuntu-latest steps: @@ -22,12 +25,12 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x - - uses: pre-commit/action@v3.0.1 + - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd #v3.0.1 with: extra_args: --all-files --show-diff-on-failure env: PRE_COMMIT_COLOR: always - - uses: pre-commit-ci/lite-action@v1.0.2 + - uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 #v1.1.0 if: always() with: msg: Apply pre-commit code formatting diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9fb059a..1f777a6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ # native support. It works, but is slow. # # Another major downside: You can't just re-run the job for one part -# of the matrix. So if there's a transient test failure that hit, say, 3.8, +# of the matrix. So if there's a transient test failure that hit, say, 3.11, # to get a clean run every version of Python runs again. That's bad. # https://github.community/t/ability-to-rerun-just-a-single-job-in-a-workflow/17234/65 @@ -97,12 +97,12 @@ jobs: matrix: python-version: - "pypy-3.10" - - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" - "3.13" + - "3.14" os: [ubuntu-latest, macos-latest, windows-latest] exclude: - os: macos-latest @@ -111,6 +111,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v4 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: @@ -152,11 +154,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 <= 75.6.0" 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 cffi + pip install -U "setuptools <= 75.6.0" wheel twine pip install -U zope.proxy - name: Build zope.security (macOS x86_64) @@ -195,7 +202,15 @@ jobs: python setup.py build_ext -i python setup.py bdist_wheel + - name: Install zope.security 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.security and dependencies + if: matrix.python-version != '3.14' run: | # Install to collect dependencies into the (pip) cache. pip install .[test] @@ -238,6 +253,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: | @@ -251,12 +267,12 @@ jobs: matrix: python-version: - "pypy-3.10" - - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" - "3.13" + - "3.14" os: [ubuntu-latest, macos-latest, windows-latest] exclude: - os: macos-latest @@ -265,6 +281,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v4 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: @@ -311,9 +329,24 @@ jobs: with: name: zope.security-${{ runner.os }}-${{ matrix.python-version }}.whl path: dist/ + - name: Install zope.security ${{ matrix.python-version }} + if: matrix.python-version == '3.14' + run: | + pip install -U wheel "setuptools <= 75.6.0" + # coverage might have a wheel on PyPI for a future python version which is + # not ABI compatible with the current one, so build it from sdist: + pip install -U --no-binary :all: coverage[toml] + # Unzip into src/ so that testrunner can find the .so files + # when we ask it to load tests from that directory. This + # might also save some build time? + unzip -n dist/zope.security-*whl -d src + # Use "--pre" here because dependencies with support for this future + # Python release may only be available as pre-releases + pip install --pre -e .[test] - name: Install zope.security + if: matrix.python-version != '3.14' run: | - pip install -U wheel "setuptools <74" + pip install -U wheel "setuptools <= 75.6.0" pip install -U coverage[toml] pip install -U 'cffi; platform_python_implementation == "CPython"' # Unzip into src/ so that testrunner can find the .so files @@ -362,6 +395,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v4 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: @@ -420,6 +455,76 @@ 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 + release-check: + needs: build-package + runs-on: "ubuntu-latest" + strategy: + matrix: + python-version: ["3.11"] + os: [ubuntu-latest] + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + allow-prereleases: true + ### + # Caching. + # This actually *restores* a cache and schedules a cleanup action + # to save the cache. So it must come before the thing we want to use + # the cache. + ### + - name: Get pip cache dir (default) + id: pip-cache-default + if: ${{ !startsWith(runner.os, 'Windows') }} + run: | + echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT + + - name: Get pip cache dir (Windows) + id: pip-cache-windows + if: ${{ startsWith(runner.os, 'Windows') }} + run: | + echo "dir=$(pip cache dir)" >> $Env:GITHUB_OUTPUT + + - name: pip cache (default) + uses: actions/cache@v4 + if: ${{ !startsWith(runner.os, 'Windows') }} + with: + path: ${{ steps.pip-cache-default.outputs.dir }} + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: pip cache (Windows) + uses: actions/cache@v4 + if: ${{ startsWith(runner.os, 'Windows') }} + with: + path: ${{ steps.pip-cache-windows.outputs.dir }} + key: ${{ runner.os }}-pip-${{ matrix.python-version }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Download zope.security wheel + uses: actions/download-artifact@v4 + with: + name: zope.security-${{ runner.os }}-${{ matrix.python-version }}.whl + path: dist/ + - name: Install zope.security + run: | + pip install -U wheel + pip install -U tox + pip install -U "`ls dist/zope.security-*.whl`[docs]" + - name: Run release check + env: + ZOPE_INTERFACE_STRICT_IRO: 1 + run: | + tox -e release-check + manylinux: runs-on: ubuntu-latest if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name @@ -432,6 +537,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v4 + with: + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: @@ -507,6 +614,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 498f615..49856b5 100755 --- a/.manylinux-install.sh +++ b/.manylinux-install.sh @@ -28,12 +28,12 @@ yum -y install libffi-devel tox_env_map() { case $1 in - *"cp38"*) echo 'py38';; *"cp39"*) echo 'py39';; *"cp310"*) echo 'py310';; *"cp311"*) echo 'py311';; *"cp312"*) echo 'py312';; *"cp313"*) echo 'py313';; + *"cp314"*) echo 'py314';; *) echo 'py';; esac } @@ -41,14 +41,19 @@ tox_env_map() { # Compile wheels for PYBIN in /opt/python/*/bin; do if \ - [[ "${PYBIN}" == *"cp38/"* ]] || \ [[ "${PYBIN}" == *"cp39/"* ]] || \ [[ "${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 8bb3d52..211981f 100644 --- a/.meta.toml +++ b/.meta.toml @@ -2,12 +2,12 @@ # https://github.com/zopefoundation/meta/tree/master/config/c-code [meta] template = "c-code" -commit-id = "d8a8b5ed" +commit-id = "3c1c588c" [python] with-windows = true with-pypy = true -with-future-python = false +with-future-python = true with-docs = true with-sphinx-doctests = true with-macos = false @@ -15,7 +15,7 @@ with-macos = false [tox] use-flake8 = true additional-envlist = [ - "py38-watch, py311-watch", + "py39-watch, py313-watch", ] testenv-setenv = [ "ZOPE_INTERFACE_STRICT_IRO=1", @@ -53,12 +53,9 @@ additional-config = [ [github-actions] additional-config = [ - "- [\"3.8\", \"py38-watch\"]", - "- [\"3.11\", \"py311-watch\"]", + "- [\"3.8\", \"py39-watch\"]", + "- [\"3.13\", \"py313-watch\"]", ] additional-build-dependencies = [ "zope.proxy", ] - -[c-code] -require-cffi = true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5d6386..7d30407 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,19 +3,19 @@ minimum_pre_commit_version: '3.6' repos: - repo: https://github.com/pycqa/isort - rev: "5.13.2" + rev: "6.0.0" hooks: - id: isort - repo: https://github.com/hhatto/autopep8 - rev: "v2.3.1" + rev: "v2.3.2" hooks: - id: autopep8 args: [--in-place, --aggressive, --aggressive] - repo: https://github.com/asottile/pyupgrade - rev: v3.17.0 + rev: v3.19.1 hooks: - id: pyupgrade - args: [--py38-plus] + args: [--py39-plus] - repo: https://github.com/isidentical/teyit rev: 0.4.3 hooks: diff --git a/CHANGES.rst b/CHANGES.rst index 247c965..0439ecd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,10 @@ 7.4 (unreleased) ---------------- +- Drop support for Python 3.8. + +- Add preliminary support for Python 3.14. + 7.3 (2024-10-02) ---------------- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e6d84b8..5242e6a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ +--> # Contributing to zopefoundation projects The projects under the zopefoundation GitHub organization are open source and diff --git a/pyproject.toml b/pyproject.toml index 59d0adb..32b6507 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,9 @@ # https://github.com/zopefoundation/meta/tree/master/config/c-code [build-system] -requires = ["setuptools<74"] +requires = [ + "setuptools <= 75.6.0", +] build-backend = "setuptools.build_meta" [tool.coverage.run] @@ -16,10 +18,23 @@ fail_under = 99.5 precision = 2 ignore_errors = true show_missing = true -exclude_lines = ["pragma: no cover", "pragma: nocover", "except ImportError:", "raise NotImplementedError", "if __name__ == '__main__':", "self.fail", "raise AssertionError", "raise unittest.Skip"] +exclude_lines = [ + "pragma: no cover", + "pragma: nocover", + "except ImportError:", + "raise NotImplementedError", + "if __name__ == '__main__':", + "self.fail", + "raise AssertionError", + "raise unittest.Skip", +] [tool.coverage.html] directory = "parts/htmlcov" [tool.coverage.paths] -source = ["src/", ".tox/*/lib/python*/site-packages/", ".tox/pypy*/site-packages/"] +source = [ + "src/", + ".tox/*/lib/python*/site-packages/", + ".tox/pypy*/site-packages/", +] diff --git a/setup.py b/setup.py index 98deada..7aea8bb 100644 --- a/setup.py +++ b/setup.py @@ -109,7 +109,7 @@ def read(*rnames): setup(name='zope.security', version=version, author='Zope Foundation and Contributors', - author_email='zope-dev@zope.org', + author_email='zope-dev@zope.dev', description='Zope Security Framework', long_description=( read('README.rst') @@ -124,7 +124,6 @@ def read(*rnames): 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', @@ -144,7 +143,7 @@ def read(*rnames): '/zope.security/issues'), 'Sources': 'https://github.com/zopefoundation/zope.security', }, - license='ZPL 2.1', + license='ZPL-2.1', packages=find_packages('src'), package_dir={'': 'src'}, namespace_packages=['zope'], @@ -152,7 +151,7 @@ def read(*rnames): 'build_ext': optional_build_ext, }, ext_modules=ext_modules, - python_requires='>=3.8', + python_requires='>=3.9', install_requires=[ 'setuptools', 'zope.component', diff --git a/tox.ini b/tox.ini index 3a09c69..f9b8cba 100644 --- a/tox.ini +++ b/tox.ini @@ -3,21 +3,24 @@ [tox] minversion = 4.0 envlist = + release-check lint - py38,py38-pure py39,py39-pure py310,py310-pure py311,py311-pure py312,py312-pure py313,py313-pure + py314,py314-pure pypy3 docs coverage - py38-watch, py311-watch + py39-watch, py313-watch [testenv] +pip_pre = py314: true deps = - setuptools <74 + setuptools <= 75.6.0 + Sphinx setenv = pure: PURE_PYTHON=1 !pure-!pypy3: PURE_PYTHON=0 @@ -54,7 +57,7 @@ description = ensure that the distribution is ready to release basepython = python3 skip_install = true deps = - setuptools <74 + setuptools <= 75.6.0 twine build check-manifest