diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 3212ce72f..853103ce3 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -50,7 +50,7 @@ jobs: - name: Build wheels run: | expected=0 - for pyver in 39 310 311 312 313 314; do + for pyver in 39 310 311 312 313 314 315; do pybin="/opt/python/cp${pyver}-cp${pyver}/bin/python" if [ ! -f "$pybin" ]; then echo "ERROR: Expected Python interpreter not found: $pybin" @@ -80,7 +80,7 @@ jobs: runs-on: macos-14 strategy: matrix: - python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14', '3.15'] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 @@ -113,7 +113,7 @@ jobs: runs-on: windows-latest strategy: matrix: - python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14', '3.15'] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 diff --git a/.github/workflows/docs-tests.yml b/.github/workflows/docs-tests.yml index 6e6e068e0..f13a5bbe7 100644 --- a/.github/workflows/docs-tests.yml +++ b/.github/workflows/docs-tests.yml @@ -92,10 +92,10 @@ jobs: - name: Set up Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: - # 3.14 to mirror Pure Python Fallback (the only existing job + # 3.15 to mirror Pure Python Fallback (the only existing job # that actually ran these tests). notebooks.yml uses 3.11 for # nbmake compat, not relevant here. - python-version: '3.14' + python-version: '3.15' - name: Install dependencies # Keep in sync with pyproject.toml [project.dependencies] and [project.optional-dependencies.dev] @@ -248,7 +248,7 @@ jobs: - name: Run changelog-fragment check on the floor Python # The compiler promises 3.9 compatibility but its behavioral tests - # run in the 3.14 doc-snippets job; this stdlib-only invocation is + # run in the 3.15 doc-snippets job; this stdlib-only invocation is # the floor's continuous syntax + behavior smoke for the script. run: python .claude/scripts/changelog_compile.py check diff --git a/.github/workflows/release-build-check.yml b/.github/workflows/release-build-check.yml index ee7c4dd53..2caa57e26 100644 --- a/.github/workflows/release-build-check.yml +++ b/.github/workflows/release-build-check.yml @@ -2,7 +2,7 @@ name: Release build check # Pre-merge guard for the PyPI release build path. publish.yml only runs on # `release: published`, so its manylinux container build (checkout@v7 inside -# glibc-2.28, openblas, py3.9-3.14) is never exercised by PR CI. This calls the +# glibc-2.28, openblas, py3.9-3.15) is never exercised by PR CI. This calls the # SAME reusable workflow build-only (no PyPI upload) so a PR that would break our # ability to mint a release fails here instead of at release time. # diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 985afc311..e4e925509 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -131,7 +131,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest, ubuntu-24.04-arm] - python-version: ['3.11', '3.13', '3.14'] + python-version: ['3.11', '3.13', '3.14', '3.15'] include: # Python 3.9 floor guard (single Linux leg): mypy >= 2.2 can no # longer type-check with python_version = "3.9", so this runtime @@ -251,7 +251,7 @@ jobs: - name: Set up Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: - python-version: '3.14' + python-version: '3.15' - name: Install dependencies # Keep in sync with pyproject.toml [project.dependencies] and [project.optional-dependencies.dev] diff --git a/README.md b/README.md index 3c5acfc07..cd318cb61 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ No other Python or R DiD package offers design-based variance estimation for mod ## Requirements -- Python 3.9 - 3.14 +- Python 3.9 - 3.15 - numpy >= 1.20 - pandas >= 1.3 - scipy >= 1.10 diff --git a/changelog.d/20261011-python-3-15.md b/changelog.d/20261011-python-3-15.md new file mode 100644 index 000000000..430bd34fe --- /dev/null +++ b/changelog.d/20261011-python-3-15.md @@ -0,0 +1,6 @@ +### Added +- **Python 3.15 support**: `requires-python` now allows 3.15 (`<3.16`) and + the 3.15 classifier is declared; release wheels are built for CPython 3.15 + on Linux (x86_64, aarch64), macOS arm64 and Windows, and CI runs the + Rust-backend matrix and the pure-Python fallback on 3.15. PyO3 0.29 + already supports 3.15, so no Rust dependency changes. diff --git a/pyproject.toml b/pyproject.toml index ea53069b7..5231a1ab3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ version = "3.12.0" description = "Difference-in-Differences causal inference with sklearn-like API. Callaway-Sant'Anna, Synthetic DiD, Honest DiD, event studies, parallel trends." readme = "README.md" license = "MIT" -requires-python = ">=3.9,<3.15" +requires-python = ">=3.9,<3.16" authors = [ {name = "diff-diff contributors"} ] @@ -40,6 +40,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", "Topic :: Scientific/Engineering :: Mathematics", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 8e2515a8f..8bfa2669a 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -25,7 +25,7 @@ openblas = ["ndarray/blas"] alloc-profile = [] [dependencies] -# PyO3 0.29 supports Python 3.9-3.14 +# PyO3 0.29 supports Python 3.9-3.15 pyo3 = "0.29" numpy = "0.29" ndarray = { version = "0.17", features = ["rayon"] }