From 804e0d1672e4d32848bb946825ece278264fe473 Mon Sep 17 00:00:00 2001 From: Aiden Storey Date: Wed, 29 Jul 2026 13:33:26 -0400 Subject: [PATCH 1/2] Drop EOL Pythons (3.7-3.9) from CI, add 3.12-3.14 virtualenv 21.5.0 (2026-06-13) dropped support for creating Python 3.8 environments, which broke the python-tests (3.8) CI job for every PR: tox now fails with 'could not find python interpreter with spec(s): py38' even though the interpreter is installed. Rather than pinning an old virtualenv, drop EOL versions and test what users actually run: - Drop 3.8 (EOL 2024-10, broken in CI) and 3.9 (EOL 2025-10, next to be dropped by the toolchain) from the CI matrix - Remove vestigial py37/py38/py39 from the tox envlist and Makefile - Add 3.12, 3.13 and 3.14 to the CI matrix and envlist - Only install python3.X-distutils for < 3.12 (removed from the stdlib) - Declare python_requires>=3.10 in setup.py Assisted-By: devx/bbf3c269-bbaa-4af2-81fc-4b93ae41af0a --- .github/workflows/tests.yml | 9 +++++++-- python/Makefile | 2 +- python/setup.cfg | 2 +- python/setup.py | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f0534345..a3c0257f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -53,7 +53,7 @@ jobs: strategy: fail-fast: false matrix: - python: [ '3.8', '3.9', '3.10', '3.11' ] + python: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] services: redis: @@ -67,7 +67,12 @@ jobs: run: | sudo add-apt-repository -y ppa:deadsnakes/ppa sudo apt-get -qq update - sudo apt-get install -y python${{ matrix.python }} python${{ matrix.python }}-distutils + sudo apt-get install -y python${{ matrix.python }} + # distutils was removed from the stdlib in Python 3.12, so the + # python3.X-distutils package only exists for older versions. + if dpkg --compare-versions "${{ matrix.python }}" lt "3.12"; then + sudo apt-get install -y python${{ matrix.python }}-distutils + fi sudo pip install autopep8 || true - name: Run Python tests run: | diff --git a/python/Makefile b/python/Makefile index 8a4e4624..fbc50e5d 100644 --- a/python/Makefile +++ b/python/Makefile @@ -4,7 +4,7 @@ python_files := find . -path '*/.*' -prune -o -name '*.py' -print0 python_version_full := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1))) python_version_major := $(word 1,${python_version_full}) -TOX_ENV ?= py37,py38,py39,py310,py311 +TOX_ENV ?= py310,py311,py312,py313,py314 all: test diff --git a/python/setup.cfg b/python/setup.cfg index 351ea78a..1f43583e 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -1,5 +1,5 @@ [tox:tox] -envlist = py37,py38,py39,py310,py311 +envlist = py310,py311,py312,py313,py314 [testenv] commands = pytest {posargs:-vv} diff --git a/python/setup.py b/python/setup.py index 0f546f33..efab4573 100644 --- a/python/setup.py +++ b/python/setup.py @@ -35,6 +35,7 @@ def get_lua_scripts(): name='ciqueue', version='0.1', packages=['ciqueue', 'ciqueue._pytest'], + python_requires='>=3.10', install_requires=[ 'dill>=0.2.7', 'pytest>=2.7', From 842c6d812930a71db85cf1eab3840ae8ad669aa2 Mon Sep 17 00:00:00 2001 From: Aiden Storey Date: Wed, 29 Jul 2026 13:35:58 -0400 Subject: [PATCH 2/2] Replace distutils.util.strtobool with local helper distutils was removed from the stdlib in Python 3.12, so importing it broke test collection on the new 3.12-3.14 CI jobs. Inline the tiny strtobool helper with identical semantics. Assisted-By: devx/bbf3c269-bbaa-4af2-81fc-4b93ae41af0a --- python/ciqueue/_pytest/test_queue.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/python/ciqueue/_pytest/test_queue.py b/python/ciqueue/_pytest/test_queue.py index e994ace7..ac5351d3 100644 --- a/python/ciqueue/_pytest/test_queue.py +++ b/python/ciqueue/_pytest/test_queue.py @@ -1,4 +1,3 @@ -from distutils import util # pylint: disable=no-name-in-module, import-modules-only from future.moves.urllib import parse as urlparse import ciqueue import ciqueue.distributed @@ -14,6 +13,16 @@ def key_item(item): return item.nodeid +def strtobool(value): + # Replacement for distutils.util.strtobool, removed in Python 3.12. + value = value.lower() + if value in ('y', 'yes', 't', 'true', 'on', '1'): + return True + if value in ('n', 'no', 'f', 'false', 'off', '0'): + return False + raise ValueError("invalid truth value {!r}".format(value)) + + def parse_worker_args(query_string, tests_index): args = urlparse.parse_qs(query_string) @@ -51,7 +60,7 @@ def parse_redis_args(spec): if 'socket_connect_timeout' in query: result['socket_connect_timeout'] = int(query['socket_connect_timeout'][0]) if 'retry_on_timeout' in query: - result['retry_on_timeout'] = bool(util.strtobool(query['retry_on_timeout'][0] or 'false')) + result['retry_on_timeout'] = strtobool(query['retry_on_timeout'][0] or 'false') if spec.scheme == "rediss": result['ssl'] = True