COMP: Move ITK Python wrapping to SWIG 4.4.1#6484
Merged
hjmjohnson merged 6 commits intoJun 23, 2026
Merged
Conversation
Member
Author
|
Pushed a fix for the vendored-SWIG Python CI failure (ARMBUILD-Python / ITK.*.Python): the FetchContent refactor removed the |
78951a1 to
b91641b
Compare
hjmjohnson
added a commit
to InsightSoftwareConsortium/ITKTestingData
that referenced
this pull request
Jun 21, 2026
Content-addressed (CID) archives repackaged from the official SWIG 4.4.1 PyPI wheels (macOS 10.9 universal2, manylinux2010/2014, Windows), used as the IPFS/CDN mirror for ITK's vendored SWIG download. See InsightSoftwareConsortium/ITK#6484.
hjmjohnson
added a commit
to hjmjohnson/ITKTestingData
that referenced
this pull request
Jun 21, 2026
CID-addressed swig 4.4.1 source used by the ITK_USE_SYSTEM_SWIG=OFF source-build fallback when no prebuilt binary exists for the host. See InsightSoftwareConsortium/ITK#6484.
hjmjohnson
added a commit
to InsightSoftwareConsortium/ITKTestingData
that referenced
this pull request
Jun 21, 2026
CID-addressed swig 4.4.1 source used by the ITK_USE_SYSTEM_SWIG=OFF source-build fallback when no prebuilt binary exists for the host. See InsightSoftwareConsortium/ITK#6484.
This comment was marked as resolved.
This comment was marked as resolved.
ITK packs several SWIG modules per shared library and injects C that calls PyInit__<X>Python() and stores the return in sys.modules. SWIG 4.4 (PEP 489 multi-phase init) makes PyInit_* return a raw PyModuleDef rather than a populated module, so the proxy fails at import with 'moduledef' object has no attribute 'delete_SwigPyIterator'. Detect a returned def at runtime and instantiate it via PyModule_FromDefAndSpec + PyModule_ExecDef; the single-phase (<=4.3) path is unchanged. All APIs used are Limited-API-safe (>=3.5). Pin the abi3 floor to a single cached source of truth (_ITK_MINIMUM_SUPPORTED_LIMITED_API_VERSION = 3.11) shared by the Limited-API auto-detect and the USE_SABI setting, so 3.11+ builds load on Python 3.11; 3.10 keeps the non-Limited-API path. Assisted-by: Claude Code — root-cause analysis and local 3.11/3.13 validation
Replace the prebuilt-binary ExternalProject_Add download branches with a single FetchContent_Declare/MakeAvailable that downloads and extracts the binary at configure time, so SWIG_EXECUTABLE exists immediately and is checked against swig_version_min by itk_assert_swig_version() (runs 'swig -version'). A wrong or corrupt upload now fails at configure instead of deep in the build. The source-build fallback keeps ExternalProject_Add (it compiles SWIG + PCRE2). Point the download at SWIG 4.4.1 binaries repackaged from the official, broadly portable SWIG PyPI wheels (Linux manylinux2010/2014, macOS 10.9 universal2, Windows) and uploaded to data.kitware.com, which resolves each by its SHA512. Every archive shares one bin/swig[.exe] + share/swig/4.4.1 layout, so the per-platform swig_dir_subpath collapses to a single value. swig_version_min is raised 4.2.0 -> 4.3.0 (4.2.x lacks the SWIG_Py_DECREF runtime); too-old system swig is now a FATAL_ERROR. Assisted-by: Claude Code — FetchContent refactor and configure-time download+assert verification
Add swig (>=4.4.1) and castxml to the python pixi feature and pass ITK_USE_SYSTEM_SWIG/ITK_USE_SYSTEM_CASTXML in configure-python and configure-debug-python, so local 'pixi run build-python' uses the conda-forge toolchain instead of the internal download/build. CI continues to exercise the vendored 4.4.1 binaries via the standard Azure/ARM Python pipelines.
swig_archive was only read by the IPFS mirror URLs, which were dropped when the vendored download moved to data.kitware.com (resolved by SHA512). The macOS per-architecture branch existed solely to set it (the universal2 archive has one hash for both), so it collapses too.
swig_cmake_version and ITK_SWIG_VERSION were both 4.4.1 after the consolidation to PyPI-wheel archives (all platforms share the share/swig/<version> layout). Drop the duplicate so SWIG_DIR's version segment derives from a single source on both the prebuilt and source-build paths.
The data.kitware.com + ITKTestingData + IPFS gateway mirror list was duplicated across the prebuilt FetchContent download and the source-build ExternalProject. Emit it from a single itk_swig_mirror_urls() helper so the gateway set stays consistent across both swig acquisition paths.
hjmjohnson
commented
Jun 22, 2026
thewtex
approved these changes
Jun 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Move ITK Python wrapping to SWIG 4.4.1. Fixes the import regression in #6479; supersedes the temporary #6480 (4.3.x baseline) and #6481 (WIP CI).
Three focused commits, no WIP — standard GHA + Azure CI run on this PR. The Azure/ARM Python pipelines exercise the vendored 4.4.1 binaries; local
pixi run build-pythonuses conda-forge SWIG/CastXML.What changed
PyInit__<X>Python()and stores the return insys.modules. SWIG 4.4 (PEP 489 multi-phase init) makesPyInit_*return a rawPyModuleDef, so the proxy failed at import with'moduledef' object has no attribute 'delete_SwigPyIterator'. The injection now detects a returned def at runtime and instantiates it viaPyModule_FromDefAndSpec+PyModule_ExecDef; the single-phase (≤4.3) path is unchanged; all APIs are Limited-API-safe (≥3.5)._ITK_MINIMUM_SUPPORTED_LIMITED_API_VERSION(3.11), shared by the Limited-API auto-detect andUSE_SABI. 3.11+ build abi3 and load on 3.11; 3.10 keeps the non-Limited-API path.ExternalProject_AddtoFetchContent, soSWIG_EXECUTABLEexists at configure time anditk_assert_swig_version()confirms it reports ≥swig_version_min(now 4.3.0; too-old system swig is aFATAL_ERROR). Binaries are repackaged from the official, broadly-portable SWIG PyPI wheels and hosted on data.kitware.com (resolved by SHA512). Source-build fallback stays on ExternalProject.configure-python/configure-debug-pythonpassITK_USE_SYSTEM_SWIG/ITK_USE_SYSTEM_CASTXML;swig (>=4.4.1)+castxmladded to thepythonpixi feature.How the vendored binaries were produced (reproducible)
The
swig<os>-<arch>-4.4.1.ziparchives are repackaged from the officialswigPyPI package (https://pypi.org/project/swig/, maintained by the SWIG team, built with cibuildwheel). These wheels are the broadest-portability prebuilt SWIG available — Linux manylinux2010 (glibc 2.12) / manylinux2014, macOS 10.9 universal2 (x86_64+arm64 in one file), and Windows — far more portable than building on a dev box. Each wheel containsswig/data/bin/swig[.exe]+swig/data/share/swig/4.4.1/, i.e. ITK's exact layout, so repackaging is just extract-and-rezip (platform-independent — no cross-compiling):The resulting archives were uploaded to data.kitware.com and are fetched by SHA512:
macosx_10_9_universal217c4637d…1ce3cef9manylinux2010_x86_646447a7b9…d88ca11manylinux2014_aarch6444a6d174…c8902d24win_amd64700bd4de…e338f3892itk_assert_swig_version()runsswig -versionon the downloaded binary at configure time and fails if it is not ≥swig_version_min, so a wrong/corrupt upload is caught immediately. For a future SWIG bump, rerun the recipe with the new version, re-upload, and updateITK_SWIG_VERSION+ the per-platform SHA512s.Validation
Builds and imports on Python 3.11.15 and 3.13.9 (same abi3 build); the
std::vector/SwigPyIteratorpath and 10/10 scoped Python ctests pass. The vendored FetchContent download from data.kitware.com was verified at configure time to fetch 4.4.1, pass the assertion, and build_ITKCommonPython.abi3.socleanly.Download mirrors
data.kitware.com(keyed by SHA512) is the primary;dweb.link,ipfs.io, andgateway.pinata.cloudserve the same bytes by content id as IPFS fallbacks, matching ITK's ExternalData gateway set.URL_HASH SHA512validates whichever mirror responds. The content ids are the reproducibleipfs-car/IPIP-0499 CIDs produced by the ExternalData upload pipeline:bafybeifxjnbydus4eq46bocwb2hcj5ufpbj4etocia5ims426gfiw7krfibafybeiep2wbecrcii7xzfe2cekhfco6mlxqym4jhfdl6xi3p4aieblgz6mbafybeifaqaus3yzp5oujxupxk422hfmcg2idf3oyvdtsppzq7ymn64nvzebafybeidllsbllkqwoby6r5w4ueqzky2o7r6qkjbh45q57mczyh2fwfwd3qThe archives are pinned to IPFS and mirrored into ITKTestingData via the ExternalData upload pipeline.