Skip to content

Add Python 3.15 support - #843

Merged
igerber merged 2 commits into
igerber:mainfrom
ilgrad:feat/python-3.15
Oct 18, 2026
Merged

igerber merged 2 commits into
igerber:mainfrom
ilgrad:feat/python-3.15

Conversation

@ilgrad

@ilgrad ilgrad commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Adds Python 3.15 to the supported range, following the pattern of #284 (Python 3.14).

CPython 3.15.0 is final, but diff-diff 3.12.0 declares requires-python = ">=3.9,<3.15". On 3.15 (checked with pip 26.2.1 and uv 0.13.0):

  • pip install diff-diff skips every release from 2.3.2 on, since each one carries an upper cap, and silently installs 2.3.1, the last release without one. pip install diff-diff==3.12.0 fails: "Ignored the following versions that require a different python version: ... 3.12.0 Requires-Python >=3.9,<3.15".
  • uv pip install diff-diff ignores the upper bound and selects 3.12.0, but there is no cp315 wheel, so it builds the sdist, which needs a Rust toolchain.

Changes

  • pyproject.toml: requires-python <3.15 -> <3.16, add the Programming Language :: Python :: 3.15 classifier.
  • build-wheels.yml (used by publish.yml and release-build-check.yml): build cp315 wheels on Linux x86_64 / aarch64 (/opt/python/cp315-cp315 ships in the current manylinux_2_28 images), macOS arm64 and Windows.
  • rust-test.yml: add 3.15 to the python-tests matrix (all four OSes); move the Pure Python Fallback job from 3.14 to 3.15, as Add Python 3.14 support #284 moved it from 3.13 to 3.14.
  • docs-tests.yml: the doc-snippets job follows the fallback job to 3.15 (its comment says it mirrors that job); the two comments naming 3.14 are updated.
  • release-build-check.yml, README.md, the rust/Cargo.toml comment: the supported range now reads 3.9-3.15.
  • changelog.d/20261011-python-3-15.md (### Added).

No Rust dependency change: PyO3 0.29 supports 3.15 (0.29.0: "Support Python 3.15.0b1", PyO3/pyo3#6014), and with no committed Cargo.lock, pyo3 = "0.29" resolves to 0.29.3. The extension is not built for abi3, so per-version wheels stay the model and PYO3_USE_ABI3_FORWARD_COMPATIBILITY is not needed for 3.15. numpy 2.5.4, scipy 1.18.1, pandas 3.0.6 and scikit-learn 1.9.1 publish cp315 wheels, so the CI install steps need no source builds.

Not changed: the Lint workflow stays on 3.14 (tool pins, not the support surface); no free-threaded (3.15t) wheels or CI legs, since the project builds none for 3.14t either.

Methodology references (required if estimator / math changes)

  • Method name(s): N/A, no estimator or math changes.
  • Paper / source link(s): N/A
  • Any intentional deviations from the source (and why): N/A

Validation

  • Tests added/updated: none; the existing suite run on 3.15 and on 3.14 for comparison.
  • Local runs, Linux x86_64 (Fedora 44), the rust-test.yml Linux steps reproduced in a fresh venv per interpreter: maturin build --release --features extension-module,openblas, install the wheel, run from a copy of tests/ outside the source tree. Dependencies resolved to numpy 2.5.4, pandas 3.0.6, scipy 1.18.1, scikit-learn 1.9.1, pytest 9.1.1, pytest-xdist 3.8.0, maturin 1.15.0, Rust 1.99.0, PyO3 0.29.3.
Run CPython 3.15.0 CPython 3.14.7
pytest tests/test_rust_backend.py -m '' 200 passed 200 passed
DIFF_DIFF_BACKEND=rust pytest tests/ --ignore=tests/test_doc_snippets.py -n 4 --dist worksteal -m '' 12398 passed, 2141 skipped 12398 passed, 2141 skipped
Pure Python fallback: PYTHONPATH=. DIFF_DIFF_BACKEND=python pytest tests/ --ignore=tests/test_rust_backend.py --ignore=tests/test_doc_snippets.py -n 4 --dist worksteal 14336 passed, 358 skipped 14336 passed, 358 skipped
Doc snippets: PYTHONPATH=. DIFF_DIFF_BACKEND=python pytest tests/test_doc_snippets.py 161 passed, 7 skipped 161 passed, 7 skipped

No failures. Per-test outcomes are identical on 3.15 and 3.14 (compared test by test from the JUnit XML), and so are the warning categories. The skips are the isolated-install and missing-fixture skips (openai_review.py not in the checkout, R / Stata golden files, matplotlib not installed), the same on both. The 3.14 runs use this branch, whose Python and Rust sources are identical to main.

  • Release path: the build-linux loop of build-wheels.yml, run in quay.io/pypa/manylinux_2_28_x86_64 for cp314 and cp315, builds both manylinux_2_28_x86_64 wheels; the cp315 wheel installs into a 3.15.0 venv with HAS_RUST_BACKEND == True, and tests/test_rust_backend.py gives 200 passed.

  • Backtest / simulation / notebook evidence (if applicable): N/A

  • Not run: macOS, Windows and aarch64 (CI covers them); the Rust unit tests (cargo test, a job with no Python matrix, unchanged here); the Lint workflow (no Python source changed); the notebooks and mmm-interop workflows.

CI has not run yet: the fork's workflow runs are waiting for a maintainer's approval, and the test jobs also need the ready-for-ci label.

Security / privacy

  • Confirm no secrets/PII in this PR: Yes

Changelog

  • changelog.d/ fragment added (or N/A - no user-visible change): changelog.d/20261011-python-3-15.md

@ilgrad
ilgrad requested a review from igerber as a code owner October 11, 2026 20:05
ilgrad and others added 2 commits October 18, 2026 13:57
CPython 3.15.0 is final, but requires-python capped the package at <3.15:
pip on 3.15 falls back to diff-diff 2.3.1, and uv builds the sdist. Raise
the cap, add the classifier, build cp315 wheels on every platform and add
3.15 to the Rust-backend CI matrix; the pure-Python fallback and the doc
snippets move to 3.15 as they moved to 3.14 in igerber#284. PyO3 0.29 already
supports 3.15.
main moved to pyo3/rust-numpy 0.30 (igerber#852), which lists Python 3.15.0
final as supported; the fragment's PyO3 0.29 sentence predates that.
@igerber igerber added the ready-for-ci Triggers CI test workflows label Oct 18, 2026
@igerber
igerber merged commit 420d5ed into igerber:main Oct 18, 2026
68 of 70 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-ci Triggers CI test workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants