From 4a22f9c987220f565a27f1d5af94ccac14f22f73 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 17:22:31 -0500 Subject: [PATCH 1/8] Add Python 3.14 support - Add Python 3.14 to classifiers in setup.py - Add Python 3.14 to Test matrix in pr.yaml - Add Python 3.14 to SmokeTestForMultipleVersions matrix - Handle Python 3.14 like 3.13 for tables package workaround The numpy compatibility fix for Python 3.14 was already merged in PR #409. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr.yaml | 6 +++--- setup.py | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 92f9fb73..36000e8c 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -34,7 +34,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest, windows-latest ] - python-version: [ "3.12", "3.13" ] + python-version: [ "3.12", "3.13", "3.14" ] fail-fast: false runs-on: ${{ matrix.os }} steps: @@ -67,7 +67,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - python-version: ['3.10', '3.11', '3.12', '3.13'] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] steps: - name: Checkout repo uses: actions/checkout@v4 @@ -83,7 +83,7 @@ jobs: run: python -m pytest --version - name: Install -us package from PyPI run: | - if [[ "${{ matrix.python-version }}" == "3.13" ]]; then + if [[ "${{ matrix.python-version }}" == "3.13" || "${{ matrix.python-version }}" == "3.14" ]]; then # For Python 3.13, install newer tables first and ignore conflicts pip install "tables>=3.10.1" pip install policyengine-us --no-deps diff --git a/setup.py b/setup.py index 31f4b569..f91fd82c 100644 --- a/setup.py +++ b/setup.py @@ -65,6 +65,7 @@ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Scientific/Engineering :: Information Analysis", ], description="Core microsimulation engine enabling country-specific policy models.", From cac377df23b536b482410f3247c3677bd3fdc7cc Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 17:24:25 -0500 Subject: [PATCH 2/8] Add changelog entry and bump version to 3.24.0 Co-Authored-By: Claude Opus 4.5 --- changelog_entry.yaml | 4 ++++ setup.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29b..06f19ed2 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Python 3.14 support. diff --git a/setup.py b/setup.py index f91fd82c..15042b38 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ setup( name="policyengine-core", - version="3.23.4", + version="3.24.0", author="PolicyEngine", author_email="hello@policyengine.org", classifiers=[ From 52573a37fb53ea470c817fe214b42a961c2b4010 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 17:27:09 -0500 Subject: [PATCH 3/8] Allow Python 3.14 smoke tests to fail tables doesn't have Python 3.14 wheels yet, so the smoke tests with policyengine-us will fail. The core tests pass on Python 3.14. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 36000e8c..883d9ce4 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -63,6 +63,8 @@ jobs: name: Test Core and country packages (${{ matrix.os }}, py${{ matrix.python-version }}) runs-on: ${{ matrix.os }} needs: Lint + # Python 3.14 smoke tests allowed to fail until tables has 3.14 wheels + continue-on-error: ${{ matrix.python-version == '3.14' }} strategy: fail-fast: false matrix: From 722cc845804df28ac37a81edd92f1ee23473c488 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 18:05:28 -0500 Subject: [PATCH 4/8] Remove continue-on-error workaround Will merge when tables has Python 3.14 wheels. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 883d9ce4..36000e8c 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -63,8 +63,6 @@ jobs: name: Test Core and country packages (${{ matrix.os }}, py${{ matrix.python-version }}) runs-on: ${{ matrix.os }} needs: Lint - # Python 3.14 smoke tests allowed to fail until tables has 3.14 wheels - continue-on-error: ${{ matrix.python-version == '3.14' }} strategy: fail-fast: false matrix: From dfa2fb39d79f2a2d72a2cdcdaa180e6a50e53cfd Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 18:08:01 -0500 Subject: [PATCH 5/8] Pin tables>=3.11 for Python 3.14 support tables 3.11+ will have Python 3.14 wheels (PyTables/PyTables#1262). Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 36000e8c..1f66df63 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -84,8 +84,9 @@ jobs: - name: Install -us package from PyPI run: | if [[ "${{ matrix.python-version }}" == "3.13" || "${{ matrix.python-version }}" == "3.14" ]]; then - # For Python 3.13, install newer tables first and ignore conflicts - pip install "tables>=3.10.1" + # For Python 3.13+, install newer tables first and ignore conflicts + # Python 3.14 requires tables>=3.11 (PyTables/PyTables#1262) + pip install "tables>=3.11" pip install policyengine-us --no-deps # Install remaining dependencies manually pip install click==8.1.3 pathlib pytest-dependency synthimpute tabulate From 01b858299af41400a94c3ce52557ce560c40b418 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 18:09:22 -0500 Subject: [PATCH 6/8] Exclude Python 3.14 from smoke tests until tables 3.11 Core tests still run on 3.14 (and pass). Smoke tests with policyengine-us excluded until tables has Python 3.14 support. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 1f66df63..d2fc01dd 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -67,7 +67,8 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + # Python 3.14 excluded until tables 3.11 releases (PyTables/PyTables#1262) + python-version: ['3.10', '3.11', '3.12', '3.13'] steps: - name: Checkout repo uses: actions/checkout@v4 @@ -83,10 +84,9 @@ jobs: run: python -m pytest --version - name: Install -us package from PyPI run: | - if [[ "${{ matrix.python-version }}" == "3.13" || "${{ matrix.python-version }}" == "3.14" ]]; then - # For Python 3.13+, install newer tables first and ignore conflicts - # Python 3.14 requires tables>=3.11 (PyTables/PyTables#1262) - pip install "tables>=3.11" + if [[ "${{ matrix.python-version }}" == "3.13" ]]; then + # For Python 3.13, install newer tables first and ignore conflicts + pip install "tables>=3.10.1" pip install policyengine-us --no-deps # Install remaining dependencies manually pip install click==8.1.3 pathlib pytest-dependency synthimpute tabulate From df16aa0e570e864351280b5eeef785d1a067e876 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 18:10:19 -0500 Subject: [PATCH 7/8] Keep Python 3.14 in smoke tests (will fail until tables 3.11) CI failure signals PR is blocked. When tables 3.11 releases, CI will auto-pass and PR is ready to merge. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index d2fc01dd..b4e83f87 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -67,8 +67,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - # Python 3.14 excluded until tables 3.11 releases (PyTables/PyTables#1262) - python-version: ['3.10', '3.11', '3.12', '3.13'] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] steps: - name: Checkout repo uses: actions/checkout@v4 @@ -84,9 +83,9 @@ jobs: run: python -m pytest --version - name: Install -us package from PyPI run: | - if [[ "${{ matrix.python-version }}" == "3.13" ]]; then - # For Python 3.13, install newer tables first and ignore conflicts - pip install "tables>=3.10.1" + if [[ "${{ matrix.python-version }}" == "3.13" || "${{ matrix.python-version }}" == "3.14" ]]; then + # Python 3.14 requires tables>=3.11 (PyTables/PyTables#1262) + pip install "tables>=3.11" pip install policyengine-us --no-deps # Install remaining dependencies manually pip install click==8.1.3 pathlib pytest-dependency synthimpute tabulate From e162b833621387007032e7653ceb92e5f998c226 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 24 Jan 2026 18:13:16 -0500 Subject: [PATCH 8/8] Remove stale smoke test workaround The old workaround installed unnecessary deps (synthimpute, etc.). Just let policyengine-us install normally - it will fail on Python 3.14 until tables 3.11 releases, then auto-work. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pr.yaml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index b4e83f87..35714d6b 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -82,18 +82,8 @@ jobs: - name: Verify pytest plugins run: python -m pytest --version - name: Install -us package from PyPI - run: | - if [[ "${{ matrix.python-version }}" == "3.13" || "${{ matrix.python-version }}" == "3.14" ]]; then - # Python 3.14 requires tables>=3.11 (PyTables/PyTables#1262) - pip install "tables>=3.11" - pip install policyengine-us --no-deps - # Install remaining dependencies manually - pip install click==8.1.3 pathlib pytest-dependency synthimpute tabulate - pip install policyengine-us-data --no-deps - else - python -m pip install policyengine-us - fi - shell: bash + # Python 3.14 blocked until tables 3.11 releases (PyTables/PyTables#1262) + run: python -m pip install policyengine-us - name: Run smoke tests only run: python -m pytest -m smoke --reruns 2 --reruns-delay 5 -v -s env: