From a2d2a5fa061b672511b8eb1ca7889ee6afac7183 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Sat, 11 Apr 2026 05:47:15 -0500 Subject: [PATCH] COMP: Bootstrap pip via ensurepip on Windows wheel build to fix Python 3.10+ scikit-ci-addons' install-python.ps1 downloads get-pip.py from a pinned GitHub gist (jcfr commit 8478d43e) rather than the canonical bootstrap.pypa.io URL, and installs a pip old enough to vendor an html5lib that still uses `from collections import Mapping`. That import was removed in Python 3.10, so the very first invocation of `python -m pip install pip --upgrade` (the bootstrap step in `build_wheels`) dies with: File ".../pip.zip/pip/_vendor/html5lib/_trie/_base.py", line 3 ImportError: cannot import name 'Mapping' from 'collections' The failure is consistent on Python 3.10 and 3.11 across all Windows matrix jobs (build-windows-python-packages (10) and (11)). Fix it by running `python -m ensurepip --upgrade --default-pip` BEFORE the existing `pip install pip --upgrade`. ensurepip uses the pip wheel that CPython itself bundled at release time (>= 21.x for Python 3.10), which has a working html5lib >= 1.1, and the subsequent self-upgrade then proceeds normally. The PowerShell entry point (windows-download-cache-and-build-module-wheels.ps1) still IEXes the upstream install-python.ps1 unchanged - the chicken-and-egg fix is purely Python-side, so no interaction with scikit-ci-addons is required. Companion `windows_build_wheels.py` is unchanged because its pip operations go through a virtualenv created by `virtualenv.exe`, and modern virtualenv ships its own bundled pip wheels rather than copying the (broken) system pip. Surfaced by KitwareMedical/ITKUltrasound#246, which is the first remote module PR to actually exercise the python wheel build matrix on Python 3.10+ after a related CI fix made the workflow start running again. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/windows_build_module_wheels.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/windows_build_module_wheels.py b/scripts/windows_build_module_wheels.py index 0a8f54f3..858f1bac 100755 --- a/scripts/windows_build_module_wheels.py +++ b/scripts/windows_build_module_wheels.py @@ -52,6 +52,22 @@ def build_wheels(py_envs=DEFAULT_PY_ENVS, cleanup=True, cmake_options=[]): with push_env(PATH="%s%s%s" % (path, os.pathsep, os.environ["PATH"])): # Install dependencies + # + # Bootstrap pip from CPython's bundled ensurepip wheel BEFORE + # invoking the system pip, to sidestep a chicken-and-egg failure + # on Python 3.10+ runners. scikit-ci-addons' install-python.ps1 + # downloads get-pip.py from a pinned GitHub gist (jcfr commit + # 8478d43e), which installs a pip old enough to vendor an + # html5lib that still does `from collections import Mapping` + # (removed in Python 3.10). Loading that pip to upgrade itself + # raises ImportError before any package operation can run. + # CPython's ensurepip module installs the pip wheel that ships + # with the interpreter (>= 21.x for Python 3.10), which has a + # working html5lib >= 1.1; the subsequent `pip install pip + # --upgrade` then succeeds normally. + check_call( + [python_executable, "-m", "ensurepip", "--upgrade", "--default-pip"] + ) check_call([python_executable, "-m", "pip", "install", "pip", "--upgrade"]) requirements_file = os.path.join(ROOT_DIR, "requirements-dev.txt") if os.path.exists(requirements_file):