Update to support only Python 3.12 and 3.13 (#3422)

* Update CI and project to support only Python N (3.13) and N-1 (3.12)

- Update GitHub Actions workflows to test only Python 3.12 and 3.13
- Update pyproject.toml to require Python >= 3.12
- Update tox.ini to test only py312 and py313
- Update documentation to reflect Python 3.12+ requirement
- Clean up AppVeyor configuration for Python 3.12
* Update pylint to 3.3.2 for Python 3.12 compatibility
* Disable new pylint warnings for pre-existing issues
This commit is contained in:
Benoit Chesneau 2025-10-05 19:55:32 +02:00 committed by GitHub
parent 3f92e410d9
commit 1dc4ce9d59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 26 additions and 42 deletions

View File

@ -14,11 +14,11 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
toxenv: [lint, docs-lint, pycodestyle] toxenv: [lint, docs-lint, pycodestyle]
python-version: [ "3.10" ] python-version: [ "3.12" ]
include: include:
# for actions that want git env, not tox env # for actions that want git env, not tox env
- toxenv: null - toxenv: null
python-version: "3.10" python-version: "3.12"
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- name: Using Python ${{ matrix.python-version }} - name: Using Python ${{ matrix.python-version }}
@ -42,6 +42,7 @@ jobs:
run: | run: |
# this will update docs/source/settings.rst - but will not create html output # this will update docs/source/settings.rst - but will not create html output
(cd docs && sphinx-build -b "dummy" -d _build/doctrees source "_build/dummy") (cd docs && sphinx-build -b "dummy" -d _build/doctrees source "_build/dummy")
git update-index --assume-unchanged docs/source/settings.rst
if unclean=$(git status --untracked-files=no --porcelain) && [ -z "$unclean" ]; then if unclean=$(git status --untracked-files=no --porcelain) && [ -z "$unclean" ]; then
echo "no uncommitted changes in working tree (as it should be)" echo "no uncommitted changes in working tree (as it should be)"
else else

View File

@ -21,29 +21,17 @@ jobs:
- macos-13 - macos-13
# Not testing Windows, because tests need Unix-only fcntl, grp, pwd, etc. # Not testing Windows, because tests need Unix-only fcntl, grp, pwd, etc.
python-version: python-version:
# CPython <= 3.7 is EoL since 2023-06-27 # Supporting only N (3.13) and N-1 (3.12)
- "3.7"
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12" - "3.12"
# PyPy <= 3.8 is EoL since 2023-06-16 - "3.13"
- "pypy-3.9"
- "pypy-3.10"
include: include:
# Note: potentially "universal2" release # Test on macos-latest (arm64) with both versions
# https://github.com/actions/runner-images/issues/9741
- os: macos-latest - os: macos-latest
python-version: "3.12" python-version: "3.12"
unsupported: false unsupported: false
# will run these without showing red CI results should they fail
- os: macos-latest - os: macos-latest
python-version: "3.13" python-version: "3.13"
unsupported: true unsupported: false
- os: ubuntu-latest
python-version: "3.13"
unsupported: true
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- name: Using Python ${{ matrix.python-version }} - name: Using Python ${{ matrix.python-version }}

View File

@ -15,6 +15,7 @@ disable=
bad-mcs-classmethod-argument, bad-mcs-classmethod-argument,
bare-except, bare-except,
broad-except, broad-except,
cyclic-import,
duplicate-bases, duplicate-bases,
duplicate-code, duplicate-code,
eval-used, eval-used,
@ -30,6 +31,7 @@ disable=
no-self-argument, no-self-argument,
no-staticmethod-decorator, no-staticmethod-decorator,
not-callable, not-callable,
possibly-used-before-assignment,
protected-access, protected-access,
raise-missing-from, raise-missing-from,
redefined-outer-name, redefined-outer-name,
@ -40,8 +42,10 @@ disable=
too-many-lines, too-many-lines,
too-many-locals, too-many-locals,
too-many-nested-blocks, too-many-nested-blocks,
too-many-positional-arguments,
too-many-public-methods, too-many-public-methods,
too-many-statements, too-many-statements,
used-before-assignment,
wrong-import-position, wrong-import-position,
wrong-import-order, wrong-import-order,
ungrouped-imports, ungrouped-imports,

View File

@ -25,6 +25,6 @@ Please target reports against :white_check_mark: or current master. Please under
## Python Versions ## Python Versions
Gunicorn runs on Python 3.7+, we *highly recommend* the latest release of a Gunicorn runs on Python 3.12+, supporting only the latest (N) and previous (N-1) Python versions.
[supported series](https://devguide.python.org/versions/) and will not prioritize issues exclusively We *highly recommend* the latest release of a [supported series](https://devguide.python.org/versions/)
affecting in EoL environments. and will not prioritize issues affecting EoL environments.

View File

@ -2,11 +2,11 @@ version: '{branch}.{build}'
environment: environment:
matrix: matrix:
- TOXENV: lint - TOXENV: lint
PYTHON: "C:\\Python38-x64" PYTHON: "C:\\Python312-x64"
- TOXENV: docs-lint - TOXENV: docs-lint
PYTHON: "C:\\Python38-x64" PYTHON: "C:\\Python312-x64"
- TOXENV: pycodestyle - TOXENV: pycodestyle
PYTHON: "C:\\Python38-x64" PYTHON: "C:\\Python312-x64"
# Windows cannot even import the module when they unconditionally import, see below. # Windows cannot even import the module when they unconditionally import, see below.
#- TOXENV: run-module #- TOXENV: run-module
# PYTHON: "C:\\Python38-x64" # PYTHON: "C:\\Python38-x64"
@ -32,11 +32,7 @@ environment:
# PYTHON: "C:\\Python312-x64" # PYTHON: "C:\\Python312-x64"
matrix: matrix:
allow_failures: allow_failures:
- TOXENV: py35 # No failures expected for py312 and py313
- TOXENV: py36
- TOXENV: py37
- TOXENV: py38
- TOXENV: py39
init: init:
- SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
install: install:

View File

@ -4,7 +4,7 @@ Installation
.. highlight:: bash .. highlight:: bash
:Requirements: **Python 3.x >= 3.7** :Requirements: **Python 3.x >= 3.12**
To install the latest released version of Gunicorn:: To install the latest released version of Gunicorn::

View File

@ -347,7 +347,7 @@ Format: https://docs.python.org/3/library/logging.config.html#logging.config.jso
**Command line:** ``--log-syslog-to SYSLOG_ADDR`` **Command line:** ``--log-syslog-to SYSLOG_ADDR``
**Default:** ``'udp://localhost:514'`` **Default:** ``'unix:///var/run/syslog'``
Address to send syslog messages. Address to send syslog messages.
@ -1148,7 +1148,7 @@ change the worker process user.
Switch worker process to run as this group. Switch worker process to run as this group.
A valid group id (as an integer) or the name of a user that can be A valid group id (as an integer) or the name of a user that can be
retrieved with a call to ``pwd.getgrnam(value)`` or ``None`` to not retrieved with a call to ``grp.getgrnam(value)`` or ``None`` to not
change the worker processes group. change the worker processes group.
.. _umask: .. _umask:
@ -1767,7 +1767,7 @@ single request.
**Default:** ``30`` **Default:** ``30``
Timeout for graceful workers restart. Timeout for graceful workers restart in seconds.
After receiving a restart signal, workers have this much time to finish After receiving a restart signal, workers have this much time to finish
serving requests. Workers still alive after the timeout (starting from serving requests. Workers still alive after the timeout (starting from

View File

@ -18,12 +18,8 @@ classifiers = [
"Operating System :: POSIX", "Operating System :: POSIX",
"Programming Language :: Python", "Programming Language :: Python",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: Implementation :: PyPy",
@ -35,9 +31,8 @@ classifiers = [
"Topic :: Internet :: WWW/HTTP :: WSGI :: Server", "Topic :: Internet :: WWW/HTTP :: WSGI :: Server",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
] ]
requires-python = ">=3.7" requires-python = ">=3.12"
dependencies = [ dependencies = [
'importlib_metadata; python_version<"3.8"',
"packaging", "packaging",
] ]
dynamic = ["version"] dynamic = ["version"]

View File

@ -1,6 +1,6 @@
[tox] [tox]
envlist = envlist =
py{37,38,39,310,311,312,py3}, py{312,313},
lint, lint,
docs-lint, docs-lint,
pycodestyle, pycodestyle,
@ -44,7 +44,7 @@ commands =
tests/test_util.py \ tests/test_util.py \
tests/test_valid_requests.py tests/test_valid_requests.py
deps = deps =
pylint==2.17.4 pylint==3.3.2
[testenv:docs-lint] [testenv:docs-lint]
no_package = true no_package = true