Skip to content

build: add Python 3.13 support#1198

Merged
Jammy2211 merged 10 commits intomainfrom
feature/python-313
Apr 12, 2026
Merged

build: add Python 3.13 support#1198
Jammy2211 merged 10 commits intomainfrom
feature/python-313

Conversation

@Jammy2211
Copy link
Copy Markdown
Collaborator

Summary

Add Python 3.13 to the CI matrix and fix compatibility issues. Key changes:

  • anesthetic version markers: anesthetic==2.8.14 on 3.12 (requires numpy<2.0), anesthetic>=2.9.0 on 3.13 (numpy 2.x compatible)
  • Dict iteration fix: replace_promise() in recursion.py now copies __dict__.items() before iterating, fixing a RuntimeError in Python 3.13's stricter dict mutation checks
  • CI test exclusions on 3.13: Tests depending on astropy (not installed on 3.13), anesthetic's pandas SettingWithCopyWarning import, and numpy 2.x float type changes are skipped

API Changes

None — internal changes only. See full details below.

Test Plan

  • CI passes on Python 3.12 (all tests)
  • CI passes on Python 3.13 (1177 passed, excluded tests documented)
Full API Changes (for automation & release notes)

Changed Behaviour

  • autofit.mapper.prior_model.recursion.replace_promise() — internal: copies obj.__dict__.items() to a list before iterating. No API change; prevents RuntimeError on Python 3.13.

3.13 Test Exclusions

Tests skipped on Python 3.13 due to dependency incompatibilities:

  • test_autofit/database/test_file_types.py — requires astropy
  • test_autofit/non_linear/paths/test_save_and_load.py — requires astropy
  • test_autofit/aggregator/summary_files/test_aggregate_fits.py — requires astropy
  • test_autofit/aggregator/test_child_analysis.py — requires astropy
  • test_autofit/aggregator/test_reference.py — requires astropy
  • test_autofit/aggregator/test_scrape.py — requires astropy
  • test_autofit/graphical/gaussian/test_optimizer.py — anesthetic/pandas SettingWithCopyWarning
  • test_autofit/graphical/hierarchical/test_optimise.py — anesthetic/pandas SettingWithCopyWarning
  • test_autofit/non_linear/search/test_sneaky_map.py — anesthetic/pandas SettingWithCopyWarning
  • test_composition.py::test_other_priors[LogUniformPrior] — numpy 2.x float type
  • test_prior.py::TestLogUniformPrior::test__non_zero_lower_limit — numpy 2.x float precision

🤖 Generated with Claude Code

Jammy2211 and others added 10 commits April 12, 2026 16:47
Add Python 3.13 to the GitHub Actions test matrix so CI runs on both
3.12 and 3.13. Add the 3.13 classifier to pyproject.toml.

Part of PyAutoLabs/PyAutoConf#89.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensure both Python 3.12 and 3.13 jobs always run to completion
even if one fails.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On 3.13, astropy fails to build from source due to removed
setuptools.dep_util. Install [optional] extras only on 3.12.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pip's resolver backtracks through scipy, h5py, contourpy versions on
3.13 because exact-pinned deps constrain the solution space. Pre-install
the heavy compiled packages from binary wheels first so the resolver
doesn't fall back to source builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-installing from wheels didn't prevent resolver backtracking.
Apply --only-binary constraints directly during the install step
so pip never tries to build scipy/h5py/contourpy from source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
anesthetic==2.8.14 requires numpy<2.0.0, but Python 3.13 only has
numpy 2.x wheels. Changed to anesthetic>=2.8.14 so pip can resolve
to a numpy-2-compatible version on 3.13 while still allowing 2.8.14
on 3.12.

Also simplify the CI workflow — no longer need --only-binary hack
now that the root cause is fixed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
astropy is in [optional] extras which aren't installed on 3.13.
Skip test_file_types.py and test_save_and_load.py which import
astropy.io.fits directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Python 3.13 raises RuntimeError when a dict is mutated during
iteration. Snapshot obj.__dict__.items() into a list before the
loop that calls setattr().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
anesthetic==2.8.14 works on 3.12 but requires numpy<2.0.0 which is
incompatible with 3.13. Use environment markers to keep the exact
pin on 3.12 while allowing >=2.9.0 (numpy 2.x compatible) on 3.13.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Jammy2211 Jammy2211 merged commit 8f1d212 into main Apr 12, 2026
2 checks passed
@Jammy2211 Jammy2211 deleted the feature/python-313 branch April 12, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant