* chore: faster mypy
This makes mypy around 26% faster from a cold cache.
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
* chore: enable more mypy error codes
Turn on possibly-undefined, exhaustive-match, and other strict flags, and
fix what they report. Two real bugs: pyodide never set `repaired_wheel`
when it reused a compatible wheel, so the test step failed with a
NameError; the OCI shell read loop spun forever if the shell exited.
Assisted-by: ClaudeCode:claude-opus-5
* test: carry default OCI runtime into podman vfs test config
Podman ignores its usual config files when CONTAINERS_CONF is set, so it
falls back to the first runtime found on PATH. On current GitHub Ubuntu
runner images that is crun 1.14.1, which cannot parse the OCI spec v1.2.x
config that podman 5.8.4 generates ("crun: unknown version specified").
Query the default runtime path and set it in the generated config.
Assisted-by: ClaudeCode:claude-fable-5
* fix: annotate vfs config dict so mypy passes on Linux
mypy on macOS marks the rest of the function unreachable after the
darwin pytest.skip, so the strict index error only appears on Linux.
Assisted-by: ClaudeCode:claude-fable-5
* chore: minor cleanup of variable name
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
* test: cover container shell exiting during call
Assisted-by: ClaudeCode:claude-opus-5
---------
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
* feat: add SHA256 verification for direct downloads
Store SHA256 hashes when running update scripts and verify them
when downloading files at build time. This improves security by
detecting unexpected changes to downloaded artifacts.
Platforms covered: macOS (CPython, PyPy, GraalPy), iOS, Android,
virtualenv, and python-build-standalone. Windows (nuget) and
Linux (Docker) are excluded.
SHA256 sources per platform:
- macOS/iOS/Android CPython (python.org): sha256_sum from API
- GraalPy: .sha256 sidecar assets from GitHub releases
- python-build-standalone: SHA256SUMS file in release
- PyPy, BeeWare iOS, Maven (Chaquopy): stream-download and compute
Changes:
- cibuildwheel/util/file.py: add sha256 param to download()
- cibuildwheel/platforms/{macos,ios,android}.py: add sha256 to
PythonConfiguration and pass to download()
- cibuildwheel/venv.py: read sha256 from toml and pass to download()
- cibuildwheel/util/python_build_standalone.py: add sha256 to
PythonBuildStandaloneAsset and pass to download()
- cibuildwheel/resources/build-platforms.toml: add sha256 fields
- cibuildwheel/resources/virtualenv.toml: add sha256 field
- cibuildwheel/resources/python-build-standalone-releases.json: add sha256
- bin/update_pythons.py: compute/store sha256 per source strategy
- bin/update_virtualenv.py: compute sha256 by streaming download
- bin/update_python_build_standalone.py: parse SHA256SUMS file
Closes#908
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: copilot-cli:claude-sonnet-4.6
* fix: populate sha256 in resource files and fix Windows PythonConfiguration
- Add sha256 field to Windows PythonConfiguration (PyPy/GraalPy have
direct download URLs on Windows too)
- Pass sha256 to install_pypy() and install_graalpy() in windows.py
- Fix update_pythons.py: handle empty sha256 from CPython API (older
versions) by streaming download to compute it; fix condition to
check 'not sha256' rather than 'not in dict'
- Fix update_virtualenv.py: compute sha256 even when version unchanged
but sha256 is empty (first-time population)
- Fix update_python_build_standalone.py: resolve file path relative to
the script itself (not the installed package) so writes go to source
checkout, not the uv cache
- Populate actual sha256 values by running all three update scripts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: copilot-cli:claude-sonnet-4.6
* fix: also include pyodide
Assisted-by: CopilotCLI:gpt-5.3-codex
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
* fix: PR review comments for cache verification and docs wording
Co-authored-by: henryiii <4616906+henryiii@users.noreply.github.com>
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
* fix: require sha256 for download configs
Require sha256 for URL-backed Python and virtualenv download configs. Update the GraalPy updater to refresh macOS x86_64 entries by selecting the latest release that still has a matching asset, and fill the two missing GraalPy checksums in build-platforms.toml.
Assisted-by: CopilotCLI:gpt-5.4
* ci: remove unit test for bin item
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
* refactor: combine sha256 unit tests into test_sha256.py
Merge pyodide_test.py and python_build_standalone_test.py into a
single unit_test/test_sha256.py since both test sha256-related
behaviour.
Assisted-by: opencode:glm-5
---------
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: henryiii <4616906+henryiii@users.noreply.github.com>
* feat: add CIBUILDWHEEL_BUILD_IDENTIFIER environment variable
Set `CIBUILDWHEEL_BUILD_IDENTIFIER` to the current build identifier
(e.g. `cp311-manylinux_x86_64`) in the environment for all per-build
steps: `before_build`, the build itself, `repair_command`,
`before_test`, and `test_command`.
This allows scripts and commands to inspect which build is currently
running, which is useful for e.g. writing per-build output files:
CIBW_TEST_COMMAND='pytest --junit-xml=results-$CIBUILDWHEEL_BUILD_IDENTIFIER.xml'
The variable is set after the user's environment overrides are applied
and is only available for per-build steps (not `before_all`, where no
single identifier applies). All six platforms are covered: linux, macOS,
Windows, pyodide, Android, and iOS.
Closes#944, closes#2750
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: OpenCode:claude-sonnet-4.6
* fix: address review comment moving this for Android
Assisted-by: OpenCode:glm-5.1
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
---------
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* WIP - initial punt at audit command
* Add `abi3audit` as a dependency
* Add helper functions to check stable ABI wheels
* Run `abi3audit` for macOS and Windows wheels
* Copy out of container for repairing?
* Add some notes that `cibuildwheel` runs `abi3audit`
* Add basic unit tests
* Add a basic C extension with `Py_LIMITED_API`
* Add a test project that violates Stable ABI
* Fix linux test
* Skip abi3 wheel tests for Pyodide
* Patch the correct subprocess module
* wrap cleanup of abi3audit dir
* Write the docs for the new options
* Move to above testing in docs
* Implement audit-requires and audit-command
* Some cleanups after self-review
* Add default value
* fix type errors
* the key is `audit-command`, not `audit`
* Add a variety of tests for audit requires options
* Add `test_audit_requires` similar to `test_test_requires`
* Add some configurability-related audit tests
* Fix parsing error with options docs leaving out commands
* Better way to extract version (maybe helps Pyodide?)
* Fix a case of unbound `use_uv`
* Standardise: rename to `abi3_wheel`
* Fix audit command run message
* Simplify custom audit command a bit
* Remove unnecessary skip for Pyodide
* Pyodide should have no default audit command
* More accurate skip messages for Pyodide skips
* Wheels are audited after they are repaired
* Regenerate constraints to include `abi3audit`
* Fix typos
* Some attempts for Windows fixes
* Check `pyvenv.cfg` instead of directory existence
* Add validation for lack of wheel placeholders
* Try yet another Windows `uv` fix
* Regenerate diagram and re-trigger Azure CI
* Add missing `import sys` for abi3 C extension tests
* Remove audit-command at the global level
* Clarify `abi3audit` pinning a little bit
* Regen constraints
* Discard changes to cibuildwheel/resources/constraints-pyodide312.txt
* Discard changes to cibuildwheel/resources/constraints-pyodide313.txt
* try opt-in uv again
* fix issue on windows on Python 3.13 related to nested venvs
On win / python 3.13, virtualenv creates a venv where the 'home'
points back to the venv that sys.executable was running in, rather
than the root install. that seemingly leads to problems with package
resolution, where pip.exe couldn't find the pip python package.
this appears to fix it!
* Update constraints
* chore: revert python-discovery bump
Assisted-by: OpenCode:glm-5.1
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
* fix: restore workaround for graalpy
Assisted-by: OpenCode:glm-5.1
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
---------
Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
Co-authored-by: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Co-authored-by: Henry Schreiner <henryfs@princeton.edu>
* Make the {project} placeholder available to repair-wheel-command
* Add separate test for {project} placeholder in repair-wheel-command
* Make the {project} placeholder available to repair-wheel-command
* reduce duplicated work in tests
* Use a valid wheel filename for the post-repair name
---------
Co-authored-by: Joe Rickerby <joerick@mac.com>
* Don't constrain build-system.requires with dependency-versions
* Remove setting of VIRTUALENV_PIP (it doesn't appear to have any effect)
* Alter tests to assert the versions in before_build, not setup.py
* Skip the util-test on linux
---------
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
* Add Android to resource files
* Add Android to miscellaneous places
* Add Android documentation
* Docs cleanups
* Add Android platform module; implement top-level structure and target Python installation
* Implement setup_env and build_wheel
* lru-dict build working
* Alter prefix in sysconfigdata file; fix various issues with FLAGS variables
* Implement Android testing
* Add type annotations to _cross_venv
* Revert Python 3.8 to pip 25.0.1
* Make test-sources required on Android
* Add Android integration tests
* Test cleanups
* Add test of all available Python versions
* Update test-sources and test-command behavior to match iOS
* Documentation cleanups
* Replace Builder class with a set of global functions
* Rename "env" to "build_env"
* Remove Chaquopy repository from default pip command line
* Move native_platform to platforms module
* Fix parse_config_settings
Co-authored-by: Joe Rickerby <joerick@mac.com>
* Add unit tests for parse_config_settings and arch_synonym
* Make `shell_prepared` arguments keyword-only, and add tests for the commands that use it
* Replace `importlib.util.spec_from_file_location` with `runpy.run_path`
* Use python-build-standalone
* Update Android Python
* Enable KVM in Linux CI
* Move KVM code to test_android.py
* Use Java 17 on Azure
* Install emulator if necessary before running -accel-check
* Free up additional disk space on Linux runners
* Add sudo
* Skip emulator tests on CI platforms that don't support it
* Download Android Python from Maven Central
* Free up more disk space on Linux runners
* fix: minor fixups
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* Set sysconfig._BASE_PREFIX to support sysconfig.get_path("include")
* Get ANDROID_API_LEVEL from the build environment, not cibuildwheel's own environment
* Correct relative path of test-sources
* Pass a CMake toolchain file to the build
* Add "repair" step which adds libc++ to the wheel when necessary
* Add missing needs_emulator decorator
* Provide useful error message if ANDROID_HOME is not set
* Remove use of HOST environment variable
* Update to Python 3.15.5
* Fix PyLint warnings, clarify comment
* Group common arguments into a dataclass
* Handle environment variables containing newlines
* Discourage the use of `pytest` test commands without `python -m`
* Use single quotes in user-visible messages
* Improve testing documentation
* Pass wheel filename to `log.build_end`
* In GitHub Actions example, skip Android tests on macOS
* Correct relative paths in `patchelf --set-rpath`
* Clarify `test-sources` docs
* Update to Python 3.13.5+20250722.214220
---------
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
* chore: add summary to Action
* refactor: new summary table
* fix: fixup tests and formatting
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* fix: pyodide missing some logging
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* fix: nicer printout, nicer in-place summary
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* fix: use summary for everything
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* fix: support only one output wheel from repair
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* Add new Github summary format
* Remove a couple of humanize uses
* fix: filter ANSI codes in summary
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* fix: add sha256
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* fix: nicer wheel/wheels depending on how many are present
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
---------
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
* Revert to running tests from from a temp dir when test-sources is unset
* Fix placeholders error message, add test for it
* Add back {project} placeholders to CIBW_TEST_COMMAND in tests & docs
* Update test/test_before_test.py
---------
Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
* Fix a typo: pyoodide ➡️ pyodide
* Add `pyodide_build_version` attribute
* Add version to xbuildenv log step
* Add version to Emscripten log step
* Use `pyodide-build`'s version for updating constraints
* Bump Pyodide constraints by updating `pyodide-build`
* Add a schema for `pyodide-version`
* Update Pyodide constraints
* Bump `pyodide-build` to new 0.29.0
* Test out another Pyodide identifier
* Update outdated Pyodide constraints
* Add Pyodide version to temp directory name
* Remove Pyodide 0.26.1 from build configurations
* Retrieve + validate + install specific xbuildenvs
* Test wheel builds with Pyodide 0.26.2
* Add correct Pyodide version to identifier temp dir
* Don't pre-call Pyodide xbuildenv search
* Fetch just the stable Pyodide versions
* Refactor search + validation + install into one step
* Move all of it under a lock
* Reorder xbuildenv installation
* Add env and cwd to xbuildenv search call
* Temporarily lower to 0.26.2 target
* Separate out search, validate, install; again
* Run xbuildenv search in `CIBW_CACHE_PATH`
* Remove prior `PYODIDE_ROOT` env vars, copy envs
* Validate doesn't need to depend on searching
* Add file lock when searching xbuildenvs
* Test the original version: 0.26.1
* Update Pyodide constraints
* Update constraints for `pyodide-build` 0.29.0 again
* Bump Pyodide from version 0.26.1 ➡️ version 0.26.4
* Add note on compatibility for macOS + other archs
* Note Pyodide version for Pyodide identifier
* Docs about `CIBW_PYODIDE_VERSION`
* Don't fetch just the stable versions
* Discard a variable that's not used later
* Rename `search_xbuildenv` ➡️ `get_xbuildenv_versions`
* `validate_xbuildenv` ➡️ `validate_xbuildenv_version`
* Replace ordered comment, add newline
* Replace sentence on macOS support
Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>
* Capitalise: "pyodide" ➡️ "Pyodide"
Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>
* "work" ➡️ "may succeed"
Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>
* Add another job to test a custom Pyodide version
* Handle "v"-prefixed + non-prefixed versions
* Convert to a proper toml-able option, and remove some hardcoded versions
This removes the enscripten and pyodide-build version specs from
pyproject.toml - pyodide-build is spec'd in the constraints file, and
the emscripten version can be read from the pyodide-build output.
* Add a schema entry
* Add docs for CIBW_PYODIDE_VERSION
* Rephrase
* Add tests for pyodide-version
* Apply suggestions from code review
* Add python_build_standalone util
* Hook up to python-build-standalone, removing dependency on host python
* Remove python hard-code in action.yml
* Add log step
* Add workaround for https://github.com/pyodide/pyodide-build/issues/143
* Add emscripten pytest test
* Remove unneeded checks
* Fix a pytest invoke for emscripten
* Generate pyodide-build constraints from the pinned pyodide version
* Remove pyodide python-build-standalone workaround
* Fixup paths from newer version of pyodide-build
* Fix/skip some failing tests
* Use `python -m pytest` on pyodide, even on Linux
* Docs fixes
* Don't call the github API at runtime, cache the release assets instead
* Ignore pylint false positive
* Add version auto-updating for pyodide
* Add support for pyodide 3.13.
* Fix tests for multiple pyodide wheels
* Remove workaround for unreleased pyodide-build
* Rename to "test_pyodide"
* Fix pathname confusion
* Remove extra github actions job
* Fix expectation for test_abi_none
* Fix the custom_repair_wheel test to actually have clashing names
* Fix pinned version test
* Document test-command limitation
* Remove pyodide 0.28.0a1 for now
* Update constraints files
* Docs/test fixes post removing pyodide cp313
* Fix ABI test expectation
* Docs improvements
* Improve some comments
* Remove logic duplication
* remove pyodide special casing
* Refactor constraints code to use a utility script, circumventing import issues
* chore: nicer nox env
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* fix: typo in variable name found by copilot
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
* Apply suggestions from code review
* Some more Pyodide version updates in the docs section
* We haven't released Pyodide v0.27.6 yet
* Back to the Github URL for cross-build-environments
* `pyodide-build`, not `emsdk` for Windows skips
Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>
* Move to a separate `_json_request` function
Co-Authored-By: Hood Chatham <roberthoodchatham@gmail.com>
* Rename "retries" ➡️ "retry_count"
* Add some type hints
* Copy env vars before `UV_CUSTOM_COMPILE_COMMAND`
* Use `HTTPError.headers.get` instead
* Remove extra end quote
* Change download tests URL to `https://badssl.com/`
Co-Authored-By: Joe Rickerby <1244307+joerick@users.noreply.github.com>
* Download size changes, too
* Use jsdelivr for Github asset mirroring
* Bump to Pyodide v0.27.6
* Fix unit tests
* Move to pyodide v0.27.6 again
* Bump to pyodide-build 0.30.4
* Use new URL for cross-build environments metadata
Co-authored-by: Joe Rickerby <joerick@mac.com>
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---------
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Hood Chatham <roberthoodchatham@gmail.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Joe Rickerby <1244307+joerick@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Add TEST_ENVIRONMENT option and set PYTHONSAFEPATH=1 in the test env
Closes https://github.com/pypa/cibuildwheel/issues/2358
* Add toml docs examples
* Add TOML examples
* Use double-quotes for windows
* feat: stricter selector parsing, refactor to `platforms` module
- Use a different method to build nothing
- Make the check aware of enable groups
* optimise unit tests - a specific platform module API for all configs
Unit test time: 26.2s -> 13.1s
* Remove unnecessary get_platform_module function