diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cbc9aa6d335..42712bb3ac5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,15 +74,15 @@ repos: rev: 24.2.0 hooks: # check conformance to black formatting - id: black - #args: ['--diff', '-v', '--target-version', 'py39' ] # if run without arguments, will fail and will format the files - args: ['--target-version', 'py39' ] # Allow black to fail and provide auto-formatting to files that need it for compliance + #args: ['--diff', '-v', '--target-version', 'py310' ] # if run without arguments, will fail and will format the files + args: ['--target-version', 'py310' ] # Allow black to fail and provide auto-formatting to files that need it for compliance exclude: ".*build.*|\\/ThirdParty\\/|\\/Data\\/" - repo: https://github.com/asottile/pyupgrade rev: v3.19.0 hooks: - id: pyupgrade exclude: ".*build.*|\\/ThirdParty\\/|\\/Data\\/" - args: [--py39-plus] + args: [--py310-plus] - repo: https://github.com/SimpleITK/CommentSpellCheck.git rev: v0.4.4 hooks: diff --git a/Documentation/docs/contributing/python_packaging.md b/Documentation/docs/contributing/python_packaging.md index af742232aca..b29a54f5fc5 100644 --- a/Documentation/docs/contributing/python_packaging.md +++ b/Documentation/docs/contributing/python_packaging.md @@ -20,7 +20,7 @@ Building ITK Python wheels requires the following: - CMake >= 3.16 - Git - C++ Compiler (see [scikit-build platform specific requirements](https://scikit-build.readthedocs.io/en/latest/generators.html)) -- Python >= 3.9 +- Python >= 3.10 ## Automated Platform Scripts @@ -40,11 +40,11 @@ git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git pushd ITKPythonPackage export MANYLINUX_VERSION=2014 -./scripts/dockcross-manylinux-build-wheels.sh cp38 +./scripts/dockcross-manylinux-build-wheels.sh cp310 [...] ls -1 dist/ -itk-5.3.0.dev20231108-cp38-cp38m-manylinux2014_x86_64.whl +itk-6.0.0.dev20260401-cp310-cp310-manylinux2014_x86_64.whl ``` ### macOS @@ -61,11 +61,11 @@ Then, run [macpython-build-wheels.sh](https://github.com/InsightSoftwareConsorti git clone https://github.com/InsightSoftwareConsortium/ITKPythonPackage.git [...] -./scripts/macpython-build-wheels.sh cp38 +./scripts/macpython-build-wheels.sh cp310 [...] ls -1 dist/ -itk-5.3.0.dev20231108-cp38-cp38m-macosx_10_9_x86_64.whl +itk-6.0.0.dev20260401-cp310-cp310-macosx_11_0_arm64.whl ``` ### Windows diff --git a/Testing/ContinuousIntegration/AzurePipelinesLinux.yml b/Testing/ContinuousIntegration/AzurePipelinesLinux.yml index 7d56c2727cd..72912b467ee 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesLinux.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesLinux.yml @@ -245,7 +245,7 @@ jobs: displayName: "Checkout pull request HEAD" - task: UsePythonVersion@0 inputs: - versionSpec: "3.9" + versionSpec: "3.10" architecture: "x64" - bash: | set -x diff --git a/Wrapping/Generators/Python/CMakeLists.txt b/Wrapping/Generators/Python/CMakeLists.txt index b4f0cefb7f3..dd496c2a010 100644 --- a/Wrapping/Generators/Python/CMakeLists.txt +++ b/Wrapping/Generators/Python/CMakeLists.txt @@ -166,7 +166,7 @@ if(NOT EXTERNAL_WRAP_ITK_PROJECT) ) configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/itkConfig.py.in" + "${CMAKE_CURRENT_SOURCE_DIR}/itkConfig.template.in.py" "${ITK_WRAP_PYTHON_ROOT_BINARY_DIR}/itkConfig.py" @ONLY ) diff --git a/Wrapping/Generators/Python/PyBase/pyBase.i b/Wrapping/Generators/Python/PyBase/pyBase.i index 1f825de6434..c90d8020de7 100644 --- a/Wrapping/Generators/Python/PyBase/pyBase.i +++ b/Wrapping/Generators/Python/PyBase/pyBase.i @@ -12,8 +12,8 @@ import collections from sys import version_info as _version_info # Set values below to the same value as # PYTHON_VERSION_MIN in ITKSetPython3Vars.cmake -if _version_info < (3, 9, 0): - raise RuntimeError("Python 3.9 or later required") +if _version_info < (3, 10, 0): + raise RuntimeError("Python 3.10 or later required") from . import _ITKCommonPython %} diff --git a/Wrapping/Generators/Python/itk/pyi_generator.py b/Wrapping/Generators/Python/itk/pyi_generator.py index 3b4ee8d99ff..d8007fb6aed 100644 --- a/Wrapping/Generators/Python/itk/pyi_generator.py +++ b/Wrapping/Generators/Python/itk/pyi_generator.py @@ -10,7 +10,6 @@ from io import StringIO from pathlib import Path, PurePath import pickle -from typing import Union import glob import re from collections import defaultdict @@ -380,7 +379,7 @@ def write_class_proxy_pyi( pyi_file.write(interfaces_code) -def unpack(file_names: [str], save_dir: str) -> Union[str, None]: +def unpack(file_names: [str], save_dir: str) -> str | None: class_definitions = [] for file_name in file_names: @@ -429,7 +428,7 @@ def unpack(file_names: [str], save_dir: str) -> Union[str, None]: return None -def merge(class_definitions: []) -> Union[ITKClass, None]: +def merge(class_definitions: []) -> ITKClass | None: # Merge all the class files together to return one complete class. if len(class_definitions) == 0: return None diff --git a/Wrapping/Generators/Python/itk/support/base.py b/Wrapping/Generators/Python/itk/support/base.py index 33563d5bf95..1d3ce9f08c6 100644 --- a/Wrapping/Generators/Python/itk/support/base.py +++ b/Wrapping/Generators/Python/itk/support/base.py @@ -21,7 +21,7 @@ from sys import stderr as system_error_stream # Required to work around weird import error with xarray -from typing import Any, Optional, Union +from typing import Any from collections.abc import Sequence import itkConfig @@ -305,7 +305,7 @@ class ITKTemplateFeatures: ('Image', 'itk::Image', 'itkImageSS2', True, 'signed short,2'), """ - def __init__(self, feature_tuple: Sequence[Union[str, bool]]) -> None: + def __init__(self, feature_tuple: Sequence[str | bool]) -> None: feature_length: int = len(feature_tuple) # ITK classes have exactly 5 elements in the tuple, otherwise they are swig classes self._is_itk_class: bool = feature_length == 5 @@ -317,7 +317,7 @@ def __init__(self, feature_tuple: Sequence[Union[str, bool]]) -> None: self._cpp_class_name: str = feature_tuple[1] self._swig_class_name: str = feature_tuple[2] self._class_in_module: bool = feature_tuple[3] if feature_length >= 4 else False - self._template_parameters: Optional[str] = ( + self._template_parameters: str | None = ( feature_tuple[4] if feature_length == 5 else None ) diff --git a/Wrapping/Generators/Python/itk/support/build_options.py b/Wrapping/Generators/Python/itk/support/build_options.py index 7744e62a26d..3b9aabee70b 100644 --- a/Wrapping/Generators/Python/itk/support/build_options.py +++ b/Wrapping/Generators/Python/itk/support/build_options.py @@ -8,7 +8,6 @@ from itk.support import types from itk.support.template_class import itkTemplate, itkTemplateBase -from typing import Union from itkConfig import ITK_GLOBAL_WRAPPING_BUILD_OPTIONS as _itkwrapbo DIMS: list[int] = [int(s) for s in _itkwrapbo["ITK_WRAP_IMAGE_DIMS"] if s] @@ -62,7 +61,7 @@ SCALARS: list[types.itkCType] = INTS + REALS VECTORS: list[itkTemplate] = VECTOR_REALS + COV_VECTOR_REALS COLORS: list[itkTemplate] = RGBS + RGBAS -ALL_TYPES: list[Union[types.itkCType, itkTemplate]] = ( +ALL_TYPES: list[types.itkCType | itkTemplate] = ( COLORS + VECTORS + SCALARS + COMPLEX_REALS ) diff --git a/Wrapping/Generators/Python/itk/support/extras.py b/Wrapping/Generators/Python/itk/support/extras.py index 787a0eb85f4..a01f9a3f3b9 100644 --- a/Wrapping/Generators/Python/itk/support/extras.py +++ b/Wrapping/Generators/Python/itk/support/extras.py @@ -16,9 +16,11 @@ # # ========================================================================== +from __future__ import annotations + import enum import re -from typing import Optional, Union, Any, TYPE_CHECKING +from typing import Any, TYPE_CHECKING from collections.abc import Sequence from sys import stderr as system_error_stream @@ -33,7 +35,7 @@ import os import builtins -fileiotype = Union[str, bytes, os.PathLike] +fileiotype = str | bytes | os.PathLike import itk.support.types as itkt @@ -178,7 +180,7 @@ def echo(obj, f=system_error_stream) -> None: print(f, obj) -def size(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[int]: +def size(image_or_filter: itkt.ImageOrImageSource) -> Sequence[int]: """Return the size of an image, or of the output image of a filter This method take care of updating the needed information @@ -192,7 +194,7 @@ def size(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[int]: return img.GetLargestPossibleRegion().GetSize() -def physical_size(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[float]: +def physical_size(image_or_filter: itkt.ImageOrImageSource) -> Sequence[float]: """Return the physical size of an image, or of the output image of a filter This method take care of updating the needed information @@ -208,7 +210,7 @@ def physical_size(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[float] return result -def spacing(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[float]: +def spacing(image_or_filter: itkt.ImageOrImageSource) -> Sequence[float]: """Return the spacing of an image, or of the output image of a filter This method take care of updating the needed information @@ -221,7 +223,7 @@ def spacing(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[float]: return img.GetSpacing() -def origin(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[float]: +def origin(image_or_filter: itkt.ImageOrImageSource) -> Sequence[float]: """Return the origin of an image, or of the output image of a filter This method take care of updating the needed information @@ -234,7 +236,7 @@ def origin(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[float]: return img.GetOrigin() -def index(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[int]: +def index(image_or_filter: itkt.ImageOrImageSource) -> Sequence[int]: """Return the index of an image, or of the output image of a filter This method take care of updating the needed information @@ -247,7 +249,7 @@ def index(image_or_filter: "itkt.ImageOrImageSource") -> Sequence[int]: return img.GetLargestPossibleRegion().GetIndex() -def region(image_or_filter: "itkt.ImageOrImageSource") -> "itkt.ImageRegion": +def region(image_or_filter: itkt.ImageOrImageSource) -> itkt.ImageRegion: """Return the region of an image, or of the output image of a filter This method take care of updating the needed information @@ -318,7 +320,7 @@ def _GetArrayFromImage( def GetArrayFromImage( - image_or_filter: "itkt.ImageOrImageSource", + image_or_filter: itkt.ImageOrImageSource, keep_axes: bool = False, update: bool = True, ttype=None, @@ -341,7 +343,7 @@ def GetArrayFromImage( def GetArrayViewFromImage( - image_or_filter: "itkt.ImageOrImageSource", + image_or_filter: itkt.ImageOrImageSource, keep_axes: bool = False, update: bool = True, ttype=None, @@ -426,7 +428,7 @@ def _GetImageFromArray( def GetImageFromArray( arr: ArrayLike, is_vector: bool = False, ttype=None -) -> "itkt.ImageBase": +) -> itkt.ImageBase: """Get an ITK image from a Python array. This is a deep copy of the NumPy array buffer and is completely safe without potential @@ -455,7 +457,7 @@ def GetImageFromArray( def GetImageViewFromArray( arr: ArrayLike, is_vector: bool = False, ttype=None, need_contiguous=True -) -> "itkt.ImageBase": +) -> itkt.ImageBase: """Get an ITK image view (shared pixel buffer memory) from a Python array. If is_vector is True, then a 3D array will be treated as a 2D vector image, @@ -484,7 +486,7 @@ def GetImageViewFromArray( def array_from_vector_container( - container: "itkt.VectorContainer", ttype=None + container: itkt.VectorContainer, ttype=None ) -> np.ndarray: """Get an Array with the content of the vector container""" import itk @@ -510,7 +512,7 @@ def array_from_vector_container( def array_view_from_vector_container( - container: "itkt.VectorContainer", ttype=None + container: itkt.VectorContainer, ttype=None ) -> np.ndarray: """Get an Array view with the content of the vector container""" import itk @@ -535,7 +537,7 @@ def array_view_from_vector_container( return itk.PyVectorContainer[keys[0]].array_view_from_vector_container(container) -def vector_container_from_array(arr: ArrayLike, ttype=None) -> "itkt.VectorContainer": +def vector_container_from_array(arr: ArrayLike, ttype=None) -> itkt.VectorContainer: """Get a vector container from a Python array""" import itk @@ -667,7 +669,7 @@ def GetArrayFromMatrix(itk_matrix) -> np.ndarray: array_from_matrix = GetArrayFromMatrix -def GetMatrixFromArray(arr: ArrayLike) -> "itkt.Matrix": +def GetMatrixFromArray(arr: ArrayLike) -> itkt.Matrix: import itk # Verify inputs @@ -685,7 +687,7 @@ def GetMatrixFromArray(arr: ArrayLike) -> "itkt.Matrix": matrix_from_array = GetMatrixFromArray -def vtk_image_from_image(l_image: "itkt.ImageOrImageSource") -> "vtk.vtkImageData": +def vtk_image_from_image(l_image: itkt.ImageOrImageSource) -> vtk.vtkImageData: """Convert an itk.Image to a vtk.vtkImageData.""" import itk import vtk @@ -742,7 +744,7 @@ def vtk_image_from_image(l_image: "itkt.ImageOrImageSource") -> "vtk.vtkImageDat return vtk_image -def image_from_vtk_image(vtk_image: "vtk.vtkImageData") -> "itkt.ImageBase": +def image_from_vtk_image(vtk_image: vtk.vtkImageData) -> itkt.ImageBase: """Convert a vtk.vtkImageData to an itk.Image.""" import itk from vtk.util.numpy_support import vtk_to_numpy @@ -788,7 +790,7 @@ def image_from_vtk_image(vtk_image: "vtk.vtkImageData") -> "itkt.ImageBase": return l_image -def dict_from_image(image: "itkt.Image") -> dict: +def dict_from_image(image: itkt.Image) -> dict: """Serialize a Python itk.Image object to a pickable Python dictionary.""" import itk @@ -811,7 +813,7 @@ def dict_from_image(image: "itkt.Image") -> dict: ) -def image_from_dict(image_dict: dict) -> "itkt.Image": +def image_from_dict(image_dict: dict) -> itkt.Image: """Deserialize an dictionary representing an itk.Image object.""" import itk @@ -840,7 +842,7 @@ def image_from_dict(image_dict: dict) -> "itkt.Image": return image -def mesh_from_dict(mesh_dict: dict) -> "itkt.Mesh": +def mesh_from_dict(mesh_dict: dict) -> itkt.Mesh: """Deserialize an dictionary representing an itk.Mesh object.""" import itk @@ -868,7 +870,7 @@ def mesh_from_dict(mesh_dict: dict) -> "itkt.Mesh": return mesh -def dict_from_mesh(mesh: "itkt.Mesh") -> dict: +def dict_from_mesh(mesh: itkt.Mesh) -> dict: """Serialize a Python itk.Mesh object to a pickable Python dictionary.""" import itk @@ -936,7 +938,7 @@ def dict_from_mesh(mesh: "itkt.Mesh") -> dict: ) -def pointset_from_dict(pointset_dict: dict) -> "itkt.PointSet": +def pointset_from_dict(pointset_dict: dict) -> itkt.PointSet: """Deserialize an dictionary representing an itk.PointSet object.""" import itk @@ -955,7 +957,7 @@ def pointset_from_dict(pointset_dict: dict) -> "itkt.PointSet": return mesh -def dict_from_pointset(pointset: "itkt.PointSet") -> dict: +def dict_from_pointset(pointset: itkt.PointSet) -> dict: """Serialize a Python itk.PointSet object to a pickable Python dictionary.""" import itk @@ -1000,7 +1002,7 @@ def dict_from_pointset(pointset: "itkt.PointSet") -> dict: ) -def polyline_from_dict(polyline_dict: dict) -> "itkt.PolylineParametricPath": +def polyline_from_dict(polyline_dict: dict) -> itkt.PolylineParametricPath: """Deserialize an dictionary representing an itk.PolylineParametricPath object.""" import itk @@ -1014,7 +1016,7 @@ def polyline_from_dict(polyline_dict: dict) -> "itkt.PolylineParametricPath": return polyline -def dict_from_polyline(polyline: "itkt.PolylineParametricPath") -> dict: +def dict_from_polyline(polyline: itkt.PolylineParametricPath) -> dict: """Serialize a Python itk.PolylineParametricPath object to a pickable Python dictionary.""" import itk @@ -1027,8 +1029,8 @@ def dict_from_polyline(polyline: "itkt.PolylineParametricPath") -> dict: def dict_from_transform( - transform: Union["itkt.TransformBase", list["itkt.TransformBase"]], -) -> Union[list[dict], dict]: + transform: itkt.TransformBase | list[itkt.TransformBase], +) -> list[dict] | dict: """Serialize a Python itk.Transform object to a pickable Python dictionary. If the transform is a list of transforms, then a list of dictionaries is returned. @@ -1106,8 +1108,8 @@ def add_transform_dict(transform): def transform_from_dict( - transform_dict: Union[dict, list[dict]], -) -> "itkt.TransformBase": + transform_dict: dict | list[dict], +) -> itkt.TransformBase: """Deserialize a dictionary representing an itk.Transform object. If the dictionary represents a list of transforms, then a Composite Transform is returned. @@ -1208,7 +1210,7 @@ def special_transform_check(transform_name): return transform -def image_intensity_min_max(image_or_filter: "itkt.ImageOrImageSource"): +def image_intensity_min_max(image_or_filter: itkt.ImageOrImageSource): """Return the minimum and maximum of values in a image of in the output image of a filter The minimum and maximum values are returned in a tuple: (min, max) @@ -1236,10 +1238,10 @@ def range(image_or_filter): def imwrite( - image_or_filter: "itkt.ImageOrImageSource", + image_or_filter: itkt.ImageOrImageSource, filename: fileiotype, compression: bool = False, - imageio: Optional["itkt.ImageIOBase"] = None, + imageio: itkt.ImageIOBase | None = None, ) -> None: """Write a image or the output image of a filter to a file. @@ -1278,12 +1280,12 @@ def imwrite( def imread( - filename: Union[fileiotype, Sequence[Union[str, os.PathLike]]], - pixel_type: Optional["itkt.PixelTypes"] = None, + filename: fileiotype | Sequence[str | os.PathLike], + pixel_type: itkt.PixelTypes | None = None, fallback_only: bool = False, - imageio: Optional["itkt.ImageIOBase"] = None, - series_uid: Optional[Union[int, str]] = None, -) -> "itkt.ImageBase": + imageio: itkt.ImageIOBase | None = None, + series_uid: int | str | None = None, +) -> itkt.ImageBase: """Read an image from a file or series of files and return an itk.Image. Parameters @@ -1417,7 +1419,7 @@ def imread( def meshwrite( - mesh: "itkt.Mesh", + mesh: itkt.Mesh, filename: fileiotype, compression: bool = False, binary: bool = False, @@ -1443,9 +1445,9 @@ def meshwrite( def meshread( filename: fileiotype, - pixel_type: Optional["itkt.PixelTypes"] = None, + pixel_type: itkt.PixelTypes | None = None, fallback_only: bool = False, -) -> "itkt.Mesh": +) -> itkt.Mesh: """Read a mesh from a file and return an itk.Mesh. The reader is instantiated with the mesh type of the mesh file if @@ -1493,7 +1495,7 @@ def meshread( return reader.GetOutput() -def transformread(filename: fileiotype) -> list["itkt.TransformBase"]: +def transformread(filename: fileiotype) -> list[itkt.TransformBase]: """Read an itk Transform file. Parameters @@ -1524,7 +1526,7 @@ def transformread(filename: fileiotype) -> list["itkt.TransformBase"]: def transformwrite( - transforms: Union["itkt.TransformBase", list["itkt.TransformBase"]], + transforms: itkt.TransformBase | list[itkt.TransformBase], filename: fileiotype, compression: bool = False, ) -> None: @@ -1587,8 +1589,8 @@ def search(s: str, case_sensitive: bool = False) -> list[str]: # , fuzzy=True): def set_inputs( new_itk_object, - inargs: Optional[Sequence[Any]] = None, - inkargs: Optional[dict[str, Any]] = None, + inargs: Sequence[Any] | None = None, + inkargs: dict[str, Any] | None = None, ): """Set the inputs of the given objects, according to the non named or the named parameters in args and kargs @@ -1845,7 +1847,7 @@ def has_key(self, key: str): def __contains__(self, key: str): return key in self - def get(self, key: str, default: Optional[str] = None) -> Optional[str]: + def get(self, key: str, default: str | None = None) -> str | None: return self.get(key, default) def __len__(self): @@ -1954,7 +1956,7 @@ def __call__(self, *args, **kargs): self.UpdateLargestPossibleRegion() return self - def expose(self, name: str, new_name: Optional[str] = None, position: int = -1): + def expose(self, name: str, new_name: str | None = None, position: int = -1): """Expose an attribute from a filter of the mini-pipeline. Once called, the pipeline instance has a new Set/Get set of methods to @@ -2002,7 +2004,7 @@ def Stop() -> None: auto_pipeline.current = None -def down_cast(obj: "itkt.LightObject"): +def down_cast(obj: itkt.LightObject): """Down cast an itk.LightObject (or a object of a subclass) to its most specialized type. """ @@ -2232,7 +2234,7 @@ def template(cl): return itkTemplateBase.__template_instantiations_object_to_name__[class_(cl)] -def ctype(s: str) -> "itkt.itkCType": +def ctype(s: str) -> itkt.itkCType: """Return the c type corresponding to the string passed in parameter The string can contain some extra spaces. diff --git a/Wrapping/Generators/Python/itk/support/init_helpers.py b/Wrapping/Generators/Python/itk/support/init_helpers.py index 49c3f719562..4d8ddec97bf 100644 --- a/Wrapping/Generators/Python/itk/support/init_helpers.py +++ b/Wrapping/Generators/Python/itk/support/init_helpers.py @@ -1,6 +1,5 @@ from sys import stderr as _system_error_stream from enum import IntEnum, unique -from typing import Union __all__ = [ "auto_not_in_place", @@ -39,7 +38,7 @@ class AutoProgressTypes(IntEnum): def auto_progress( - progress_type: Union[bool, AutoProgressTypes] = AutoProgressTypes.TERMINAL, + progress_type: bool | AutoProgressTypes = AutoProgressTypes.TERMINAL, ) -> None: """Set up auto progress report diff --git a/Wrapping/Generators/Python/itk/support/template_class.py b/Wrapping/Generators/Python/itk/support/template_class.py index 96a765bf8b6..7698a85aa9f 100644 --- a/Wrapping/Generators/Python/itk/support/template_class.py +++ b/Wrapping/Generators/Python/itk/support/template_class.py @@ -23,7 +23,8 @@ import types import collections import warnings -from typing import Any, Callable, Union +from typing import Any +from collections.abc import Callable import itkConfig @@ -299,7 +300,7 @@ def __local__init__(self, new_object_name: str) -> None: so that the singleton takes preference. Use this to define the class member elements """ - self.__template__: dict[str, Union[str, Callable[..., Any]]] = ( + self.__template__: dict[str, str | Callable[..., Any]] = ( collections.OrderedDict() ) self.__name__: str = new_object_name diff --git a/Wrapping/Generators/Python/itk/support/types.py b/Wrapping/Generators/Python/itk/support/types.py index cf5b9b307e1..f929d29361f 100644 --- a/Wrapping/Generators/Python/itk/support/types.py +++ b/Wrapping/Generators/Python/itk/support/types.py @@ -46,7 +46,6 @@ class itkCType: # import locally to facilitate dynamic loading in itk/__init__.py import numpy as np - from typing import Optional __c_types__: dict[str, "itkCType"] = {} __c_types_for_dtype__: dict[str, np.dtype] = {} @@ -71,7 +70,7 @@ def __repr__(self) -> str: return f"" @staticmethod - def GetCType(name: str) -> Optional["itkCType"]: + def GetCType(name: str) -> "itkCType | None": # import locally to facilitate dynamic loading in itk/__init__.py """Get the type corresponding to the provided C primitive type name.""" @@ -90,7 +89,7 @@ def GetCType(name: str) -> Optional["itkCType"]: return None @staticmethod - def GetCTypeForDType(np_dtype: np.dtype) -> Optional["itkCType"]: + def GetCTypeForDType(np_dtype: np.dtype) -> "itkCType | None": """Get the type corresponding to the provided numpy.dtype.""" try: return itkCType.__c_types_for_dtype__[np_dtype] diff --git a/Wrapping/Generators/Python/itkConfig.py.in b/Wrapping/Generators/Python/itkConfig.template.in.py similarity index 94% rename from Wrapping/Generators/Python/itkConfig.py.in rename to Wrapping/Generators/Python/itkConfig.template.in.py index 4ed680c534f..1e68019fa54 100644 --- a/Wrapping/Generators/Python/itkConfig.py.in +++ b/Wrapping/Generators/Python/itkConfig.template.in.py @@ -34,7 +34,6 @@ LazyLoading: Only load an itk library when needed. Before the library is loaded, the namespace will be inhabited with dummy objects.""" -from typing import Dict, List, Optional, Type, Union # User options SILENT: int = 0 @@ -51,6 +50,7 @@ def _get_environment_boolean(environment_var: str, default_string: str) -> bool: # False values are n, no, f, false, off and 0. # Raises ValueError if val is anything else. from os import environ as _environ + def _strtobool(val: str) -> bool: val = val.lower() if val in ("y", "yes", "t", "true", "on", "1"): @@ -60,7 +60,6 @@ def _strtobool(val: str) -> bool: else: raise ValueError(f"invalid truth value {val}") - try: _StringDefault: str = _environ.get(environment_var, default_string) return bool(_strtobool(_StringDefault)) @@ -77,7 +76,9 @@ def _strtobool(val: str) -> bool: return bool(_strtobool(default_string)) -DefaultFactoryLoading: bool = _get_environment_boolean("ITK_PYTHON_DEFAULTFACTORYLOADING", "True") +DefaultFactoryLoading: bool = _get_environment_boolean( + "ITK_PYTHON_DEFAULTFACTORYLOADING", "True" +) LazyLoading: bool = _get_environment_boolean("ITK_PYTHON_LAZYLOADING", "True") NotInPlace: bool = _get_environment_boolean("ITK_PYTHON_NOTINPLACE", "False") del _get_environment_boolean @@ -86,11 +87,11 @@ def _strtobool(val: str) -> bool: def _itk_format_warning( - message: Union[Warning, str], - category: Type[Warning], # Ignore category + message: Warning | str, + category: type[Warning], # Ignore category filename: str, # Ignore filename lineno: int, # Ignore lineno - line: Optional[str] = None, # Ignore line + line: str | None = None, # Ignore line ) -> str: """Format the warnings issued by itk to display only the message. @@ -151,7 +152,7 @@ def _normalized_path(relative_posix_path: str, message) -> str: ITK_GLOBAL_VERSION_STRING: str = ( "@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@" ) -ITK_GLOBAL_WRAPPING_BUILD_OPTIONS: Dict[str, List[str]] = { +ITK_GLOBAL_WRAPPING_BUILD_OPTIONS: dict[str, list[str]] = { "ITK_WRAP_IMAGE_DIMS": "@ITK_WRAP_IMAGE_DIMS@".split(";"), "WRAP_ITK_USIGN_INT": "@WRAP_ITK_USIGN_INT@".split(";"), "WRAP_ITK_SIGN_INT": "@WRAP_ITK_SIGN_INT@".split(";"),