diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 603609a..6d57c00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.11", "3.12"] + python-version: ["3.11", "3.12", "3.13", "3.14"] # SPEC-v0.6 §4. The Postgres tests skip when CTRLRUN_TEST_POSTGRES is unset, and a # skipping test proves nothing -- so CI supplies a real server rather than letting the diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5d0d049..9dbabc4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -6,7 +6,7 @@ name: CodeQL # the extra queries cost a few minutes that a project this size can afford. # # Findings land in the repository's code-scanning tab. Nothing here gates a merge -- the -# required checks stay `check (3.11)`, `check (3.12)` and `package` -- because a static +# required checks stay `check (3.11)` through `check (3.14)` and `package` -- because a static # analyser's first run on an unfamiliar codebase is a reading list, not a verdict. on: diff --git a/CHANGELOG.md b/CHANGELOG.md index dcd7a5c..0a8ce94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,23 @@ All notable changes to this project are documented here. The format follows Public API names are frozen in `docs/SPEC-v0.1.md` §8. Before 1.0 they may still change, and any change to one appears here. +## [Unreleased] + +### Added + +- **Python 3.13 and 3.14 are tested and declared.** CI's `check` job runs the full suite on + 3.11, 3.12, 3.13 and 3.14, and the package classifiers name all four. The floor is unchanged: + `requires-python` stays `>=3.11`, and mypy and ruff still check against 3.11. No library code + changed; the one test fix is below. + +### Fixed + +- **The migration tests' release fixtures could not build a venv on some interpreters.** + `venv.create` copies the interpreter by default, and a copied binary from a shared-libpython + build (uv's CPython 3.14 on macOS) aborted inside `ensurepip`, so all five release fixtures + errored before a release was installed. The fixture now symlinks, as `python -m venv` does on + POSIX. + ## [0.6.1] - 2026-09-07 — The audit's fixes, and the gateway's transport Everything found after `v0.6.0` was tagged: twenty-nine defects from an audit of the shipped diff --git a/pyproject.toml b/pyproject.toml index e8f20ca..2805cb2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,8 @@ classifiers = [ "Intended Audience :: Developers", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Typing :: Typed", ] dependencies = [ diff --git a/tests/test_migrations.py b/tests/test_migrations.py index c3d1739..8ca46ad 100644 --- a/tests/test_migrations.py +++ b/tests/test_migrations.py @@ -68,7 +68,11 @@ def _release_venv(tmp_path_factory, version: str) -> Path | None: """ root = tmp_path_factory.mktemp(f"rel-{version}") env = root / "venv" - venv.create(env, with_pip=True) + # Symlinks, as `python -m venv` uses on POSIX. `venv.create` copies the interpreter by + # default, and a copied binary from a shared-libpython build looks for `libpython` beside + # itself: on uv's CPython 3.14 for macOS it aborted inside `ensurepip`, and every release + # fixture errored before a release was installed. + venv.create(env, with_pip=True, symlinks=os.name != "nt") python = env / "bin" / "python" done = subprocess.run( [str(python), "-m", "pip", "install", "-q", f"ctrlrun=={version}"],