Skip to content

ENH: Update to minimum Python support to py310#6012

Merged
hjmjohnson merged 8 commits intoInsightSoftwareConsortium:mainfrom
hjmjohnson:enh/pre-commit-py310
Apr 7, 2026
Merged

ENH: Update to minimum Python support to py310#6012
hjmjohnson merged 8 commits intoInsightSoftwareConsortium:mainfrom
hjmjohnson:enh/pre-commit-py310

Conversation

@hjmjohnson
Copy link
Copy Markdown
Member

@hjmjohnson hjmjohnson commented Apr 4, 2026

Summary

  • Python 3.9 reached end-of-life in October 2025 and is no longer receiving security updates.
  • Update black and pyupgrade to target Python 3.10+, the oldest actively supported release.
Tool Before After
black --target-version py39 --target-version py310
pyupgrade --py39-plus --py310-plus

This aligns ITK's pre-commit config with BRAINSTools (which already uses py310 targets) and drops enforcement of syntax compatibility with an unsupported Python version.

Test plan

  • pre-commit run --all-files passes on this branch with no regressions.
  • Confirm no ITK Python files require py39-only syntax that would break under py310 enforcement.

🤖 Generated with Claude Code

@hjmjohnson hjmjohnson marked this pull request as draft April 4, 2026 14:03
@github-actions github-actions bot added the type:Enhancement Improvement of existing methods or implementation label Apr 4, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 4, 2026

Greptile Summary

This PR updates ITK's pre-commit configuration and Python source files to target Python 3.10+ instead of the EOL Python 3.9. The changes span linter configuration (.pre-commit-config.yaml), CI pipeline (AzurePipelinesLinux.yml), documentation (python_packaging.md), and Python type annotation modernization across several wrapping generator files. The itkConfig.py.in template is also renamed to itkConfig.template.in.py with its CMakeLists.txt reference updated.

Key changes:

  • black target updated from py39 to py310 and pyupgrade from --py39-plus to --py310-plus in .pre-commit-config.yaml
  • Python 3.10 type hint syntax (X | Y, X | None, built-in dict/list/type) replaces legacy typing.Union, typing.Optional, typing.Dict, typing.List, typing.Type across wrapping generator Python files
  • collections.abc.Callable replaces typing.Callable in template_class.py
  • Azure Pipelines pre-commit job updated to use Python 3.10
  • Documentation examples refreshed with updated Python/ITK version strings
  • Note: Wrapping/Generators/Python/PyBase/pyBase.i still contains a runtime version check if _version_info < (3, 9, 0) with the message "Python 3.9 or later required", even though CMake/ITKSetPython3Vars.cmake already sets PYTHON_VERSION_MIN = 3.10 and explicitly comments that these values should be kept in sync.

Confidence Score: 4/5

Mostly safe — one P1 inconsistency in pyBase.i where the runtime version guard still checks for Python 3.9 while the CMake minimum is already 3.10 and this PR adds 3.10-only syntax to the codebase.

All pre-commit, CI, and type-annotation changes look correct and consistent. The single P1 finding is in pyBase.i (not changed by this PR) where the runtime check if _version_info < (3, 9, 0) and its error message are inconsistent with CMake's PYTHON_VERSION_MIN=3.10 and with the new 3.10-only union syntax introduced in this PR — a Python 3.9 user would pass the guard but immediately hit a TypeError at import time.

Wrapping/Generators/Python/PyBase/pyBase.i — runtime version check and error message need to be updated from 3.9 to 3.10.

Important Files Changed

Filename Overview
.pre-commit-config.yaml Updated black target from py39 to py310 and pyupgrade from --py39-plus to --py310-plus; both active and commented-out args updated consistently
Documentation/docs/contributing/python_packaging.md Updated Python >= 3.9 to >= 3.10 and refreshed example wheel build script invocations and output filenames
Testing/ContinuousIntegration/AzurePipelinesLinux.yml Updated Azure Pipelines pre-commit job Python version spec from 3.9 to 3.10
Wrapping/Generators/Python/CMakeLists.txt Updated configure_file reference from itkConfig.py.in to itkConfig.template.in.py following the file rename
Wrapping/Generators/Python/itkConfig.template.in.py Renamed from itkConfig.py.in; removed typing imports and replaced with built-in generics and X
Wrapping/Generators/Python/itk/pyi_generator.py Removed top-level Union import; updated two function return annotations to use str
Wrapping/Generators/Python/itk/support/types.py Removed Optional import; updated GetCType and GetCTypeForDType return types to X
Wrapping/Generators/Python/itk/support/template_class.py Moved Callable import from typing to collections.abc; replaced Union[str, Callable] with str

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Python runtime imports itk] --> B{pyBase.i version check\nif _version_info < 3,9,0}
    B -->|Python < 3.9| C[RuntimeError: Python 3.9 or later required\n⚠️ Message still says 3.9]
    B -->|Python >= 3.9| D[Continue module loading]
    D --> E{Python version?}
    E -->|Python 3.9| F[TypeError: unsupported operand type\nfor | in union annotations\ne.g. str | None]
    E -->|Python >= 3.10| G[Imports succeed ✅]
    H[CMakeLists.txt / PYTHON_VERSION_MIN=3.10] -.->|Build-time enforcement| A
    style C fill:#ffcccc
    style F fill:#ffcccc
    style G fill:#ccffcc
Loading

Greploops — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.
Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

Reviews (2): Last reviewed commit: "ENH: Rename itkConfig.py.in to itkConfig..." | Re-trigger Greptile

@github-actions github-actions bot added type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots area:Python wrapping Python bindings for a class type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Documentation Issues affecting the Documentation module labels Apr 4, 2026
@hjmjohnson hjmjohnson force-pushed the enh/pre-commit-py310 branch from 29d9b1b to eccb91f Compare April 4, 2026 14:37
hjmjohnson and others added 3 commits April 4, 2026 09:46
ITK v6.0 requires Python >= 3.10 for wrapping. Update the
LinuxCxx20 CI job to use Python 3.10 instead of 3.9.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update the minimum Python version requirement from 3.9 to 3.10 and
modernize the wheel build examples from cp38/ITK 5.3 to cp310/ITK 6.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Python 3.9 reached end-of-life in October 2025.  Update black and
pyupgrade to target Python 3.10+, which is the oldest supported release.

- black: --target-version py39 -> py310
- pyupgrade: --py39-plus -> --py310-plus

This aligns ITK's pre-commit config with BRAINSTools (which already uses
py310) and drops support for a Python version that is no longer maintained.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@hjmjohnson hjmjohnson force-pushed the enh/pre-commit-py310 branch from 511815e to 9f9b850 Compare April 4, 2026 14:46
hjmjohnson and others added 2 commits April 4, 2026 10:00
Modernize type annotations in ITK Python wrapping code:
- Union[X, Y] -> X | Y (PEP 604)
- Optional[X] -> X | None (PEP 604)
- typing.Callable -> collections.abc.Callable (PEP 585)

These syntax forms are supported in Python >= 3.10.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Manually apply PEP 604/585 modernizations to itkConfig.py.in since
pre-commit hooks (black, pyupgrade) skip .py.in files:
- Union[Warning, str] -> Warning | str
- Type[Warning] -> type[Warning]
- Optional[str] -> str | None
- Dict[str, List[str]] -> dict[str, list[str]]
- Remove 'from typing import Dict, List, Optional, Type, Union'

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@hjmjohnson hjmjohnson force-pushed the enh/pre-commit-py310 branch from fea2085 to af68b5c Compare April 4, 2026 15:00
Rename the CMake configure_file template so that it has a .py extension
and is recognized as Python by pre-commit hooks (black, pyupgrade,
check-ast). The .py.in extension was classified as plain text by the
identify library, causing all Python linting hooks to skip the file.

The output filename remains itkConfig.py — only the source template
name changes.

Apply black formatting now that the file is covered by pre-commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@hjmjohnson hjmjohnson marked this pull request as ready for review April 4, 2026 15:15
hjmjohnson and others added 2 commits April 4, 2026 14:08
The pyupgrade --py310-plus conversion changed:

  Union["itkt.TransformBase", list["itkt.TransformBase"]]

to:

  "itkt.TransformBase" | list["itkt.TransformBase"]

This fails at runtime because Python evaluates annotations eagerly
by default, and str.__or__(GenericAlias) is not defined. Adding
`from __future__ import annotations` defers all annotation evaluation
to string form, making PEP 604 union syntax safe even with forward
references. pyupgrade then also removes the now-unnecessary string
quotes from other forward reference annotations.

Fixes 169 Python test failures in ITK.Linux.Python and
ITK.macOS.Python CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The runtime version guard in pyBase.i checked for Python 3.9 but
CMake/ITKSetPython3Vars.cmake already sets PYTHON_VERSION_MIN=3.10,
and the codebase now uses Python 3.10-only syntax (PEP 604 unions).

A Python 3.9 user would pass the old guard but immediately hit a
TypeError at import time from the X|Y type annotations.

Update the check and error message to match the CMake minimum,
as the comment in pyBase.i instructs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@hjmjohnson hjmjohnson requested a review from dzenanz April 5, 2026 11:06
Copy link
Copy Markdown
Member

@dzenanz dzenanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but preferably someone else should also review.

@blowekamp
Copy link
Copy Markdown
Member

Updating pre-commit and updating python in wrapping seem like two rather different things.

@hjmjohnson hjmjohnson changed the title ENH: Update pre-commit Python target from py39 to py310 ENH: Update to minimum Python support to py310 Apr 6, 2026
@hjmjohnson
Copy link
Copy Markdown
Member Author

Updating pre-commit and updating Python in wrapping seem like two rather different things.

@blowekamp updated the PR comment to reflect the full scope of these changes. Let me know if you want something else done.

@hjmjohnson hjmjohnson requested a review from thewtex April 6, 2026 20:48
Copy link
Copy Markdown
Member

@thewtex thewtex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Hans!

@hjmjohnson hjmjohnson merged commit 8a2451b into InsightSoftwareConsortium:main Apr 7, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Documentation Issues affecting the Documentation module area:Python wrapping Python bindings for a class type:Enhancement Improvement of existing methods or implementation type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants