From: Ben Darnell Date: Wed, 20 Aug 2025 18:37:14 +0000 (-0400) Subject: setup: Use cog to automate the annual chore of updating Python versions X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F3536%2Fhead;p=thirdparty%2Ftornado.git setup: Use cog to automate the annual chore of updating Python versions We must specify our supported python versions in a variety of places and formats, so use cog to update them all at once. This commit drops support for Python 3.9, which will no longer be supported by the time of the next release, and formalizes support for Python 3.14. --- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8355230f..e8e1a2cf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,9 @@ on: permissions: {} env: + # [[[cog cog.outl(f"python-version: '3.{default_python_minor}'")]]] python-version: '3.13' + # [[[end]]] jobs: build_sdist: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5b89c3b6..e6d7ac3e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,13 +25,16 @@ jobs: - uses: actions/setup-python@v5 name: Install Python with: - # Lint python version must be synced with tox.ini + # [[[cog cog.outl(f"python-version: '3.{default_python_minor}'")]]] python-version: '3.13' + # [[[end]]] - name: Install tox run: python -m pip install tox -c requirements.txt - name: Run test suite + # [[[cog cog.outl(f"run: python -m tox -e py3{default_python_minor},lint")]]] run: python -m tox -e py313,lint + # [[[end]]] test_tox: name: Run full tests @@ -40,34 +43,58 @@ jobs: strategy: matrix: include: - - python: '3.9' - tox_env: py39-full + # [[[cog + # configs = [] + # for minor in range(int(min_python_minor), int(max_python_minor) + 1): + # if minor == int(dev_python_minor): + # # For python versions in development, specify a range so we install + # # a final version if available, otherwise a prerelease. + # # The .0 is necessary here for unclear reasons. + # configs.append((f"3.{minor}.0-dev - 3.{minor}", f"py3{minor}")) + # else: + # configs.append((f"3.{minor}", f"py3{minor}-full")) + # if int(min_python_threaded_minor) <= minor <= int(max_python_threaded_minor): + # if minor == int(dev_python_minor): + # # The range trick above doesn't work for threaded builds, so we'll + # # just be stuck with last prerelease until we update dev_python_minor. + # configs.append((f"3.{minor}t-dev", f"py3{minor}")) + # else: + # configs.append((f"3.{minor}t", f"py3{minor}")) + # # Early versions of 3.10 and 3.11 had different deprecation + # # warnings in asyncio. Test with them too to make sure everything + # # works the same way. + # configs.append(("3.10.8", "py310-full")) + # configs.append(("3.11.0", "py311-full")) + # # Pypy is a lot slower due to jit warmup costs, so don't run the + # # "full" test config there. + # configs.append(("pypy-3.10", "pypy3")) + # # Docs python version must be synced with tox.ini + # configs.append((f"3.{default_python_minor}", "docs")) + # for version, tox_env in configs: + # cog.outl(f" - python: '{version}'") + # cog.outl(f" tox_env: {tox_env}") + # ]]] - python: '3.10' tox_env: py310-full - - python: '3.10.8' - # Early versions of 3.10 and 3.11 had different deprecation - # warnings in asyncio. Test with them too to make sure everything - # works the same way. - tox_env: py310-full - python: '3.11' tox_env: py311-full - - python: '3.11.0' - tox_env: py311-full - python: '3.12' tox_env: py312-full - python: '3.13' tox_env: py313-full - - python: '3.14.0-rc.1 - 3.14' - tox_env: py314-full + - python: '3.14.0-dev - 3.14' + tox_env: py314 - python: '3.14t-dev' - tox_env: py314t + tox_env: py314 + - python: '3.10.8' + tox_env: py310-full + - python: '3.11.0' + tox_env: py311-full - python: 'pypy-3.10' - # Pypy is a lot slower due to jit warmup costs, so don't run the - # "full" test config there. tox_env: pypy3 - python: '3.13' - # Docs python version must be synced with tox.ini tox_env: docs + # [[[end]]] steps: - uses: actions/checkout@v4 @@ -101,7 +128,9 @@ jobs: - uses: actions/setup-python@v5 name: Install Python with: + # [[[cog cog.outl(f"python-version: '3.{default_python_minor}'")]]] python-version: '3.13' + # [[[end]]] - name: Run test suite # TODO: figure out what's up with these log messages run: py -m tornado.test --fail-if-logs=false @@ -141,4 +170,6 @@ jobs: # For speed, we only build one python version and one arch. We throw away the wheels # built here; the real build is defined in build.yml. CIBW_ARCHS: native + # [[[cog cog.outl(f"CIBW_BUILD: cp3{default_python_minor}-manylinux*")]]] CIBW_BUILD: cp313-manylinux* + # [[[end]]] diff --git a/docs/index.rst b/docs/index.rst index 9b121862..9b3df09f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -99,7 +99,7 @@ installed in this way, so you may wish to download a copy of the source tarball or clone the `git repository `_ as well. -**Prerequisites**: Tornado 6.3 requires Python 3.9 or newer. The following +**Prerequisites**: Tornado requires Python 3. The following optional packages may be useful: * `pycurl `_ is used by the optional diff --git a/maint/scripts/runcog.sh b/maint/scripts/runcog.sh new file mode 100755 index 00000000..0314bfb4 --- /dev/null +++ b/maint/scripts/runcog.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# max/min_python_minor are the range of Python 3.x versions we support. +# max_min_python_threaded_minor are the range of free-threaded python +# versions we support. +# default_python_minor is used in various parts of the build/CI pipeline, +# most significantly in the docs and lint builds which can be sensitive +# to minor version changes. We use the same version for all miscellaneous +# tasks for consistency. +# dev_python_minor is the version of Python that is currently under development +# and is used to install pre-release versions of Python in CI. +uvx --from cogapp cog \ + -D min_python_minor=10 \ + -D max_python_minor=14 \ + -D min_python_threaded_minor=14 \ + -D max_python_threaded_minor=14 \ + -D default_python_minor=13 \ + -D dev_python_minor=14 \ + -r $(git grep -l '\[\[\[cog') diff --git a/pyproject.toml b/pyproject.toml index c8f2c2ca..7e6b3174 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,10 +3,20 @@ requires = ["setuptools"] build-backend = "setuptools.build_meta" [tool.black] -target-version = ['py39', 'py310', 'py311', 'py312', 'py313'] +# [[[cog +# cog.outl(f"target-version = ['py3{min_python_minor}']") +# ]]] +target-version = ['py310'] +#[[[end]]] [tool.cibuildwheel] -build = "cp39* cp310* cp311* cp312* cp313* cp314* cp314t*" +# [[[cog +# versions = [f"cp3{m}*" for m in range(int(min_python_minor), int(max_python_minor) + 1)] +# versions += ["cp314t*"] +# cog.outl(f"build = \"{" ".join(versions)}\"") +# ]]] +build = "cp310* cp311* cp312* cp313* cp314* cp314t*" +#[[[end]]] test-command = "python -m tornado.test" [tool.cibuildwheel.macos] diff --git a/setup.cfg b/setup.cfg index f1d2b312..957b526b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,9 @@ license_file = LICENSE [mypy] -python_version = 3.9 +# [[[cog cog.outl(f"python_version = 3.{min_python_minor}")]]] +python_version = 3.10 +# [[[end]]] no_implicit_optional = True [mypy-tornado.*,tornado.platform.*] diff --git a/setup.py b/setup.py index e2a69912..62eca36c 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,20 @@ if ( can_use_limited_api = not sysconfig.get_config_var("Py_GIL_DISABLED") + if can_use_limited_api: + # [[[cog + # cog.out(f"define_macros = [(\"Py_LIMITED_API\", ") + # cog.out(f"\"0x03{int(min_python_minor):02x}0000\"") + # cog.outl(")]") + # cog.outl(f"bdist_wheel_options = {{\"py_limited_api\": \"cp3{min_python_minor}\"}}") + # ]]] + define_macros = [("Py_LIMITED_API", "0x030a0000")] + bdist_wheel_options = {"py_limited_api": "cp310"} + # [[[end]]] + else: + define_macros = [] + bdist_wheel_options = {} + # This extension builds and works on pypy as well, although pypy's jit # produces equivalent performance. kwargs["ext_modules"] = [ @@ -51,18 +65,20 @@ if ( # Use the stable ABI so our wheels are compatible across python # versions. py_limited_api=can_use_limited_api, - define_macros=[("Py_LIMITED_API", "0x03090000")] if can_use_limited_api else [], + define_macros=define_macros, ) ] - if can_use_limited_api: - kwargs["options"] = {"bdist_wheel": {"py_limited_api": "cp39"}} + if bdist_wheel_options: + kwargs["options"] = {"bdist_wheel": bdist_wheel_options} setuptools.setup( name="tornado", version=version, - python_requires=">= 3.9", + # [[[cog cog.outl(f"python_requires=\">= 3.{min_python_minor}\",")]]] + python_requires=">= 3.10", + # [[[end]]] packages=["tornado", "tornado.test", "tornado.platform"], package_data={ # data files need to be listed both here (which determines what gets @@ -102,11 +118,16 @@ setuptools.setup( classifiers=[ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", + # [[[cog + # for minor in range(int(min_python_minor), int(max_python_minor) + 1): + # cog.outl(f"\"Programming Language :: Python :: 3.{minor}\"") + # ]]] + "Programming Language :: Python :: 3.10" + "Programming Language :: Python :: 3.11" + "Programming Language :: Python :: 3.12" + "Programming Language :: Python :: 3.13" + "Programming Language :: Python :: 3.14" + # [[[end]]] "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ], diff --git a/tox.ini b/tox.ini index be3abce9..88e8eb9d 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,13 @@ [tox] envlist = # Basic configurations: Run the tests for each python version. - py39-full,py310-full,py311-full,py312-full,py313-full,py314-full,py314t,pypy3-full + # [[[cog + # versions = [f"py3{m}" for m in range(int(min_python_minor), int(max_python_minor) + 1)] + # versions += ["pypy3"] + # cog.outl(','.join(versions)) + # ]]] + py310,py311,py312,py313,py314,pypy3 + # [[[end]]] # Build and test the docs with sphinx. docs @@ -29,8 +35,13 @@ basepython = # linter warning-suppression comments go), so we specify a # python version for these builds. # These versions must be synced with the versions in .github/workflows/test.yml + # [[[cog + # cog.outl(f"docs: python3.{default_python_minor}") + # cog.outl(f"lint: python3.{default_python_minor}") + # ]]] docs: python3.13 lint: python3.13 + # [[[end]]] deps = full: pycurl @@ -41,7 +52,13 @@ deps = setenv = # Treat the extension as mandatory in testing (but not on pypy) - {py3,py39,py310,py311,py312,py313,py314,py314t}: TORNADO_EXTENSION=1 + # [[[cog + # versions = [f"py3{m}" for m in range(int(min_python_minor), int(max_python_minor) + 1)] + # versions.insert(0, "py3") + # cog.outl(f"{{{",".join(versions)}}}: TORNADO_EXTENSION=1") + # ]]] + {py3,py310,py311,py312,py313,py314}: TORNADO_EXTENSION=1 + # [[[end]]] # CI workers are often overloaded and can cause our tests to exceed # the default timeout of 5s. ASYNC_TEST_TIMEOUT=25 @@ -113,5 +130,7 @@ commands = # something new than of depending on something old and deprecated. # But sometimes something we depend on gets removed so we should also # test the newest version. + # [[[cog cog.outl(f"env -u PYTHONWARNDEFAULTENCODING mypy --platform linux --python-version 3.{default_python_minor} {{posargs:tornado}}")]]] env -u PYTHONWARNDEFAULTENCODING mypy --platform linux --python-version 3.13 {posargs:tornado} + # [[[end]]] changedir = {toxinidir}