Skip to content

chore: drop Python 3.9, require 3.10+ - #1135

Draft
henryiii wants to merge 1 commit into
developfrom
chore/drop-python-39-1132
Draft

chore: drop Python 3.9, require 3.10+#1135
henryiii wants to merge 1 commit into
developfrom
chore/drop-python-39-1132

Conversation

@henryiii

Copy link
Copy Markdown
Member

🤖 AI text below 🤖

Addresses part of #1132.

Python 3.9 reached EOL in October 2025. This PR drops 3.9 support, bumping the minimum to Python 3.10, and applies the modernizations that unlocks.

Changes

pyproject.toml

  • requires-python = ">=3.10" (was >=3.9)
  • numpy >=1.21.3 (oldest numpy with a 3.10 wheel; was >=1.21)
  • Added explicit Programming Language :: Python :: 3.10/3.11/3.12/3.13 classifiers
  • [tool.cibuildwheel]: removed cp39-musllinux_i686 skip entry (replaced with cp310-musllinux_i686)
  • [[tool.cibuildwheel.overrides]]: selector changed from cp3{9,10}-manylinux* to cp310-manylinux*

.github/workflows/release.yml

  • Removed cp39 from the py: matrix
  • Removed two cp39 excludes (ubuntu-24.04-arm and windows-11-arm)

.github/workflows/test.yml

  • Minimum-version test leg updated from python-version: "3.9" / numpy==1.21.0 to python-version: "3.10" / numpy==1.21.3

noxfile.py

  • No changes needed: MINIMUM_PYTHON reads from pyproject.toml dynamically, so it picks up 3.10 automatically.

Typing modernization (src/iminuit/)

  • typing.py: removed Optional, Union, List imports; Key type alias and UserBound/Interval fields now use X | Y and float | None syntax; added from __future__ import annotations
  • ipywidget.py, qtwidget.py: from typing import Dict, Callable replaced with collections.abc.Callable and dict[str, Any]
  • Ruff UP auto-fixes applied across src/ (213 fixes): deprecated typing.Union, Optional, List, Tuple, Dict, Set usages replaced with modern equivalents in minuit.py, cost.py, util.py, _deprecated.py, _optional_dependencies.py, _parse_version.py, _repr_html.py; unused typing imports removed (F401)
  • One correctness fix in minuit.py: method: str | Callable | None = None (ruff correctly surfaced a latent mypy issue)

doc/conf.py

  • Synced root_version to match the submodule SHA (pre-commit hook was failing on a pre-existing mismatch)

Test results

All tests pass on Python 3.10 except tests/test_tabulate.py::test_params which is a pre-existing failure on the develop branch (tabulate column-alignment difference unrelated to this PR).

Note on conflicts

This PR modifies minuit.py, cost.py, and util.py (import blocks only, not logic). It may conflict slightly with parallel bugfix PRs touching those same files. Recommend merging this PR last among active PRs, or rebasing it on top of them once they land.

@henryiii

Copy link
Copy Markdown
Member Author

Ahh, I've been trying to remember to tell it not to do a Python drop, missed this one had that recommendation. If this is helpful, we can leave it open, if you prefer to do it yourself eventually, happy to close. (I have a custom skill that can be used for Python drops, too, at https://github.com/henryiii/skills).

@henryiii
henryiii force-pushed the chore/drop-python-39-1132 branch from 8ad48f8 to 2b66bd5 Compare June 15, 2026 12:40
@henryiii
henryiii force-pushed the chore/drop-python-39-1132 branch from 2b66bd5 to af3e7da Compare July 23, 2026 18:43
eduardo-rodrigues pushed a commit that referenced this pull request Jul 24, 2026
cibuildwheel/manylinux has dropped 3.13t (which was experimental only),
pybind11 is dropping 3.13t, numpy dropped it, etc, so drop it here too.
Support 3.14t+ only.

GitHub has also removed the `macos-13` runner, so the x86-64 macOS wheel
jobs now queue forever. Switch them to `macos-26-intel`.

This fixes the CI on jobs that touch files triggering wheel builds.

Part of unblocking #1143.

:robot: _AI text below_ :robot:

NumPy no longer ships free-threaded (`cp313t`) wheels for Windows
`win32` and `win_arm64`. cibuildwheel then tries to build numpy from
source in the wheel test step and fails (no compiler / `Python.h`). The
`cp313t` Windows jobs are red on any PR that triggers the wheel matrix
(e.g. #1133, #1135).

Free-threaded 3.14 (`cp314t`) wheels exist and already pass across the
whole matrix, so this drops `cp313t` from the wheel build matrix in
`release.yml` and keeps `cp314t`.
Python 3.9 reached EOL in October 2025. Bump the minimum required
version to 3.10 and apply the modernizations it unlocks: PEP 604
union types, builtin generics, and collections.abc.Callable in
place of deprecated typing aliases.

- pyproject.toml: requires-python >=3.10, numpy >=1.21.3, remove
  cp39 from cibuildwheel skip/overrides
- .github/workflows/release.yml: drop cp39 from wheel matrix
- .github/workflows/test.yml: min-version leg moved to 3.10/numpy 1.21.3
- src/iminuit/typing.py: use X | Y and builtin generics throughout
- src/iminuit/{ipywidget,qtwidget}.py: collections.abc.Callable, dict[]
- ruff UP fixes applied across src/ (F401 unused typing imports removed,
  Union/Optional/List/Tuple/Dict replaced with modern equivalents)
- doc/conf.py: sync root_version to submodule

Assisted-by: ClaudeCode:claude-sonnet-4-6
@henryiii
henryiii force-pushed the chore/drop-python-39-1132 branch from af3e7da to 777f194 Compare July 25, 2026 01:13
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