Skip to content

Support Python 3.11–3.14 and NumPy 2#161

Open
pscicluna wants to merge 2 commits into
Starfish-develop:masterfrom
pscicluna:claude/python-3-14-compat-6282z0
Open

Support Python 3.11–3.14 and NumPy 2#161
pscicluna wants to merge 2 commits into
Starfish-develop:masterfrom
pscicluna:claude/python-3-14-compat-6282z0

Conversation

@pscicluna

Copy link
Copy Markdown

Support Python 3.11–3.14 and NumPy 2

I'm not entirely sure if Starfish is still alive or if it is now abandonware, but I find it useful and I'm not really aware of a good alternative, so I thought I would take a shot at updating some of the key infrastructure for it. This is primarily intended to fix issue #160, and in doing so it seemed logical to make a few other updates to modernise the package. The updates were written by Claude, but are fairly simple - I've reviewed it all and can't see any obvious problems, and would welcome a thorough review. Claude's own summary of the changes is below.

Problem

Starfish currently cannot be installed on any Python newer than 3.10:

  • python_requires = ">=3.7,<3.11" makes pip reject the package outright on 3.11+
    (ERROR: Package 'astrostarfish' requires a different Python: 3.11.5 not in '<3.11,>=3.7').
  • On older Pythons, the capped dependencies (astropy>=4,<6, numpy<2, …) force pip to
    build very old sdists from source, which fails against modern build tooling (e.g. the
    astropy 4.x ImportError: cannot import name 'soft_unicode' from 'markupsafe' reported
    in Installation problems through pip #160).
  • Two dependencies are effectively dead: nptyping==1.* (abandoned; incompatible with
    NumPy 2 and the source of the <3.11 cap) and the dataclasses PyPI backport (only
    ever needed on Python 3.6, and harmful on modern interpreters).

Since Starfish is pure Python, unblocking modern interpreters is almost entirely a
packaging/metadata fix plus a handful of small code changes.

Changes

Packaging

  • Migrated all metadata from setup.py to a PEP 621 pyproject.toml;
    requires-python = ">=3.11", classifiers for 3.11–3.14.
  • Removed the dataclasses backport and nptyping.
  • Relaxed dependency caps to floors: astropy>=5.3, numpy>=1.24 (NumPy 1.x and
    2.x are both supported), scipy>=1.10, scikit-learn>=1.2, extinction>=0.4.7
    (ships wheels through cp314), h5py>=3.8, flatdict>=4.0, toml>=0.10.2,
    tqdm>=4.60.
  • toml is kept (rather than stdlib tomllib) because SpectrumModel.save() relies on
    toml.TomlNumpyEncoder for writing NumPy scalars, and tomllib is read-only.

Code compatibility

  • Type annotations moved from nptyping to numpy.typing.NDArray
    (spectrum.py, emulator/emulator.py, models/utils.py) — annotation-only.
  • np.trapzscipy.integrate.trapezoid (7 sites; same algorithm, works on
    NumPy 1.24–2.x) and np.Infnp.inf (removed in NumPy 2).
  • eval("extinction.{law}")getattr(extinction, law) (law names were already
    whitelist-validated).
  • plt.style.use("seaborn")"seaborn-v0_8" with a graceful fallback (the bare name
    was removed in matplotlib 3.6, so importing emulator.plotting raised).
  • Raw-stringed two matplotlib labels that trigger SyntaxWarning: invalid escape sequence '\l' on Python 3.12+ (an error in a future Python).
  • Removed the dead "samplers" entry from Starfish.__all__ (no such module).
  • Fixed test_no_par_truncation, which called np.asarray() on the PHOENIX grid's
    ragged parameter list — an error since NumPy 1.24. The test now iterates the list
    directly (equivalent to the old object-array behaviour).

CI / docs

  • CI matrix bumped to Python 3.11–3.14 × {ubuntu, macos, windows}; updated stale
    actions (checkout@v4, setup-python@v5, cache@v4, codecov@v4); dropped the
    unmaintained pytest-black plugin from the test run.
  • Release workflow now uses python -m build and
    pypa/gh-action-pypi-publish@release/v1 (replaces the deprecated pep517.build).
  • Docs: app.add_stylesheetapp.add_css_file (removed in Sphinx 4), unpinned the
    docs toolchain (builds cleanly on Sphinx 9.1), migrated .readthedocs.yml to the
    current build.os/build.tools schema.

Correctness and performance

No numerical code path changes behaviour: the annotation swap has zero runtime effect,
scipy.integrate.trapezoid is the implementation NumPy's own migration notes point to,
and np.Inf/np.inf are the same object.

Verified explicitly by running the old code + old pinned deps (Python 3.10 / NumPy 1.26)
against the new code (Python 3.13 / NumPy 2.5) on identical inputs across 13 outputs
(all transforms, all five extinction laws, PHOENIX flux normalization): the
trapezoid-affected paths are bit-for-bit identical; the remainder agree to
≤ 7×10⁻¹³ relative (FFT differences between NumPy builds, not this diff). The
pytest-benchmark suite shows performance parity.

Testing

  • Full test suite passes on all 12 CI jobs — Python 3.11 / 3.12 / 3.13 / 3.14 ×
    ubuntu / macos / windows — against real downloaded PHOENIX models:
    https://github.com/pscicluna/Starfish/actions/runs/29474810935
  • Additionally run locally on Python 3.11 against both NumPy 1.26 and NumPy 2.4
    with identical results, confirming the change is NumPy-1/2 agnostic.
  • python -m build + twine check pass; clean pip install verified from both wheel
    and sdist on 3.11–3.14.

🤖 Generated with Claude Code

claude added 2 commits July 16, 2026 05:38
Fixes installation on modern Python (Starfish-develop#160):

- Migrate packaging metadata from setup.py to PEP 621 pyproject.toml
  with requires-python >=3.11 (was capped at <3.11)
- Drop the obsolete dataclasses backport and the abandoned nptyping
  dependency (replaced by numpy.typing.NDArray annotations)
- Relax dependency upper caps (astropy, numpy, scipy, scikit-learn,
  extinction, h5py, flatdict, toml, tqdm) so modern wheels are used
- Replace np.trapz with scipy.integrate.trapezoid and np.Inf with
  np.inf for NumPy 2 compatibility (works with NumPy 1.24+ too)
- Replace eval() with getattr() for extinction law lookup
- Fix matplotlib "seaborn" style name removed in matplotlib 3.6
- Remove dead "samplers" entry from Starfish.__all__
- Update CI matrix to 3.11-3.14, bump stale GitHub Action versions,
  drop unmaintained pytest-black, build releases with python -m build
- Fix Sphinx 4+ add_css_file API in docs/conf.py, unpin docs
  toolchain, migrate .readthedocs.yml to the current schema

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1cwqRt8tE5LDgfxmipTBk
np.asarray() on the PHOENIX grid's ragged points list (58 Teff, 12
logg, 9 Z values) raises ValueError on numpy>=1.24; iterate the list
directly instead. Also raw-string two matplotlib labels that trigger
SyntaxWarning on Python 3.14.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1cwqRt8tE5LDgfxmipTBk
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.

2 participants