Compare commits

...
62 Commits
Author SHA1 Message Date
Joe Rickerby 619e1dc989 WIP - initial punt at audit command 2026-02-04 09:26:35 +00:00
Henry Schreiner e8646fb903 fix: nicer fail message when --only is wrong (#2722)
* fix: nicer fail message when --only is wrong

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

* Update cibuildwheel/__main__.py

---------

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
2026-01-30 16:24:57 +00:00
Matthieu Darbois 6f8121fa47 ci: test action with uv extra (#2712)
* ci: test action with `uv` extra

* fix: uv extra for Android on Linux
2026-01-28 10:16:54 -05:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 7989c25bcd [pre-commit.ci] pre-commit autoupdate (#2720)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.13 → v0.14.14](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.13...v0.14.14)
- [github.com/python-jsonschema/check-jsonschema: 0.36.0 → 0.36.1](https://github.com/python-jsonschema/check-jsonschema/compare/0.36.0...0.36.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-27 09:22:47 +00:00
Agriya KhetarpalandGyeongjae Choi 9a15d0851e Bump to Pyodide v0.29.2 (#2719)
* Bump to Pyodide v0.29.2

* Bump the Pyodide constraints too

* Include new auditwheel-emscripten and pyodide-build release

* Bump pyodide-build in test to a newer version

Co-Authored-By: Gyeongjae Choi <def6488@gmail.com>

---------

Co-authored-by: Gyeongjae Choi <def6488@gmail.com>
2026-01-27 09:22:16 +00:00
riri dc4fc9c3fe feat(android): add Rust cross-compilation setup for Android environment (#2650) 2026-01-25 14:13:03 +00:00
Joe Rickerby dcd9f40825 Update Python version range to 3.14 in Github Action (#2716) 2026-01-25 09:14:13 +01:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 90da3e21e2 [pre-commit.ci] pre-commit autoupdate (#2714)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.10 → v0.14.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.10...v0.14.13)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-19 19:10:45 +00:00
Joe Rickerby f3ba8a83a5 Merge branch '3.3.x' 2026-01-05 20:04:05 +00:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> 3cefb9d38c [Bot] Update dependencies (#2709)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2026-01-05 19:59:47 +00:00
Joe Rickerby 298ed2fb2c Bump version: v3.3.1 2026-01-05 19:57:01 +00:00
Joe Rickerbyandmayeut f0ff944318 [3.3.x] Update dependencies (#2708)
* Update deps

nox --force-color -s update_constraints && nox --force-color -s update_pins

* update deps

nox -s update_pins

---------

Co-authored-by: mayeut <mayeut@users.noreply.github.com>
2026-01-05 19:51:01 +00:00
Xeonacid aae69a8e1d break: drop unused riscv64 enable option (#2525) 2026-01-04 20:20:29 +01:00
Matthieu Darbois 24bade1d15 break: remove Travis CI support (#2682)
Stop testing on Travis CI.
References to Travis CI are removed from docs.
Travis CI specifics are kept as-is in cibuildwheel itself (mostly logging stuff).
2025-12-29 17:03:03 -05:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> a68c3b27fb [Bot] Update dependencies (#2704)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-12-29 17:01:45 -05:00
Henry Schreiner 99059b7442 chore: use prek in noxfile/ci (#2681) 2025-12-23 18:51:19 -05:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> d0e070e278 [Bot] Update dependencies (#2697)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-12-23 06:44:34 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> bb2f93202e chore(deps): bump actions/attest-build-provenance from 3.0.0 to 3.1.0 in the actions group (#2698)
chore(deps): bump actions/attest-build-provenance in the actions group

Bumps the actions group with 1 update: [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance).


Updates `actions/attest-build-provenance` from 3.0.0 to 3.1.0
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](https://github.com/actions/attest-build-provenance/compare/977bb373ede98d70efdf65b84cb5f73e068dcc2a...00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8)

---
updated-dependencies:
- dependency-name: actions/attest-build-provenance
  dependency-version: 3.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-23 06:44:14 +01:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 11597ed249 [pre-commit.ci] pre-commit autoupdate (#2699)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.9 → v0.14.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.9...v0.14.10)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-12-23 06:43:57 +01:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> 90422f1824 [Bot] Update dependencies (#2692)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-12-15 23:38:01 -05:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 986d80b3d7 [pre-commit.ci] pre-commit autoupdate (#2694)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.8 → v0.14.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.8...v0.14.9)
- [github.com/pre-commit/mirrors-mypy: v1.19.0 → v1.19.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.19.0...v1.19.1)
- [github.com/python-jsonschema/check-jsonschema: 0.35.0 → 0.36.0](https://github.com/python-jsonschema/check-jsonschema/compare/0.35.0...0.36.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-12-15 23:37:41 -05:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 5acadc2dfc chore(deps): bump the actions group with 3 updates (#2693)
Bumps the actions group with 3 updates: [actions/download-artifact](https://github.com/actions/download-artifact), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request).


Updates `actions/download-artifact` from 6 to 7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

Updates `actions/upload-artifact` from 5 to 6
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

Updates `peter-evans/create-pull-request` from 7 to 8
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: peter-evans/create-pull-request
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 20:31:18 +01:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> 6878a1baeb [Bot] Update dependencies (#2688)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-12-09 00:11:05 -05:00
Malcolm Smith 7288bbed76 Update Android Python versions (#2687)
* Update Android Python versions

* Restore "free up disk space" step for non-Android jobs only
2025-12-09 00:10:36 -05:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 0cb04c05db [pre-commit.ci] pre-commit autoupdate (#2689)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.7 → v0.14.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.7...v0.14.8)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-12-09 00:09:16 -05:00
Marco Sulla 3c2d5961de Added more infos about muslinux support of uv in options.md (#2675)
uv doesn't support also ppc64le and riscv64 for muslinux
2025-12-06 12:15:11 +01:00
pre-commit-ci[bot]pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>Henry Schreiner
6c7e3ee860 [pre-commit.ci] pre-commit autoupdate (#2680)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.6 → v0.14.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.6...v0.14.7)
- [github.com/pre-commit/mirrors-mypy: v1.18.2 → v1.19.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.18.2...v1.19.0)

* chore: update for newer mypy

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

---------

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Henry Schreiner <henryfs@princeton.edu>
2025-12-02 18:06:04 -05:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> df2ce29908 [Bot] Update dependencies (#2677)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-12-02 12:22:25 -05:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 74a3c45b74 [pre-commit.ci] pre-commit autoupdate (#2674)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.5 → v0.14.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.5...v0.14.6)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-11-28 15:52:36 +00:00
Eric Larson 9f991f2330 DOC: Document location in error message (#2669) 2025-11-28 15:48:44 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ea4b3eb6a5 chore(deps): bump actions/checkout from 5 to 6 in the actions group (#2672)
Bumps the actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 5 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 11:28:39 -05:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> 6bc6700ab3 [Bot] Update dependencies (#2671)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-11-24 10:56:53 -05:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> c314f9f07b [Bot] Update dependencies (#2665)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-11-18 09:48:55 -05:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> dd81fa002c chore(deps): bump wntrblm/nox from 2025.10.16 to 2025.11.12 in the actions group (#2666)
chore(deps): bump wntrblm/nox in the actions group

Bumps the actions group with 1 update: [wntrblm/nox](https://github.com/wntrblm/nox).


Updates `wntrblm/nox` from 2025.10.16 to 2025.11.12
- [Release notes](https://github.com/wntrblm/nox/releases)
- [Changelog](https://github.com/wntrblm/nox/blob/main/CHANGELOG.md)
- [Commits](https://github.com/wntrblm/nox/compare/2025.10.16...2025.11.12)

---
updated-dependencies:
- dependency-name: wntrblm/nox
  dependency-version: 2025.11.12
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-18 09:48:43 -05:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 3658bf2f84 [pre-commit.ci] pre-commit autoupdate (#2667)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.4 → v0.14.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.4...v0.14.5)
- [github.com/python-jsonschema/check-jsonschema: 0.34.1 → 0.35.0](https://github.com/python-jsonschema/check-jsonschema/compare/0.34.1...0.35.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-11-17 17:51:47 -05:00
Joe Rickerby 63fd63b352 Bump version: v3.3.0 2025-11-12 19:27:31 +00:00
Henry Schreiner f4fe311fc9 fix: support Docker 29 (#2660)
* fix: support Docker 29

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* refactor: closer to actual case, lambda

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

---------

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
2025-11-12 14:15:10 -05:00
Alexander CondelloandJoe Rickerby f6c810852d feat: make the {project} placeholder available to repair-wheel-command (#2589)
* 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>
2025-11-10 20:59:32 -05:00
Henry Schreiner ccbae30b53 feat: support uv with Android (#2587) 2025-11-10 19:43:52 -05:00
Henry Schreiner 1337e50f74 chore: pytest log_level is better than log_cli_level (#2657)
Committed via https://github.com/asottile/all-repos
2025-11-10 22:47:32 +01:00
Matthieu Darbois 720f8e266f feat: add manylinux_2_35 (#2656)
pypa/manylinux now has a manylinux_2_35_armv7l image allowing for better C++20 support.
piwheels is still building for Debian Bullseye so keeping manylinux_2_31 as the default image.
2025-11-10 15:54:53 -05:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 4c7f3696b1 [pre-commit.ci] pre-commit autoupdate (#2658)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.3 → v0.14.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.3...v0.14.4)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-11-10 15:53:57 -05:00
Henry Schreiner e1baa60eb0 chore: enable more Ruff checks (#2654)
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
2025-11-07 18:48:20 -05:00
Joe RickerbyandHenry Schreiner 1f2f8b28d5 fix: don't constrain build-system.requires with our dependency-versions (#2583)
* 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>
2025-11-06 17:03:00 -05:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 8c5b02f42c [pre-commit.ci] pre-commit autoupdate (#2648)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.2 → v0.14.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.2...v0.14.3)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-11-06 16:49:12 -05:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> 997a6e1931 [Bot] Update dependencies (#2646)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-11-06 14:43:00 -05:00
4fe7630d9c feat: add configuration option for test executor arguments (#2636)
* Add test-execution-args option.

* Add usage of test-execution-args.

* Add CI configuration to use test-execution-args.

* Document the test-execution-args setting.

* Simplify code using or syntax instead of inline if.

Co-authored-by: Malcolm Smith <smith@chaquo.com>

* Clarified some Android-specific terminology, and added details about the default args to the test runner.

* Switch to a dict-based test-execution configuration

* Add tests for test-execution parsing.

* Add all the files before pushing...

* Add note about default Android version for testbed.

* Improve description of test-execution setting.

Co-authored-by: Joe Rickerby <joerick@mac.com>

* Switch to using test-runtime.

---------

Co-authored-by: Malcolm Smith <smith@chaquo.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
2025-11-05 16:19:41 -05:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> c53e541c2d [Bot] Update dependencies (#2642)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-10-29 12:44:46 +00:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 58d113ad2b [pre-commit.ci] pre-commit autoupdate (#2644)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.1 → v0.14.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.1...v0.14.2)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-29 12:44:28 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> de0262ea87 chore(deps): bump the actions group with 2 updates (#2643)
Bumps the actions group with 2 updates: [actions/download-artifact](https://github.com/actions/download-artifact) and [actions/upload-artifact](https://github.com/actions/upload-artifact).


Updates `actions/download-artifact` from 5 to 6
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

Updates `actions/upload-artifact` from 4 to 5
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 17:56:46 +00:00
cibuildwheel-bot[bot]cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>Joe Rickerby
41f3304a86 [Bot] Update dependencies (#2633)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
2025-10-26 17:02:37 +00:00
Ofek Lev a3af13a337 Allow installation of extras in GitHub action (#2630) 2025-10-26 13:29:26 +00:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 168717b5c5 [pre-commit.ci] pre-commit autoupdate (#2635)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.0 → v0.14.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.0...v0.14.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-25 16:25:41 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> a592c06add chore(deps): bump wntrblm/nox from 2025.05.01 to 2025.10.16 in the actions group (#2634)
chore(deps): bump wntrblm/nox in the actions group

Bumps the actions group with 1 update: [wntrblm/nox](https://github.com/wntrblm/nox).


Updates `wntrblm/nox` from 2025.05.01 to 2025.10.16
- [Release notes](https://github.com/wntrblm/nox/releases)
- [Changelog](https://github.com/wntrblm/nox/blob/main/CHANGELOG.md)
- [Commits](https://github.com/wntrblm/nox/compare/2025.05.01...2025.10.16)

---
updated-dependencies:
- dependency-name: wntrblm/nox
  dependency-version: 2025.10.16
  dependency-type: direct:production
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-25 16:25:00 +01:00
Henry Schreiner bbe00a21e3 chore: fix warning on pylint 4 (#2624)
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
2025-10-25 15:35:48 +01:00
Malcolm Smithandpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> 362020b1c7 Update Android test-command handling (#2590)
* Update Android test-command handling

* Update to Python 3.13.8

* Update documentation and tests

* Deal with `sysconfig.get_config_var("exec_prefix")` changing in Python 3.14, and add cross venv tests

* Allow test commands starting with `python3`

* test-command cleanups

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-25 15:29:52 +01:00
Joe Rickerby 8165422c41 chrome: remove dependency workaround for mkdocs-macro-plugin (#2639)
chrome: remove version pin for mkdocs-macro-plugin
2025-10-25 14:40:07 +01:00
Alex WillmerandJoe Rickerby a6acd2a2d5 docs: Note the evalution order of environment variables (#2618)
* docs: Note the evalution order of environment variables

* Remove example that doesn't reinforce good practice

Co-authored-by: Joe Rickerby <joerick@mac.com>

---------

Co-authored-by: Joe Rickerby <joerick@mac.com>
2025-10-15 15:44:15 -04:00
Michael R. Crusoe 372dd68cf6 docs: working examples: pyzmq no longer uses CircleCI (#2620)
pyzmq no longer uses CircleCI

https://github.com/zeromq/pyzmq/commit/014bc3eefc8bb1f883bacc9392966022de62be30
2025-10-15 15:43:39 -04:00
cibuildwheel-bot[bot]andcibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com> cb5496943f [Bot] Update dependencies (#2621)
Update dependencies

Co-authored-by: cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>
2025-10-15 15:42:54 -04:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ad74d64a16 chore(deps): bump astral-sh/setup-uv from 6 to 7 in the actions group (#2622)
Bumps the actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 6 to 7
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-15 15:42:31 -04:00
pre-commit-ci[bot]andpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> be214efadb [pre-commit.ci] pre-commit autoupdate (#2623)
updates:
- [github.com/python-jsonschema/check-jsonschema: 0.34.0 → 0.34.1](https://github.com/python-jsonschema/check-jsonschema/compare/0.34.0...0.34.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-15 15:41:27 -04:00
88 changed files with 1882 additions and 1175 deletions
+3 -3
View File
@@ -11,7 +11,7 @@ jobs:
dist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: hynek/build-and-inspect-python-package@v2
@@ -27,13 +27,13 @@ jobs:
attestations: write
steps:
- uses: actions/download-artifact@v5
- uses: actions/download-artifact@v7
with:
name: Packages
path: dist
- name: Generate artifact attestation for sdist and wheel
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0
with:
subject-path: "dist/cibuildwheel-*"
+94 -29
View File
@@ -37,18 +37,38 @@ jobs:
name: Linters (mypy, ruff, etc.)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
id: python
with:
python-version: "3.x"
- uses: pre-commit/action@v3.0.1
- uses: j178/prek-action@v1
- name: PyLint checks
run: pipx run --python "${{ steps.python.outputs.python-path }}" nox -s pylint -- --output-format=github
sample:
name: Generate a sample project
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
name: Install Python
with:
python-version: "3.x"
- uses: astral-sh/setup-uv@v7
- name: Install dependencies
run: uv sync --no-dev --group test
- name: Generate a sample project
run: uv run --no-sync -m test.test_projects test.test_0_basic.basic_project sample_proj
- uses: actions/upload-artifact@v6
with:
name: sample_proj
path: sample_proj
test:
name: Test on ${{ matrix.os }} (${{ matrix.python_version }}) ${{ matrix.test_select }}
needs: lint
needs: sample
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@@ -79,31 +99,34 @@ jobs:
- os: macos-15
python_version: '3.13'
test_select: ios
# Exercise iOS on a non-default simulator.
test_runtime: 'args: --simulator "iPhone 16e,OS=18.5"'
- os: macos-15-intel
python_version: '3.13'
test_select: android
# Exercise Android on a non-default simulator
test_runtime: 'args: --managed minVersion'
- os: macos-15
python_version: '3.13'
test_select: android
timeout-minutes: 180
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
name: Install Python ${{ matrix.python_version }}
with:
python-version: ${{ matrix.python_version }}
allow-prereleases: true
- uses: astral-sh/setup-uv@v6
- uses: astral-sh/setup-uv@v7
- name: Free up disk space
if: runner.os == 'Linux'
if: runner.os == 'Linux' && matrix.test_select != 'android'
run: |
docker system prune -a -f
sudo rm -rf $ANDROID_HOME/ndk/{26,28}.* /opt/hostedtoolcache/CodeQL \
sudo rm -rf $ANDROID_HOME/ndk /opt/hostedtoolcache/CodeQL \
/usr/local/lib/node_modules /usr/local/share/chromium \
/usr/local/share/powershell
df -h
df -m
# for oci_container unit tests
- name: Set up QEMU
@@ -117,8 +140,7 @@ jobs:
sudo xcode-select --switch /Applications/Xcode_16.4.app
- name: Install dependencies
run: |
uv sync --no-dev --group test
run: uv sync --no-dev --group test
- uses: joerick/pr-labels-action@v1.0.9
@@ -141,9 +163,11 @@ jobs:
fi
echo "CIBW_ENABLE=${CIBW_ENABLE}" >> $GITHUB_ENV
- name: Generate a sample project
run: |
uv run --no-sync -m test.test_projects test.test_0_basic.basic_project sample_proj
- name: Download a sample project
uses: actions/download-artifact@v5
with:
name: sample_proj
path: sample_proj
- name: Run a sample build (GitHub Action)
uses: ./
@@ -154,6 +178,7 @@ jobs:
CIBW_ARCHS_MACOS: x86_64 universal2 arm64
CIBW_BUILD_FRONTEND: ${{ matrix.test_select && 'build' || 'build[uv]' }}
CIBW_PLATFORM: ${{ matrix.test_select }}
CIBW_TEST_RUNTIME: ${{ matrix.test_runtime }}
- name: Run a sample build (GitHub Action, only)
uses: ./
@@ -179,6 +204,7 @@ jobs:
uses: ./
env:
CIBW_PLATFORM: ${{ matrix.test_select }}
CIBW_TEST_RUNTIME: ${{ matrix.test_runtime }}
with:
package-dir: sample_proj
output-dir: wheelhouse_config_file
@@ -196,14 +222,15 @@ jobs:
run: |
test $(find wheelhouse_only -name '*.whl' | wc -l) -eq 1
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: wheelhouse/*.whl
- name: Test cibuildwheel
run: |
uv run --no-sync bin/run_tests.py --test-select=${{ matrix.test_select || 'native' }} ${{ (runner.os == 'Linux' && runner.arch == 'X64') && '--run-podman' || '' }}
env:
CIBW_TEST_RUNTIME: ${{ matrix.test_runtime }}
run: uv run --no-sync bin/run_tests.py --test-select=${{ matrix.test_select || 'native' }} ${{ (runner.os == 'Linux' && runner.arch == 'X64') && '--run-podman' || '' }}
emulated-archs:
name: Get qemu emulated architectures
@@ -212,11 +239,11 @@ jobs:
outputs:
archs: ${{ steps.archs.outputs.archs }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.x"
- uses: astral-sh/setup-uv@v6
- uses: astral-sh/setup-uv@v7
- name: Install dependencies
run: uv sync --no-dev --group test
- name: Get qemu emulated architectures
@@ -235,11 +262,11 @@ jobs:
matrix:
arch: ${{ fromJSON(needs.emulated-archs.outputs.archs) }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.x"
- uses: astral-sh/setup-uv@v6
- uses: astral-sh/setup-uv@v7
- name: Install dependencies
run: uv sync --no-dev --group test
@@ -251,23 +278,25 @@ jobs:
test-pyodide:
name: Test pyodide
needs: lint
needs: sample
runs-on: ubuntu-24.04
timeout-minutes: 180
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
name: Install Python 3.12
with:
python-version: '3.12'
- uses: astral-sh/setup-uv@v6
- uses: astral-sh/setup-uv@v7
- name: Install dependencies
run: uv sync --no-dev --group test
- name: Generate a sample project
run: |
uv run --no-sync -m test.test_projects test.test_0_basic.basic_project sample_proj
- name: Download a sample project
uses: actions/download-artifact@v5
with:
name: sample_proj
path: sample_proj
- name: Run a sample build (GitHub Action)
uses: ./
@@ -278,7 +307,43 @@ jobs:
CIBW_PLATFORM: pyodide
- name: Run tests with 'CIBW_PLATFORM' set to 'pyodide'
run: |
uv run --no-sync ./bin/run_tests.py
run: uv run --no-sync ./bin/run_tests.py
env:
CIBW_PLATFORM: pyodide
test-uv-extras:
name: Test uv extra on ${{ matrix.os }} ${{ matrix.test_select }}
needs: sample
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
test_select: android
- os: windows-latest
- os: windows-11-arm
- os: macos-15-intel
- os: macos-15
- os: macos-15-intel
test_select: android
- os: macos-15
test_select: android
steps:
- uses: actions/checkout@v6
- name: Download a sample project
uses: actions/download-artifact@v5
with:
name: sample_proj
path: sample_proj
- name: Run a sample build (GitHub Action)
uses: ./
with:
extras: uv
package-dir: sample_proj
output-dir: wheelhouse
env:
CIBW_ARCHS_MACOS: x86_64 universal2 arm64
CIBW_BUILD: cp314-*
CIBW_BUILD_FRONTEND: 'build[uv]'
CIBW_PLATFORM: ${{ matrix.test_select }}
+3 -3
View File
@@ -30,9 +30,9 @@ jobs:
app-id: ${{ secrets.CIBUILDWHEEL_BOT_APP_ID }}
private-key: ${{ secrets.CIBUILDWHEEL_BOT_APP_PRIVATE_KEY }}
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: wntrblm/nox@2025.05.01
- uses: wntrblm/nox@2025.11.12
- name: "Run update: dependencies"
run: nox --force-color -s update_constraints
@@ -43,7 +43,7 @@ jobs:
- name: Create Pull Request
if: github.ref == 'refs/heads/main' && github.repository == 'pypa/cibuildwheel'
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@v8
with:
commit-message: Update dependencies
title: '[Bot] Update dependencies'
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Update the ${{ env.TAG_NAME }} tag
id: update-major-minor-tag
+5 -5
View File
@@ -14,14 +14,14 @@ repos:
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.0
rev: v0.14.14
hooks:
- id: ruff-check
args: ["--fix", "--show-fixes"]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.18.2
rev: v1.19.1
hooks:
- id: mypy
name: mypy 3.11 on cibuildwheel/
@@ -49,8 +49,8 @@ repos:
- uv
- validate-pyproject
- id: mypy
name: mypy 3.13
args: ["--python-version=3.13"]
name: mypy 3.14
args: ["--python-version=3.14"]
additional_dependencies: *mypy-dependencies
- repo: https://github.com/shellcheck-py/shellcheck-py
@@ -83,7 +83,7 @@ repos:
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.34.0
rev: 0.36.1
hooks:
- id: check-dependabot
- id: check-github-actions
-79
View File
@@ -1,79 +0,0 @@
os: linux
dist: jammy
language: python
branches:
only:
- main
# only build the main branch or PR that explicitely want to test with Travis CI
if: (type = "push") OR (commit_message =~ /travis-ci/)
jobs:
include:
- name: Linux | x86_64 + i686 | Python 3.12
python: 3.12
services: docker
env:
- PYTHON=python
# a build using CIBW_ENABLE=all does not fit into Travis' time limit,
# so only the defaults are tested
- name: Linux | arm64 | Python 3.12
python: 3.12
services: docker
arch: arm64
env:
- PYTHON=python
- CIBW_ENABLE=all
- name: Linux | ppc64le | Python 3.12
python: 3.12
services: docker
arch: ppc64le
allow_failure: True
env:
- PYTHON=python
# skip test_manylinuxXXXX_only, it uses too much disk space
# c.f. https://travis-ci.community/t/running-out-of-disk-space-quota-when-using-docker-on-ppc64le/11634
- PYTEST_ADDOPTS='-k "not test_manylinuxXXXX_only"'
- CIBW_ENABLE=all
- name: Windows | x86_64 | Python 3.12
os: windows
language: shell
before_install:
# http://woshub.com/updating-trusted-root-certificates-in-windows-10
- certutil -generateSSTFromWU roots.sst
- powershell -Command 'Get-ChildItem -Path roots.sst | Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root'
- rm -f roots.sst
- choco upgrade python3 -y --version 3.12.8 --limit-output --params "/InstallDir:C:\\Python312"
env:
- PYTHON=C:\\Python312\\python
# a build using CIBW_ENABLE=all does not fit into Travis' time limit,
# so only the defaults are tested
- name: Linux | s390x | Python 3.12
python: 3.12
services: docker
arch: s390x
allow_failure: True
env:
- PYTHON=python
- CIBW_ENABLE=all
install:
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all; fi
- $PYTHON -m pip install -U pip
- $PYTHON -m pip install -e. --group test
script: |
# travis_wait disable the output while waiting
# use the same kind of tricks as in multibuild
(while true; do echo "travis_keep_alive"; sleep 300; done) &
SPINNER_PID=$!
disown
result=0
$PYTHON ./bin/run_tests.py --num-processes 2 || result=1
kill -9 ${SPINNER_PID}
test ${result} -eq 0
+5 -7
View File
@@ -1,11 +1,9 @@
This is a summary of the host Python versions and platforms covered by the different CI platforms:
| | 3.11 | 3.12 | 3.13 |
|---------|----------------------------------|---------------------------------------------|----------------|
| Linux | Azure Pipelines / GitHub Actions | CircleCI¹ / Cirrus CI / GitLab¹ / Travis CI | GitHub Actions |
| macOS | Azure Pipelines | CircleCI¹ / Cirrus CI / GitLab¹ | GitHub Actions |
| Windows | Azure Pipelines | Cirrus CI / GitLab¹ / Travis CI | GitHub Actions |
| | 3.11 | 3.12 | 3.13 | 3.14 |
|---------|----------------------------------|---------------------------------|----------------|----------------|
| Linux | Azure Pipelines / GitHub Actions | CircleCI¹ / Cirrus CI / GitLab¹ | GitHub Actions | GitHub Actions |
| macOS | Azure Pipelines | CircleCI¹ / Cirrus CI / GitLab¹ | GitHub Actions | |
| Windows | Azure Pipelines | Cirrus CI / GitLab¹ | GitHub Actions | |
> ¹ Runs a reduced set of tests to reduce CI load
Non-x86 architectures are covered on Travis CI using Python 3.12.
+30 -35
View File
@@ -4,7 +4,6 @@ cibuildwheel
[![PyPI](https://img.shields.io/pypi/v/cibuildwheel.svg)](https://pypi.python.org/pypi/cibuildwheel)
[![Documentation Status](https://readthedocs.org/projects/cibuildwheel/badge/?version=stable)](https://cibuildwheel.pypa.io/en/stable/?badge=stable)
[![Actions Status](https://github.com/pypa/cibuildwheel/workflows/Test/badge.svg)](https://github.com/pypa/cibuildwheel/actions)
[![Travis Status](https://img.shields.io/travis/com/pypa/cibuildwheel/main?logo=travis)](https://travis-ci.com/github/pypa/cibuildwheel)
[![CircleCI Status](https://img.shields.io/circleci/build/gh/pypa/cibuildwheel/main?logo=circleci)](https://circleci.com/gh/pypa/cibuildwheel)
[![Azure Status](https://dev.azure.com/joerick0429/cibuildwheel/_apis/build/status/pypa.cibuildwheel?branchName=main)](https://dev.azure.com/joerick0429/cibuildwheel/_build/latest?definitionId=4&branchName=main)
@@ -15,7 +14,7 @@ cibuildwheel
Python wheels are great. Building them across **Mac, Linux, Windows**, on **multiple versions of Python**, is not.
`cibuildwheel` is here to help. `cibuildwheel` runs on your CI server - currently it supports GitHub Actions, Azure Pipelines, Travis CI, CircleCI, and GitLab CI - and it builds and tests your wheels across all of your platforms.
`cibuildwheel` is here to help. `cibuildwheel` runs on your CI server - currently it supports GitHub Actions, Azure Pipelines, CircleCI, and GitLab CI - and it builds and tests your wheels across all of your platforms.
What does it do?
@@ -46,7 +45,7 @@ While cibuildwheel itself requires a recent Python version to run (we support th
<sup>⁵ manylinux armv7l support is experimental. As there are no RHEL based image for this architecture, it's using an Ubuntu based image instead.</sup><br>
- Builds manylinux, musllinux, macOS, and Windows wheels for CPython, PyPy, and GraalPy
- Works on GitHub Actions, Azure Pipelines, Travis CI, CircleCI, GitLab CI, and Cirrus CI
- Works on GitHub Actions, Azure Pipelines, CircleCI, GitLab CI, and Cirrus CI
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
- Runs your library's tests against the wheel-installed version of your library
@@ -59,9 +58,8 @@ Usage
| | Linux | macOS | Windows | Linux ARM | macOS ARM | Windows ARM | Android | iOS |
|-----------------|-------|-------|---------|-----------|-----------|-------------|---------|-----|
| GitHub Actions | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅⁴ | ✅³ |
| Azure Pipelines | ✅ | ✅ | ✅ | | ✅ | ✅² | ✅⁴ | ✅³ |
| Travis CI | ✅ | | ✅ | ✅ | | | ✅⁴ | |
| GitHub Actions | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅⁴ | ✅³ |
| Azure Pipelines | ✅ | ✅ | ✅ | | ✅ | ✅² | ✅⁴ | ✅³ |
| CircleCI | ✅ | ✅ | | ✅ | ✅ | | ✅⁴ | ✅³ |
| Gitlab CI | ✅ | ✅ | ✅ | ✅¹ | ✅ | | ✅⁴ | ✅³ |
| Cirrus CI | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅⁴ | |
@@ -70,7 +68,6 @@ Usage
<sup>² [Uses cross-compilation](https://cibuildwheel.pypa.io/en/stable/faq/#windows-arm64). It is not possible to test `arm64` on this CI platform.</sup><br>
<sup>³ Requires a macOS runner; runs tests on the simulator for the runner's architecture. </sup><br>
<sup>⁴ Building for Android requires the runner to be Linux x86_64, macOS ARM64 or macOS x86_64. Testing has [additional requirements](https://cibuildwheel.pypa.io/en/stable/platforms/#android).</sup><br>
<sup>⁵ The `macos-15` and `macos-latest` images are [incompatible with cibuildwheel at this time](platforms/#ios-system-requirements)</sup><br> when building iOS wheels.
<!--intro-end-->
@@ -100,7 +97,7 @@ jobs:
- uses: actions/setup-python@v5
- name: Install cibuildwheel
run: python -m pip install cibuildwheel==3.2.1
run: python -m pip install cibuildwheel==3.3.1
- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
@@ -160,12 +157,13 @@ The following diagram summarises the steps that cibuildwheel takes on each platf
| | [`test-groups`](https://cibuildwheel.pypa.io/en/stable/options/#test-groups) | Specify test dependencies from your project's `dependency-groups` |
| | [`test-skip`](https://cibuildwheel.pypa.io/en/stable/options/#test-skip) | Skip running tests on some builds |
| | [`test-environment`](https://cibuildwheel.pypa.io/en/stable/options/#test-environment) | Set environment variables for the test environment |
| | [`test-runtime`](https://cibuildwheel.pypa.io/en/stable/options/#test-runtime) | Controls how the tests will be executed. |
| **Debugging** | [`debug-keep-container`](https://cibuildwheel.pypa.io/en/stable/options/#debug-keep-container) | Keep the container after running for debugging. |
| | [`debug-traceback`](https://cibuildwheel.pypa.io/en/stable/options/#debug-traceback) | Print full traceback when errors occur. |
| | [`build-verbosity`](https://cibuildwheel.pypa.io/en/stable/options/#build-verbosity) | Increase/decrease the output of the build |
<!--[[[end]]] (sum: FxE3nIgFiY) -->
<!--[[[end]]] (sum: dbfwOkj/k/) -->
These options can be specified in a pyproject.toml file, or as environment variables, see [configuration docs](https://cibuildwheel.pypa.io/en/latest/configuration/).
@@ -184,8 +182,8 @@ Here are some repos that use cibuildwheel.
| [duckdb][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | DuckDB is an analytical in-process SQL database management system |
| [pytorch-fairseq][] | ![github icon][] | ![apple icon][] ![linux icon][] | Facebook AI Research Sequence-to-Sequence Toolkit written in Python. |
| [NumPy][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The fundamental package for scientific computing with Python. |
| [Tornado][] | ![github icon][] | ![linux icon][] ![apple icon][] ![windows icon][] | Tornado is a Python web framework and asynchronous networking library. Uses stable ABI for a small C extension. |
| [NCNN][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | ncnn is a high-performance neural network inference framework optimized for the mobile platform |
| [Tornado][] | ![github icon][] | ![linux icon][] ![apple icon][] ![windows icon][] | Tornado is a Python web framework and asynchronous networking library. Uses stable ABI for a small C extension. |
| [Matplotlib][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The venerable Matplotlib, a Python library with C++ portions |
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | The compiled version of MyPy using MyPyC. |
| [Prophet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth. |
@@ -195,8 +193,8 @@ Here are some repos that use cibuildwheel.
[duckdb]: https://github.com/duckdb/duckdb
[pytorch-fairseq]: https://github.com/facebookresearch/fairseq
[NumPy]: https://github.com/numpy/numpy
[Tornado]: https://github.com/tornadoweb/tornado
[NCNN]: https://github.com/Tencent/ncnn
[Tornado]: https://github.com/tornadoweb/tornado
[Matplotlib]: https://github.com/matplotlib/matplotlib
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
[Prophet]: https://github.com/facebook/prophet
@@ -230,6 +228,26 @@ Changelog
<!-- [[[cog from readme_changelog import mini_changelog; print(mini_changelog()) ]]] -->
### v3.3.1
_5 January 2026_
- 🛠 Update dependencies and container pins, including updating to CPython 3.14.2. (#2708)
### v3.3.0
_12 November 2025_
- 🐛 Fix an incompatibility with Docker v29 (#2660)
- ✨ Adds `test-runtime` option, to customise how tests on simulated/emulated environments are run (#2636)
- ✨ Adds support for new `manylinux_2_35` images on 32-bit ARM `armv7l`, offering better C++20 compatibility (#2656)
- ✨ `build[uv]` is now supported on Android (#2587)
- ✨ You can now install extras (such as `uv`) with a simple option on the GitHub Action (#2630)
- ✨ `{project}` and `{package}` placeholders are now supported in `repair-wheel-command` (#2589)
- 🛠 The versions set with `dependency-versions` no longer constrain packages specified by your `build-system.requires`. Previously, on platforms other than Linux, the constraints in this option would remain in the environment during the build. This has been tidied up make behaviour more consistent between platforms, and to prevent version conflicts. (#2583)
- 🛠 Improve the handling of `test-command` on Android, enabling more options to be passed (#2590)
- 📚 Docs improvements (#2618)
### v3.2.1
_12 October 2025_
@@ -267,30 +285,7 @@ _19 August 2025_
- 🧪 Fix and enable doctests (#2546)
- 📚 Improve our docs on free-threading (#2549)
### v3.1.3
_1 August 2025_
- 🐛 Fix bug where "latest" dependencies couldn't update to pip 25.2 on Windows (#2537)
- 🧪 Use pytest-rerunfailures to improve some of our iOS/Android tests (#2527, #2539)
- 🧪 Remove some GraalPy Windows workarounds in our tests (#2501)
### v3.1.2
_29 July 2025_
- ⚠️ Add an error if `CIBW_FREE_THREADING_SUPPORT` is set; you are likely missing 3.13t wheels, please use the `enable`/`CIBW_ENABLE` (#2520)
- 🛠 `riscv64` now enabled if you target that architecture, it's now supported on PyPI (#2509)
- 🛠 Add warning when using `cpython-experimental-riscv64` (no longer needed) (#2526, #2528)
- 🛠 iOS versions bumped, fixing issues with 3.14 (now RC 1) (#2530)
- 🐛 Fix bug in Android running wheel from our GitHub Action (#2517)
- 🐛 Fix warning when using `test-skip` of `"*-macosx_universal2:arm64"` (#2522)
- 🐛 Fix incorrect number of wheels reported in logs, again (#2517)
- 📚 We welcome our Android platform maintainer (#2516)
<!-- [[[end]]] (sum: ZUsMYXdVXu) -->
<!-- [[[end]]] (sum: PDe+dJWkRl) -->
---
+32 -6
View File
@@ -17,6 +17,10 @@ inputs:
description: 'Build a specific wheel only. No need for arch/platform if this is set'
required: false
default: ''
extras:
description: 'Comma-separated list of extras to install'
required: false
default: ''
branding:
icon: package
color: yellow
@@ -27,7 +31,7 @@ runs:
- uses: actions/setup-python@v6
id: python
with:
python-version: "3.11 - 3.13"
python-version: "3.11 - 3.14"
update-environment: false
- id: cibw
@@ -42,6 +46,8 @@ runs:
from pathlib import Path
from subprocess import run
EXTRAS = set(e.strip() for e in "${{ inputs.extras }}".split(",") if e.strip())
class EnvBuilder(venv.EnvBuilder):
def __init__(self):
@@ -53,7 +59,10 @@ runs:
def post_setup(self, context):
super().post_setup(context)
self.bin_path = Path(context.env_exe).parent
run([sys.executable, "-m", "pip", "--python", context.env_exe, "install", r"${{ github.action_path }}"], check=True)
install_spec = r"${{ github.action_path }}"
if EXTRAS:
install_spec += f"[{','.join(sorted(EXTRAS))}]"
run([sys.executable, "-m", "pip", "--python", context.env_exe, "install", install_spec], check=True)
print("::group::Install cibuildwheel")
@@ -62,30 +71,47 @@ runs:
shutil.rmtree(venv_path)
builder = EnvBuilder()
builder.create(venv_path)
cibw_path = [path for path in builder.bin_path.glob("cibuildwheel*") if path.stem == "cibuildwheel"][0]
exposed_binaries = {"cibuildwheel"}
if "uv" in EXTRAS:
exposed_binaries.add("uv")
clean_bin_path = builder.bin_path.parent / f"{builder.bin_path.name}.clean"
clean_bin_path.mkdir()
for path in list(builder.bin_path.iterdir()):
if path.stem in exposed_binaries:
try:
os.symlink(path, clean_bin_path / path.name)
except OSError:
import shutil
shutil.copy2(path, clean_bin_path / path.name)
full_path = f"{clean_bin_path}{os.pathsep}{os.environ['PATH']}"
with open(os.environ["GITHUB_OUTPUT"], "at") as f:
f.write(f"cibw-path={cibw_path}\n")
f.write(f"updated-path={full_path}\n")
print("::endgroup::")
EOF
shell: bash
# Redirecting stderr to stdout to fix interleaving issue in Actions.
- run: >
"${{ steps.cibw.outputs.cibw-path }}"
cibuildwheel
"${{ inputs.package-dir }}"
${{ inputs.output-dir != '' && format('--output-dir "{0}"', inputs.output-dir) || ''}}
${{ inputs.config-file != '' && format('--config-file "{0}"', inputs.config-file) || ''}}
${{ inputs.only != '' && format('--only "{0}"', inputs.only) || ''}}
2>&1
env:
PATH: "${{ steps.cibw.outputs.updated-path }}"
shell: bash
if: runner.os != 'Windows'
# Windows needs powershell to interact nicely with Meson
- run: >
& "${{ steps.cibw.outputs.cibw-path }}"
cibuildwheel
"${{ inputs.package-dir }}"
${{ inputs.output-dir != '' && format('--output-dir "{0}"', inputs.output-dir) || ''}}
${{ inputs.config-file != '' && format('--config-file "{0}"', inputs.config-file) || ''}}
${{ inputs.only != '' && format('--only "{0}"', inputs.only) || ''}}
env:
PATH: "${{ steps.cibw.outputs.updated-path }}"
shell: pwsh
if: runner.os == 'Windows'
+5 -5
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# /// script
# dependencies = ["click", "packaging"]
# dependencies = ["click", "packaging", "prek"]
# ///
@@ -68,8 +68,8 @@ def bump_version() -> None:
sys.exit(1)
# fmt: off
print( 'Current version:', current_version)
new_version = input(' New version: ').strip()
print( "Current version:", current_version)
new_version = input(" New version: ").strip()
# fmt: on
try:
@@ -139,7 +139,7 @@ def bump_version() -> None:
# run pre-commit to update the README changelog
subprocess.run(
[
"pre-commit",
"prek",
"run",
"--files=docs/changelog.md",
],
@@ -149,7 +149,7 @@ def bump_version() -> None:
# run pre-commit to check that no errors occurred on the second run
subprocess.run(
[
"pre-commit",
"prek",
"run",
"--files=docs/changelog.md",
],
+19 -1
View File
@@ -28,7 +28,6 @@ $defs:
description: How to inherit the parent's value.
enable:
enum:
- cpython-experimental-riscv64
- cpython-freethreading
- cpython-prerelease
- graalpy
@@ -224,6 +223,24 @@ properties:
test-environment:
description: Set environment variables for the test environment
type: string_table
test-runtime:
description: Additional configuration for the test runner
oneOf:
- type: string
pattern: '^$'
- type: object
additionalProperties: false
- type: string
pattern: 'args:'
- type: object
additionalProperties: false
required: [args]
properties:
args:
type: array
items:
type: string
"""
schema = yaml.safe_load(starter)
@@ -304,6 +321,7 @@ items:
test-sources: {"$ref": "#/$defs/inherit"}
test-requires: {"$ref": "#/$defs/inherit"}
test-environment: {"$ref": "#/$defs/inherit"}
test-runtime: {"$ref": "#/$defs/inherit"}
"""
)
+2
View File
@@ -71,6 +71,8 @@ images = [
"pypy_aarch64",
],
),
# manylinux_2_35 images
PyPAImage("manylinux_2_35", ["armv7l"]),
# manylinux_2_39 images
PyPAImage("manylinux_2_39", ["riscv64"]),
# musllinux_1_2 images
+1 -1
View File
@@ -1 +1 @@
__version__ = "3.2.1"
__version__ = "3.3.1"
+21 -9
View File
@@ -1,6 +1,7 @@
import argparse
import contextlib
import dataclasses
import functools
import os
import shutil
import sys
@@ -78,8 +79,13 @@ def main_inner(global_options: GlobalOptions) -> None:
`main_inner` is the same as `main`, but it raises FatalError exceptions
rather than exiting directly.
"""
# Default in 3.15+, only needed on 3.14
if sys.version_info >= (3, 14):
arg_parser = functools.partial(argparse.ArgumentParser, suggest_on_error=True)
else:
arg_parser = argparse.ArgumentParser
parser = argparse.ArgumentParser(
parser = arg_parser(
description="Build wheels for all the platforms.",
epilog="""
Most options are supplied via environment variables or in
@@ -314,7 +320,7 @@ def _compute_platform(args: CommandLineArguments) -> PlatformName:
if args.only:
return _compute_platform_only(args.only)
elif platform_option_value != "auto":
return typing.cast(PlatformName, platform_option_value)
return typing.cast("PlatformName", platform_option_value)
return native_platform()
@@ -378,10 +384,23 @@ def build_in_directory(args: CommandLineArguments) -> None:
output_dir.mkdir(parents=True, exist_ok=True)
# Snapshot wheels before build to detect newly built ones
wheels_before = {p.name for p in output_dir.glob("*.whl")}
tmp_path = Path(mkdtemp(prefix="cibw-run-")).resolve(strict=True)
try:
with log.print_summary(options=options):
platform_module.build(options, tmp_path)
# Run audit step after all builds complete
if options.globals.audit_command:
from cibuildwheel.audit import run_audit
run_audit(
audit_command=options.globals.audit_command,
output_dir=output_dir,
wheels_before=wheels_before,
)
finally:
# avoid https://github.com/python/cpython/issues/86962 by performing
# cleanup manually
@@ -463,13 +482,6 @@ def detect_warnings(*, options: Options) -> Generator[str, None, None]:
build_selector = options.globals.build_selector
test_selector = options.globals.test_selector
if EnableGroup.CPythonExperimentalRiscV64 in build_selector.enable:
yield (
"'cpython-experimental-riscv64' enable is deprecated and will be removed in a future version. "
"It should be removed from tool.cibuildwheel.enable in pyproject.toml "
"or CIBW_ENABLE environment variable."
)
all_valid_identifiers = [
config.identifier
for module in ALL_PLATFORM_MODULES.values()
+89
View File
@@ -0,0 +1,89 @@
"""
Audit step for wheels built by cibuildwheel.
This module provides functionality to run audit commands (like abi3audit)
on built wheels after all platform builds are complete.
"""
import os
import subprocess
from pathlib import Path
from packaging.utils import parse_wheel_filename
from .logger import log
from .util.helpers import format_safe
def is_abi3_wheel(wheel_path: Path) -> bool:
"""Check if a wheel is an abi3 wheel by parsing its filename."""
_, _, _, tags = parse_wheel_filename(wheel_path.name)
return any(t.abi == "abi3" for t in tags)
def run_audit(
audit_command: str,
output_dir: Path,
wheels_before: set[str],
) -> None:
"""
Run the audit command on wheels built in this run.
The audit command supports the following placeholders:
- {wheel}: expands to each wheel path, runs the command once per wheel
- {abi3_wheel}: same as {wheel}, but only for abi3 wheels
If the command contains {abi3_wheel} but no abi3 wheels were produced,
the audit step is skipped.
Args:
audit_command: The command template to run
output_dir: Directory where wheels were output
wheels_before: Set of wheel filenames that existed before the build
"""
if not audit_command:
return
# Find wheels built in this run (new wheels that weren't there before)
all_wheels = sorted(output_dir.glob("*.whl"))
just_built = [w for w in all_wheels if w.name not in wheels_before]
if not just_built:
return
# Determine if we're auditing abi3 wheels only
abi3_only = "{abi3_wheel}" in audit_command
# Filter wheels if needed
if abi3_only:
wheels_to_audit = [w for w in just_built if is_abi3_wheel(w)]
if not wheels_to_audit:
log.step("Skipping audit step (no abi3 wheels produced)")
return
else:
wheels_to_audit = just_built
log.step("Running audit...")
for wheel in wheels_to_audit:
# Prepare command with placeholders
prepared = format_safe(
audit_command,
wheel=wheel,
abi3_wheel=wheel,
)
log.step(f" Auditing {wheel.name}...")
env = os.environ.copy()
try:
subprocess.run(
prepared,
shell=True,
check=True,
env=env,
cwd=output_dir,
)
except subprocess.CalledProcessError as e:
log.error(f"Audit command failed for {wheel.name}")
raise SystemExit(e.returncode) from e
+2 -2
View File
@@ -41,7 +41,7 @@ def dump_python_configurations(
def _json_request(request: urllib.request.Request, timeout: int = 30) -> dict[str, Any]:
with urllib.request.urlopen(request, timeout=timeout) as response:
return typing.cast(dict[str, Any], json.load(response))
return typing.cast("dict[str, Any]", json.load(response))
def github_api_request(path: str, *, max_retries: int = 3) -> dict[str, Any]:
@@ -98,4 +98,4 @@ def get_pyodide_xbuildenv_info() -> PyodideXBuildEnvInfo:
"https://pyodide.github.io/pyodide/api/pyodide-cross-build-environments.json"
)
with urllib.request.urlopen(xbuildenv_info_url) as response:
return typing.cast(PyodideXBuildEnvInfo, json.loads(response.read().decode("utf-8")))
return typing.cast("PyodideXBuildEnvInfo", json.loads(response.read().decode("utf-8")))
+1 -1
View File
@@ -24,7 +24,7 @@ class BuildFrontendConfig:
msg = f"Unrecognised build frontend {name!r}, must be one of {names}"
raise ValueError(msg)
name = typing.cast(BuildFrontendName, name)
name = typing.cast("BuildFrontendName", name)
args = config_dict.get("args") or []
return cls(name=name, args=args)
+11 -8
View File
@@ -78,7 +78,7 @@ class OCIContainerEngineConfig:
msg = f"unknown container engine {name}"
raise ValueError(msg)
name = typing.cast(ContainerEngineName, name)
name = typing.cast("ContainerEngineName", name)
# some flexibility in the option names to cope with TOML conventions
create_args = config_dict.get("create_args") or config_dict.get("create-args") or []
disable_host_mount_options = (
@@ -116,11 +116,14 @@ DEFAULT_ENGINE = OCIContainerEngineConfig("docker")
def _check_engine_version(engine: OCIContainerEngineConfig) -> None:
try:
version_string = call(engine.name, "version", "-f", "{{json .}}", capture_stdout=True)
version_info = json.loads(version_string.strip())
# We are using lowercase keys for all dicts so we are not affected by casing of keys
version_info = json.loads(
version_string.strip(), object_pairs_hook=lambda inp: {k.lower(): v for k, v in inp}
)
match engine.name:
case "docker":
client_api_version = FlexibleVersion(version_info["Client"]["ApiVersion"])
server_api_version = FlexibleVersion(version_info["Server"]["ApiVersion"])
client_api_version = FlexibleVersion(version_info["client"]["apiversion"])
server_api_version = FlexibleVersion(version_info["server"]["apiversion"])
# --platform support was introduced in 1.32 as experimental, 1.41 removed the experimental flag
version = min(client_api_version, server_api_version)
minimum_version = FlexibleVersion("1.41")
@@ -135,9 +138,9 @@ def _check_engine_version(engine: OCIContainerEngineConfig) -> None:
)
case "podman":
# podman uses the same version string for "Version" & "ApiVersion"
client_version = FlexibleVersion(version_info["Client"]["Version"])
if "Server" in version_info:
server_version = FlexibleVersion(version_info["Server"]["Version"])
client_version = FlexibleVersion(version_info["client"]["version"])
if "server" in version_info:
server_version = FlexibleVersion(version_info["server"]["version"])
else:
server_version = client_version
# --platform support was introduced in v3
@@ -515,7 +518,7 @@ class OCIContainer:
capture_output=True,
)
)
return typing.cast(dict[str, str], env)
return typing.cast("dict[str, str]", env)
def environment_executor(self, command: Sequence[str], environment: dict[str, str]) -> str:
# used as an EnvironmentExecutor to evaluate commands and capture output
+35 -1
View File
@@ -24,7 +24,7 @@ from .projectfiles import get_requires_python_str, resolve_dependency_groups
from .selector import BuildSelector, EnableGroup, TestSelector, selector_matches
from .typing import PLATFORMS, PlatformName
from .util import resources
from .util.helpers import format_safe, strtobool, unwrap
from .util.helpers import format_safe, parse_key_value_string, strtobool, unwrap
from .util.packaging import DependencyConstraints
MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
@@ -90,6 +90,21 @@ class GlobalOptions:
test_selector: TestSelector
architectures: set[Architecture]
allow_empty: bool
audit_command: str
@dataclasses.dataclass(frozen=True)
class TestRuntimeConfig:
args: Sequence[str] = ()
@classmethod
def from_config_string(cls, config_string: str) -> Self:
config_dict = parse_key_value_string(config_string, [], ["args"])
args = config_dict.get("args") or []
return cls(args=args)
def options_summary(self) -> str | dict[str, str]:
return {"args": repr(self.args)}
@dataclasses.dataclass(frozen=True, kw_only=True)
@@ -110,6 +125,7 @@ class BuildOptions:
test_extras: str
test_groups: list[str]
test_environment: ParsedEnvironment
test_runtime: TestRuntimeConfig
build_verbosity: int
build_frontend: BuildFrontendConfig
config_settings: str
@@ -680,6 +696,8 @@ class Options:
)
test_selector = TestSelector(skip_config=test_skip)
audit_command = self.reader.get("audit", option_format=ListFormat(sep=" && "))
return GlobalOptions(
package_dir=package_dir,
output_dir=output_dir,
@@ -687,6 +705,7 @@ class Options:
test_selector=test_selector,
architectures=architectures,
allow_empty=allow_empty,
audit_command=audit_command,
)
def _check_pinned_image(self, value: str, pinned_images: Mapping[str, str]) -> None:
@@ -761,6 +780,20 @@ class Options:
msg = f"Malformed environment option {test_environment_config!r}"
raise errors.ConfigurationError(msg) from e
test_runtime_str = self.reader.get(
"test-runtime",
env_plat=False,
option_format=ShlexTableFormat(sep="; ", pair_sep=":", allow_merge=False),
)
if not test_runtime_str:
test_runtime = TestRuntimeConfig()
else:
try:
test_runtime = TestRuntimeConfig.from_config_string(test_runtime_str)
except ValueError as e:
msg = f"Failed to parse test runtime config. {e}"
raise errors.ConfigurationError(msg) from e
test_requires = self.reader.get(
"test-requires", option_format=ListFormat(sep=" ")
).split()
@@ -868,6 +901,7 @@ class Options:
test_command=test_command,
test_sources=test_sources,
test_environment=test_environment,
test_runtime=test_runtime,
test_requires=[*test_requires, *test_requirements_from_groups],
test_extras=test_extras,
test_groups=test_groups,
+10 -7
View File
@@ -1,16 +1,19 @@
from __future__ import annotations
import sys
from collections.abc import Sequence
from pathlib import Path
from typing import Final, Protocol
from typing import TYPE_CHECKING, Final, Protocol
from cibuildwheel import errors
from cibuildwheel.architecture import Architecture
from cibuildwheel.options import Options
from cibuildwheel.platforms import android, ios, linux, macos, pyodide, windows
from cibuildwheel.selector import BuildSelector
from cibuildwheel.typing import GenericPythonConfiguration, PlatformName
if TYPE_CHECKING:
from collections.abc import Sequence
from pathlib import Path
from cibuildwheel.architecture import Architecture
from cibuildwheel.options import Options
from cibuildwheel.selector import BuildSelector
from cibuildwheel.typing import GenericPythonConfiguration, PlatformName
class PlatformModule(Protocol):
+99 -27
View File
@@ -7,7 +7,7 @@ import shlex
import shutil
import subprocess
import sysconfig
from collections.abc import Iterable, Iterator
from collections.abc import Iterable, Iterator, MutableMapping
from dataclasses import dataclass
from os.path import relpath
from pathlib import Path
@@ -34,14 +34,12 @@ from ..util.file import CIBW_CACHE_PATH, copy_test_sources, download, move_file
from ..util.helpers import prepare_command
from ..util.packaging import find_compatible_wheel
from ..util.python_build_standalone import create_python_build_standalone_environment
from ..venv import constraint_flags, virtualenv
from ..venv import constraint_flags, find_uv, virtualenv
def android_triplet(identifier: str) -> str:
return {
"arm64_v8a": "aarch64-linux-android",
"x86_64": "x86_64-linux-android",
}[parse_identifier(identifier)[1]]
ANDROID_TRIPLET = {
"arm64_v8a": "aarch64-linux-android",
"x86_64": "x86_64-linux-android",
}
def parse_identifier(identifier: str) -> tuple[str, str]:
@@ -53,6 +51,10 @@ def parse_identifier(identifier: str) -> tuple[str, str]:
return (f"{major}.{minor}", arch)
def android_triplet(identifier: str) -> str:
return ANDROID_TRIPLET[parse_identifier(identifier)[1]]
@dataclass(frozen=True)
class PythonConfiguration:
version: str
@@ -147,7 +149,7 @@ def build(options: Options, tmp_path: Path) -> None:
built_wheel = build_wheel(state)
repaired_wheel = repair_wheel(state, built_wheel)
test_wheel(state, repaired_wheel)
test_wheel(state, repaired_wheel, build_frontend=build_options.build_frontend.name)
output_wheel: Path | None = None
if compatible_wheel is None:
@@ -187,6 +189,13 @@ def setup_env(
* android_env, which uses the environment while simulating running on Android.
"""
log.step("Setting up build environment...")
build_frontend = build_options.build_frontend.name
use_uv = build_frontend == "build[uv]"
uv_path = find_uv()
if use_uv and uv_path is None:
msg = "uv not found"
raise AssertionError(msg)
pip = ["pip"] if not use_uv else [str(uv_path), "pip"]
# Create virtual environment
python_exe = create_python_build_standalone_environment(
@@ -197,14 +206,14 @@ def setup_env(
version=config.version, tmp_dir=build_path
)
build_env = virtualenv(
config.version, python_exe, venv_dir, dependency_constraint, use_uv=False
config.version, python_exe, venv_dir, dependency_constraint, use_uv=use_uv
)
create_cmake_toolchain(config, build_path, python_dir, build_env)
# Apply custom environment variables, and check environment is still valid
build_env = build_options.environment.as_dictionary(build_env)
build_env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1"
for command in ["python", "pip"]:
for command in ["python"] if use_uv else ["python", "pip"]:
command_path = call("which", command, env=build_env, capture_stdout=True).strip()
if command_path != f"{venv_dir}/bin/{command}":
msg = (
@@ -219,11 +228,10 @@ def setup_env(
android_env = setup_android_env(config, python_dir, venv_dir, build_env)
# Install build tools
build_frontend = build_options.build_frontend
if build_frontend.name != "build":
if build_frontend not in {"build", "build[uv]"}:
msg = "Android requires the build frontend to be 'build'"
raise errors.FatalError(msg)
call("pip", "install", "build", *constraint_flags(dependency_constraint), env=build_env)
call(*pip, "install", "build", *constraint_flags(dependency_constraint), env=build_env)
# Build-time requirements must be queried within android_env, because
# `get_requires_for_build` can run arbitrary code in setup.py scripts, which may be
@@ -243,13 +251,13 @@ def setup_env(
pb = ProjectBuilder.from_isolated_env(AndroidEnv(), build_options.package_dir)
if pb.build_system_requires:
call("pip", "install", *pb.build_system_requires, env=build_env)
call(*pip, "install", *pb.build_system_requires, env=build_env)
requires_for_build = pb.get_requires_for_build(
"wheel", parse_config_settings(build_options.config_settings)
)
if requires_for_build:
call("pip", "install", *requires_for_build, env=build_env)
call(*pip, "install", *requires_for_build, env=build_env)
return build_env, android_env
@@ -382,6 +390,9 @@ def setup_android_env(
for key in ["CFLAGS", "CXXFLAGS"]:
android_env[key] += " " + opt
# Cargo target linker needs to be specified after CC is set
setup_rust(config, python_dir, android_env)
# Format the environment so it can be pasted into a shell when debugging.
for key, value in sorted(android_env.items()):
if os.environ.get(key) != value:
@@ -390,6 +401,34 @@ def setup_android_env(
return android_env
def setup_rust(
config: PythonConfiguration,
python_dir: Path,
env: MutableMapping[str, str],
) -> None:
cargo_target = android_triplet(config.identifier)
# CARGO_BUILD_TARGET is the variable used by Cargo and setuptools_rust
env["CARGO_BUILD_TARGET"] = cargo_target
# The linker needs to be specified after CC is set by android-env.sh
cargo_target_linker_env_name = f"CARGO_TARGET_{cargo_target.upper().replace('-', '_')}_LINKER"
# CC has already been set by calling android.py (it calls android-env.sh)
env[cargo_target_linker_env_name] = env["CC"]
# All Python extension modules must be explicitly linked against libpython3.x.so when building for Android.
# See: https://peps.python.org/pep-0738/#linkage
# For projects using PyO3, this requires setting PYO3_CROSS_LIB_DIR to the directory containing libpython3.x.so.
# See: https://pyo3.rs/v0.27.1/building-and-distribution.html#cross-compiling
env["PYO3_CROSS_LIB_DIR"] = str(python_dir / "prefix" / "lib")
venv_bin = Path(env["VIRTUAL_ENV"]) / "bin"
for tool in ["cargo", "rustup"]:
shim_path = venv_bin / tool
shutil.copy(resources.PATH / "_rust_shim.py", shim_path)
shim_path.chmod(0o755)
def before_build(state: BuildState) -> None:
if state.options.before_build:
log.step("Running before_build...")
@@ -439,7 +478,11 @@ def repair_wheel(state: BuildState, built_wheel: Path) -> Path:
if state.options.repair_command:
shell(
prepare_command(
state.options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir
state.options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
package=state.options.package_dir,
project=".",
),
env=state.build_env,
)
@@ -559,12 +602,19 @@ def soname_with_hash(src_path: Path) -> str:
return src_name
def test_wheel(state: BuildState, wheel: Path) -> None:
def test_wheel(state: BuildState, wheel: Path, *, build_frontend: str) -> None:
test_command = state.options.test_command
if not (test_command and state.options.test_selector(state.config.identifier)):
return
log.step("Testing wheel...")
use_uv = build_frontend == "build[uv]"
uv_path = find_uv()
if use_uv and uv_path is None:
msg = "uv not found"
raise AssertionError(msg)
pip = ["pip"] if not use_uv else [str(uv_path), "pip"]
native_arch = arch_synonym(platform.machine(), platforms.native_platform(), "android")
if state.config.arch != native_arch:
log.warning(
@@ -580,15 +630,23 @@ def test_wheel(state: BuildState, wheel: Path) -> None:
env=state.build_env,
)
platform_args = (
["--python-platform", android_triplet(state.config.identifier)]
if use_uv
else [
"--platform",
sysconfig_print("get_platform()", state.android_env).replace("-", "_"),
]
)
# Install the wheel and test-requires.
site_packages_dir = state.build_path / "site-packages"
site_packages_dir.mkdir()
call(
"pip",
*pip,
"install",
"--only-binary=:all:",
"--platform",
sysconfig_print("get_platform()", state.android_env).replace("-", "_"),
*platform_args,
"--target",
site_packages_dir,
f"{wheel}{state.options.test_extras}",
@@ -617,8 +675,11 @@ def test_wheel(state: BuildState, wheel: Path) -> None:
# Parse test-command.
test_args = shlex.split(test_command)
if test_args[:2] in [["python", "-c"], ["python", "-m"]]:
test_args[:3] = [test_args[1], test_args[2], "--"]
if test_args[0] in ["python", "python3"] and any(arg in test_args for arg in ["-c", "-m"]):
# Forward the args to the CPython testbed script. We require '-c' or '-m'
# to be in the command, because without those flags, the testbed script
# will prepend '-m test', which will run Python's own test suite.
del test_args[0]
elif test_args[0] in ["pytest"]:
# We transform some commands into the `python -m` form, but this is deprecated.
msg = (
@@ -627,25 +688,36 @@ def test_wheel(state: BuildState, wheel: Path) -> None:
"If this works, all you need to do is add that to your test command."
)
log.warning(msg)
test_args[:1] = ["-m", test_args[0], "--"]
test_args.insert(0, "-m")
else:
msg = (
f"Test command {test_command!r} is not supported on Android. "
f"Supported commands are 'python -m' and 'python -c'."
f"Command must begin with 'python' or 'python3', and contain '-m' or '-c'."
)
raise errors.FatalError(msg)
# By default, run on a testbed managed emulator running the newest supported
# Android version. However, if the user specifies a --managed or --connected
# test execution argument, that argument takes precedence.
test_runtime_args = state.options.test_runtime.args
if any(arg.startswith(("--managed", "--connected")) for arg in test_runtime_args):
emulator_args = []
else:
emulator_args = ["--managed", "maxVersion"]
# Run the test app.
call(
state.python_dir / "android.py",
"test",
"--managed",
"maxVersion",
"--site-packages",
site_packages_dir,
"--cwd",
cwd_dir,
*emulator_args,
*(["-v"] if state.options.build_verbosity > 0 else []),
*test_runtime_args,
"--",
*test_args,
env=state.build_env,
)
+37 -19
View File
@@ -2,27 +2,23 @@ from __future__ import annotations
import dataclasses
import os
import platform
import shlex
import shutil
import subprocess
import sys
import textwrap
from collections.abc import Sequence, Set
from pathlib import Path
from typing import assert_never
from typing import TYPE_CHECKING, assert_never
from filelock import FileLock
from .. import errors
from ..architecture import Architecture
from ..environment import ParsedEnvironment
from ..frontend import (
BuildFrontendName,
get_build_frontend_extra_flags,
)
from ..logger import log
from ..options import Options
from ..selector import BuildSelector
from ..util import resources
from ..util.cmd import call, shell, split_command
from ..util.file import (
@@ -33,13 +29,19 @@ from ..util.file import (
)
from ..util.helpers import prepare_command, unwrap_preserving_paragraphs
from ..util.packaging import (
combine_constraints,
find_compatible_wheel,
get_pip_version,
)
from ..venv import constraint_flags, virtualenv
from .macos import install_cpython as install_build_cpython
if TYPE_CHECKING:
from collections.abc import Sequence, Set
from ..architecture import Architecture
from ..environment import ParsedEnvironment
from ..options import Options
from ..selector import BuildSelector
@dataclasses.dataclass(frozen=True, kw_only=True)
class PythonConfiguration:
@@ -461,7 +463,6 @@ def build(options: Options, tmp_path: Path) -> None:
build_frontend=build_frontend.name,
xbuild_tools=build_options.xbuild_tools,
)
pip_version = get_pip_version(env)
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
if compatible_wheel:
@@ -489,11 +490,6 @@ def build(options: Options, tmp_path: Path) -> None:
build_frontend, build_options.build_verbosity, build_options.config_settings
)
build_env = env.copy()
build_env["VIRTUALENV_PIP"] = pip_version
if constraints_path:
combine_constraints(build_env, constraints_path, None)
match build_frontend.name:
case "pip":
# Path.resolve() is needed. Without it pip wheel may try to
@@ -508,7 +504,7 @@ def build(options: Options, tmp_path: Path) -> None:
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*extra_flags,
env=build_env,
env=env,
)
case "build":
call(
@@ -519,7 +515,7 @@ def build(options: Options, tmp_path: Path) -> None:
"--wheel",
f"--outdir={built_wheel_dir}",
*extra_flags,
env=build_env,
env=env,
)
case _:
assert_never(build_frontend)
@@ -537,9 +533,7 @@ def build(options: Options, tmp_path: Path) -> None:
elif config.arch != os.uname().machine:
log.step("Skipping tests on non-native simulator architecture")
else:
test_env = build_options.test_environment.as_dictionary(
prev_environment=build_env
)
test_env = build_options.test_environment.as_dictionary(prev_environment=env)
if build_options.before_test:
before_test_prepared = prepare_command(
@@ -653,11 +647,35 @@ def build(options: Options, tmp_path: Path) -> None:
)
raise errors.FatalError(msg)
test_runtime_args = build_options.test_runtime.args
# 2025-10: The GitHub Actions macos-15 runner has a known issue where
# the default simulator won't start due to a disk performance issue;
# see https://github.com/actions/runner-images/issues/12777 for details.
# In the meantime, if it looks like we're running on a GitHub Actions
# macos-15 runner, use a simulator that is known to work, unless the
# user explicitly specifies a simulator.
os_version, _, arch = platform.mac_ver()
if (
"GITHUB_ACTIONS" in os.environ
and os_version.startswith("15.")
and arch == "arm64"
and not any(
arg.startswith("--simulator") for arg in test_runtime_args
)
):
test_runtime_args = [
"--simulator",
"iPhone 16e,OS=18.5",
*test_runtime_args,
]
call(
"python",
testbed_path,
"run",
*(["--verbose"] if build_options.build_verbosity > 0 else []),
*test_runtime_args,
"--",
*final_command,
env=test_env,
+9 -3
View File
@@ -6,7 +6,7 @@ import textwrap
from collections import OrderedDict
from collections.abc import Iterable, Iterator, Sequence, Set
from pathlib import Path, PurePath, PurePosixPath
from typing import assert_never
from typing import TYPE_CHECKING, assert_never
from .. import errors
from ..architecture import Architecture
@@ -15,12 +15,14 @@ from ..logger import log
from ..oci_container import OCIContainer, OCIContainerEngineConfig, OCIPlatform
from ..options import BuildOptions, Options
from ..selector import BuildSelector
from ..typing import PathOrStr
from ..util import resources
from ..util.file import copy_test_sources
from ..util.helpers import prepare_command, unwrap
from ..util.packaging import find_compatible_wheel
if TYPE_CHECKING:
from ..typing import PathOrStr
ARCHITECTURE_OCI_PLATFORM_MAP = {
Architecture.x86_64: OCIPlatform.AMD64,
Architecture.i686: OCIPlatform.i386,
@@ -320,7 +322,11 @@ def build_in_container(
if build_options.repair_command:
log.step("Repairing wheel...")
repair_command_prepared = prepare_command(
build_options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir
build_options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
package=container_package_dir,
project=container_project_path,
)
container.call(["sh", "-c", repair_command_prepared], env=env)
else:
+6 -9
View File
@@ -32,7 +32,7 @@ from ..util.file import (
move_file,
)
from ..util.helpers import prepare_command, unwrap
from ..util.packaging import combine_constraints, find_compatible_wheel, get_pip_version
from ..util.packaging import find_compatible_wheel, get_pip_version
from ..venv import constraint_flags, find_uv, virtualenv
@@ -60,7 +60,7 @@ def get_macos_version() -> tuple[int, int]:
capture_stdout=True,
)
version = tuple(map(int, version_str.split(".")[:2]))
return typing.cast(tuple[int, int], version)
return typing.cast("tuple[int, int]", version)
@functools.cache
@@ -141,7 +141,8 @@ def install_cpython(_tmp: Path, version: str, url: str, free_threading: bool) ->
# let the user know & provide a link to the installer
msg = inspect.cleandoc(
f"""
Error: CPython {version} is not installed.
Framework CPython {version} not detected as installed in:
{installation_path}
cibuildwheel will not perform system-wide installs when running outside of CI.
To build locally, install CPython {version} on this machine, or, disable this
version of Python using CIBW_SKIP=cp{version.replace(".", "")}-macosx_*
@@ -464,12 +465,6 @@ def build(options: Options, tmp_path: Path) -> None:
)
build_env = env.copy()
if pip_version is not None:
build_env["VIRTUALENV_PIP"] = pip_version
if constraints_path:
combine_constraints(
build_env, constraints_path, identifier_tmp_dir if use_uv else None
)
match build_frontend.name:
case "pip":
@@ -528,6 +523,8 @@ def build(options: Options, tmp_path: Path) -> None:
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
delocate_archs=delocate_archs,
package=build_options.package_dir,
project=".",
)
shell(repair_command_prepared, env=env)
else:
+5 -7
View File
@@ -32,7 +32,7 @@ from ..util.file import (
move_file,
)
from ..util.helpers import prepare_command, unwrap, unwrap_preserving_paragraphs
from ..util.packaging import combine_constraints, find_compatible_wheel, get_pip_version
from ..util.packaging import find_compatible_wheel, get_pip_version
from ..util.python_build_standalone import (
PythonBuildStandaloneError,
create_python_build_standalone_environment,
@@ -130,7 +130,7 @@ def get_all_xbuildenv_version_info(env: dict[str, str]) -> list[PyodideXBuildEnv
msg = f"Invalid xbuildenvs info, got {xbuildenvs_info}"
raise ValueError(msg)
return typing.cast(list[PyodideXBuildEnvInfo], xbuildenvs_info["environments"])
return typing.cast("list[PyodideXBuildEnvInfo]", xbuildenvs_info["environments"])
def get_xbuildenv_version_info(
@@ -419,17 +419,13 @@ def build(options: Options, tmp_path: Path) -> None:
build_frontend, build_options.build_verbosity, build_options.config_settings
)
build_env = env.copy()
if constraints_path:
combine_constraints(build_env, constraints_path, identifier_tmp_dir)
build_env["VIRTUALENV_PIP"] = pip_version
call(
"pyodide",
"build",
build_options.package_dir,
f"--outdir={built_wheel_dir}",
*extra_flags,
env=build_env,
env=env,
)
built_wheel = next(built_wheel_dir.glob("*.whl"))
@@ -443,6 +439,8 @@ def build(options: Options, tmp_path: Path) -> None:
build_options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
package=build_options.package_dir,
project=".",
)
shell(repair_command_prepared, env=env)
log.step_end()
+5 -10
View File
@@ -23,7 +23,7 @@ from ..util import resources
from ..util.cmd import call, shell
from ..util.file import CIBW_CACHE_PATH, copy_test_sources, download, extract_zip, move_file
from ..util.helpers import prepare_command, unwrap
from ..util.packaging import combine_constraints, find_compatible_wheel, get_pip_version
from ..util.packaging import find_compatible_wheel, get_pip_version
from ..venv import constraint_flags, find_uv, virtualenv
@@ -468,13 +468,6 @@ def build(options: Options, tmp_path: Path) -> None:
shell("graalpy -m pip install setuptools wheel", env=env)
extra_flags = [*extra_flags, "-n"]
build_env = env.copy()
if pip_version is not None:
build_env["VIRTUALENV_PIP"] = pip_version
if constraints_path:
combine_constraints(build_env, constraints_path, identifier_tmp_dir)
match build_frontend.name:
case "pip":
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
@@ -488,7 +481,7 @@ def build(options: Options, tmp_path: Path) -> None:
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*extra_flags,
env=build_env,
env=env,
)
case "build" | "build[uv]":
if (
@@ -506,7 +499,7 @@ def build(options: Options, tmp_path: Path) -> None:
"--wheel",
f"--outdir={built_wheel_dir}",
*extra_flags,
env=build_env,
env=env,
)
case _:
assert_never(build_frontend)
@@ -525,6 +518,8 @@ def build(options: Options, tmp_path: Path) -> None:
build_options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
package=build_options.package_dir,
project=".",
)
shell(repair_command_prepared, env=env)
else:
+1 -1
View File
@@ -50,7 +50,7 @@ class Analyzer(ast.NodeVisitor):
)
match node:
case ast.keyword(arg="python_requires", value=ast.Constant(value=str(version))):
case ast.keyword(arg="python_requires", value=ast.Constant(value=str() as version)):
if unnested or name_main_unnested:
self.requires_python = version
+11 -7
View File
@@ -68,16 +68,20 @@ def initialize() -> None:
# sysconfig ###############################################################
#
# We don't change the actual sys.base_prefix and base_exec_prefix, because that
# could have unpredictable effects. Instead, we change the internal variables
# used to generate sysconfig.get_path("include").
exec_prefix = sysconfig.get_config_var("exec_prefix")
sysconfig._BASE_PREFIX = sysconfig._BASE_EXEC_PREFIX = exec_prefix # type: ignore[attr-defined]
# Reload the sysconfigdata file, generating its name from sys.abiflags,
# Load the sysconfigdata file, generating its name from sys.abiflags,
# sys.platform, and sys.implementation._multiarch.
sysconfig._init_config_vars() # type: ignore[attr-defined]
# We don't change the actual sys.base_prefix and base_exec_prefix, because that
# could have unpredictable effects. Instead, we change the sysconfig variables
# used by sysconfig.get_paths().
vars = sysconfig.get_config_vars()
try:
host_prefix = vars["host_prefix"] # This variable was added in Python 3.14.
except KeyError:
host_prefix = vars["exec_prefix"]
vars["installed_base"] = vars["installed_platbase"] = host_prefix
# sysconfig.get_platform, which determines the wheel tag, is implemented in terms of
# sys.platform, sysconfig.get_config_var("ANDROID_API_LEVEL") (see localized_vars in
# android.py), and os.uname.
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
import os
import shutil
import subprocess
import sys
from pathlib import Path
def main() -> None:
# CIBW_HOST_TRIPLET is set in the android_env to the Android target triplet.
target = os.environ.get("CIBW_HOST_TRIPLET")
cmd_name = Path(sys.argv[0]).name
# Find the real command in PATH, excluding the current script's directory
path_env = os.environ.get("PATH", "")
script_dir = Path(__file__).resolve().parent
paths = path_env.split(os.pathsep)
# Filter out the script directory to avoid recursion
filtered_paths = [p for p in paths if Path(p).resolve() != script_dir]
filtered_path_env = os.pathsep.join(filtered_paths)
real_cmd = shutil.which(cmd_name, path=filtered_path_env)
if not real_cmd:
sys.stderr.write(f"cibuildwheel: Error: Could not find system {cmd_name}\n")
sys.exit(1)
# If we have a target (i.e. we are in the android_env), try to install it.
if target:
# Check if rustup is available to install the target
rustup_path = shutil.which("rustup", path=filtered_path_env)
if rustup_path:
try:
# We call rustup to ensure the target is installed.
subprocess.run(
[rustup_path, "target", "add", target],
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
text=True,
)
except subprocess.CalledProcessError as e:
sys.stderr.write(
f"cibuildwheel: Error: Failed to install Rust target {target}: {e.stderr}\n"
)
sys.exit(1)
# Execute the real command
os.execv(real_cmd, [real_cmd, *sys.argv[1:]])
if __name__ == "__main__":
main()
+32 -32
View File
@@ -161,18 +161,18 @@ python_configurations = [
{ identifier = "cp312-macosx_x86_64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.10/python-3.12.10-macos11.pkg" },
{ identifier = "cp312-macosx_arm64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.10/python-3.12.10-macos11.pkg" },
{ identifier = "cp312-macosx_universal2", version = "3.12", url = "https://www.python.org/ftp/python/3.12.10/python-3.12.10-macos11.pkg" },
{ identifier = "cp313-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.8/python-3.13.8-macos11.pkg" },
{ identifier = "cp313-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.8/python-3.13.8-macos11.pkg" },
{ identifier = "cp313-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.8/python-3.13.8-macos11.pkg" },
{ identifier = "cp313t-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.8/python-3.13.8-macos11.pkg" },
{ identifier = "cp313t-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.8/python-3.13.8-macos11.pkg" },
{ identifier = "cp313t-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.8/python-3.13.8-macos11.pkg" },
{ identifier = "cp314-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-macos11.pkg" },
{ identifier = "cp314-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-macos11.pkg" },
{ identifier = "cp314-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-macos11.pkg" },
{ identifier = "cp314t-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-macos11.pkg" },
{ identifier = "cp314t-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-macos11.pkg" },
{ identifier = "cp314t-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-macos11.pkg" },
{ identifier = "cp313-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.11/python-3.13.11-macos11.pkg" },
{ identifier = "cp313-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.11/python-3.13.11-macos11.pkg" },
{ identifier = "cp313-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.11/python-3.13.11-macos11.pkg" },
{ identifier = "cp313t-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.11/python-3.13.11-macos11.pkg" },
{ identifier = "cp313t-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.11/python-3.13.11-macos11.pkg" },
{ identifier = "cp313t-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.11/python-3.13.11-macos11.pkg" },
{ identifier = "cp314-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-macos11.pkg" },
{ identifier = "cp314-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-macos11.pkg" },
{ identifier = "cp314-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-macos11.pkg" },
{ identifier = "cp314t-macosx_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-macos11.pkg" },
{ identifier = "cp314t-macosx_arm64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-macos11.pkg" },
{ identifier = "cp314t-macosx_universal2", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-macos11.pkg" },
{ identifier = "pp38-macosx_x86_64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-macos_x86_64.tar.bz2" },
{ identifier = "pp38-macosx_arm64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-macos_arm64.tar.bz2" },
{ identifier = "pp39-macosx_x86_64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-macos_x86_64.tar.bz2" },
@@ -183,8 +183,8 @@ python_configurations = [
{ identifier = "pp311-macosx_arm64", version = "3.11", url = "https://downloads.python.org/pypy/pypy3.11-v7.3.20-macos_arm64.tar.bz2" },
{ identifier = "gp311_242-macosx_x86_64", version = "3.11", url = "https://github.com/oracle/graalpython/releases/download/graal-24.2.2/graalpy-24.2.2-macos-amd64.tar.gz" },
{ identifier = "gp311_242-macosx_arm64", version = "3.11", url = "https://github.com/oracle/graalpython/releases/download/graal-24.2.2/graalpy-24.2.2-macos-aarch64.tar.gz" },
{ identifier = "gp312_250-macosx_x86_64", version = "3.12", url = "https://github.com/oracle/graalpython/releases/download/graal-25.0.0/graalpy-25.0.0-macos-amd64.tar.gz" },
{ identifier = "gp312_250-macosx_arm64", version = "3.12", url = "https://github.com/oracle/graalpython/releases/download/graal-25.0.0/graalpy-25.0.0-macos-aarch64.tar.gz" },
{ identifier = "gp312_250-macosx_x86_64", version = "3.12", url = "https://github.com/oracle/graalpython/releases/download/graal-25.0.1/graalpy-25.0.1-macos-amd64.tar.gz" },
{ identifier = "gp312_250-macosx_arm64", version = "3.12", url = "https://github.com/oracle/graalpython/releases/download/graal-25.0.1/graalpy-25.0.1-macos-aarch64.tar.gz" },
]
[windows]
@@ -199,42 +199,42 @@ python_configurations = [
{ identifier = "cp311-win_amd64", version = "3.11.9" },
{ identifier = "cp312-win32", version = "3.12.10" },
{ identifier = "cp312-win_amd64", version = "3.12.10" },
{ identifier = "cp313-win32", version = "3.13.8" },
{ identifier = "cp313t-win32", version = "3.13.8" },
{ identifier = "cp313-win_amd64", version = "3.13.8" },
{ identifier = "cp313t-win_amd64", version = "3.13.8" },
{ identifier = "cp314-win32", version = "3.14.0" },
{ identifier = "cp314t-win32", version = "3.14.0" },
{ identifier = "cp314-win_amd64", version = "3.14.0" },
{ identifier = "cp314t-win_amd64", version = "3.14.0" },
{ identifier = "cp313-win32", version = "3.13.11" },
{ identifier = "cp313t-win32", version = "3.13.11" },
{ identifier = "cp313-win_amd64", version = "3.13.11" },
{ identifier = "cp313t-win_amd64", version = "3.13.11" },
{ identifier = "cp314-win32", version = "3.14.2" },
{ identifier = "cp314t-win32", version = "3.14.2" },
{ identifier = "cp314-win_amd64", version = "3.14.2" },
{ identifier = "cp314t-win_amd64", version = "3.14.2" },
{ identifier = "cp39-win_arm64", version = "3.9.10" },
{ identifier = "cp310-win_arm64", version = "3.10.11" },
{ identifier = "cp311-win_arm64", version = "3.11.9" },
{ identifier = "cp312-win_arm64", version = "3.12.10" },
{ identifier = "cp313-win_arm64", version = "3.13.8" },
{ identifier = "cp313t-win_arm64", version = "3.13.8" },
{ identifier = "cp314-win_arm64", version = "3.14.0" },
{ identifier = "cp314t-win_arm64", version = "3.14.0" },
{ identifier = "cp313-win_arm64", version = "3.13.11" },
{ identifier = "cp313t-win_arm64", version = "3.13.11" },
{ identifier = "cp314-win_arm64", version = "3.14.2" },
{ identifier = "cp314t-win_arm64", version = "3.14.2" },
{ identifier = "pp38-win_amd64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-win64.zip" },
{ identifier = "pp39-win_amd64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-win64.zip" },
{ identifier = "pp310-win_amd64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.19-win64.zip" },
{ identifier = "pp311-win_amd64", version = "3.11", url = "https://downloads.python.org/pypy/pypy3.11-v7.3.20-win64.zip" },
{ identifier = "gp311_242-win_amd64", version = "3.11", url = "https://github.com/oracle/graalpython/releases/download/graal-24.2.2/graalpy-24.2.2-windows-amd64.zip" },
{ identifier = "gp312_250-win_amd64", version = "3.12", url = "https://github.com/oracle/graalpython/releases/download/graal-25.0.0/graalpy-25.0.0-windows-amd64.zip" },
{ identifier = "gp312_250-win_amd64", version = "3.12", url = "https://github.com/oracle/graalpython/releases/download/graal-25.0.1/graalpy-25.0.1-windows-amd64.zip" },
]
[pyodide]
python_configurations = [
{ identifier = "cp312-pyodide_wasm32", version = "3.12", default_pyodide_version = "0.27.7", node_version = "v22" },
{ identifier = "cp313-pyodide_wasm32", version = "3.13", default_pyodide_version = "0.28.3", node_version = "v22" },
{ identifier = "cp313-pyodide_wasm32", version = "3.13", default_pyodide_version = "0.29.2", node_version = "v22" },
]
[android]
python_configurations = [
{ identifier = "cp313-android_arm64_v8a", version = "3.13", url = "https://repo.maven.apache.org/maven2/com/chaquo/python/python/3.13.7/python-3.13.7-aarch64-linux-android.tar.gz" },
{ identifier = "cp313-android_x86_64", version = "3.13", url = "https://repo.maven.apache.org/maven2/com/chaquo/python/python/3.13.7/python-3.13.7-x86_64-linux-android.tar.gz" },
{ identifier = "cp314-android_arm64_v8a", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-aarch64-linux-android.tar.gz" },
{ identifier = "cp314-android_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.0/python-3.14.0-x86_64-linux-android.tar.gz" },
{ identifier = "cp313-android_arm64_v8a", version = "3.13", url = "https://repo.maven.apache.org/maven2/com/chaquo/python/python/3.13.11/python-3.13.11-aarch64-linux-android.tar.gz" },
{ identifier = "cp313-android_x86_64", version = "3.13", url = "https://repo.maven.apache.org/maven2/com/chaquo/python/python/3.13.11/python-3.13.11-x86_64-linux-android.tar.gz" },
{ identifier = "cp314-android_arm64_v8a", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-aarch64-linux-android.tar.gz" },
{ identifier = "cp314-android_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.2/python-3.14.2-x86_64-linux-android.tar.gz" },
]
[ios]
@@ -13,7 +13,6 @@
},
"enable": {
"enum": [
"cpython-experimental-riscv64",
"cpython-freethreading",
"cpython-prerelease",
"graalpy",
@@ -28,6 +27,21 @@
"description": "cibuildwheel's settings.",
"type": "object",
"properties": {
"audit": {
"description": "Execute a shell command to audit each wheel after all builds complete. Use {wheel} for each wheel path, or {abi3_wheel} to only audit abi3 wheels.",
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"title": "CIBW_AUDIT"
},
"archs": {
"description": "Change the architectures built on your machine by default.",
"oneOf": [
@@ -569,6 +583,39 @@
],
"title": "CIBW_TEST_ENVIRONMENT"
},
"test-runtime": {
"description": "Additional configuration for the test runner",
"oneOf": [
{
"type": "string",
"pattern": "^$"
},
{
"type": "object",
"additionalProperties": false
},
{
"type": "string",
"pattern": "args:"
},
{
"type": "object",
"additionalProperties": false,
"required": [
"args"
],
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
],
"title": "CIBW_TEST_RUNTIME"
},
"overrides": {
"type": "array",
"description": "An overrides array",
@@ -638,6 +685,9 @@
},
"test-environment": {
"$ref": "#/$defs/inherit"
},
"test-runtime": {
"$ref": "#/$defs/inherit"
}
}
},
@@ -748,6 +798,9 @@
},
"test-environment": {
"$ref": "#/properties/test-environment"
},
"test-runtime": {
"$ref": "#/properties/test-runtime"
}
}
}
@@ -876,6 +929,9 @@
},
"test-environment": {
"$ref": "#/properties/test-environment"
},
"test-runtime": {
"$ref": "#/properties/test-runtime"
}
}
},
@@ -936,6 +992,9 @@
},
"test-environment": {
"$ref": "#/properties/test-environment"
},
"test-runtime": {
"$ref": "#/properties/test-runtime"
}
}
},
@@ -1009,6 +1068,9 @@
},
"test-environment": {
"$ref": "#/properties/test-environment"
},
"test-runtime": {
"$ref": "#/properties/test-runtime"
}
}
},
@@ -1069,6 +1131,9 @@
},
"test-environment": {
"$ref": "#/properties/test-environment"
},
"test-runtime": {
"$ref": "#/properties/test-runtime"
}
}
},
@@ -1129,6 +1194,9 @@
},
"test-environment": {
"$ref": "#/properties/test-environment"
},
"test-runtime": {
"$ref": "#/properties/test-runtime"
}
}
},
@@ -1189,6 +1257,9 @@
},
"test-environment": {
"$ref": "#/properties/test-environment"
},
"test-runtime": {
"$ref": "#/properties/test-runtime"
}
}
}
@@ -2,20 +2,20 @@
# nox -s update_constraints
annotated-types==0.7.0
# via pydantic
anyio==4.11.0
anyio==4.12.1
# via httpx
auditwheel-emscripten==0.2.0
auditwheel-emscripten==0.2.1
# via pyodide-build
build==1.2.2.post1
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
certifi==2025.10.5
certifi==2026.1.4
# via
# httpcore
# httpx
# requests
charset-normalizer==3.4.3
charset-normalizer==3.4.4
# via requests
click==8.1.8
# via
@@ -23,7 +23,7 @@ click==8.1.8
# typer
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
h11==0.16.0
# via httpcore
@@ -31,65 +31,62 @@ httpcore==1.0.9
# via httpx
httpx==0.28.1
# via unearth
idna==3.10
idna==3.11
# via
# anyio
# httpx
# requests
leb128==1.0.8
leb128==1.0.9
# via auditwheel-emscripten
markdown-it-py==4.0.0
# via rich
mdurl==0.1.2
# via markdown-it-py
packaging==25.0
packaging==26.0
# via
# auditwheel-emscripten
# build
# pyodide-build
# unearth
pip==25.2
# wheel
pip==25.3
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
platformdirs==4.5.0
platformdirs==4.5.1
# via
# pyodide-build
# virtualenv
pydantic==2.12.0
pydantic==2.12.5
# via
# pyodide-build
# pyodide-lock
pydantic-core==2.41.1
pydantic-core==2.41.5
# via pydantic
pygments==2.19.2
# via rich
pyodide-build==0.30.7
pyodide-build==0.31.2
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
pyodide-cli==0.4.0
pyodide-cli==0.4.2
# via
# auditwheel-emscripten
# pyodide-build
pyodide-lock==0.1.0
pyodide-lock==0.1.1
# via pyodide-build
pyproject-hooks==1.2.0
# via build
requests==2.32.5
# via pyodide-build
resolvelib==1.2.0
resolvelib==1.2.1
# via pyodide-build
rich==14.2.0
rich==14.3.1
# via
# pyodide-build
# pyodide-cli
# typer
ruamel-yaml==0.18.15
ruamel-yaml==0.19.1
# via pyodide-build
ruamel-yaml-clib==0.2.14
# via ruamel-yaml
shellingham==1.5.4
# via typer
sniffio==1.3.1
# via anyio
typer==0.19.2
typer==0.21.1
# via
# auditwheel-emscripten
# pyodide-build
@@ -103,15 +100,15 @@ typing-extensions==4.15.0
# typing-inspection
typing-inspection==0.4.2
# via pydantic
unearth==0.17.5
unearth==0.18.2
# via pyodide-build
urllib3==2.5.0
urllib3==2.6.3
# via requests
virtualenv==20.35.2
virtualenv==20.36.1
# via
# build
# pyodide-build
wheel==0.45.1
wheel==0.46.3
# via
# auditwheel-emscripten
# pyodide-build
@@ -2,20 +2,20 @@
# nox -s update_constraints
annotated-types==0.7.0
# via pydantic
anyio==4.11.0
anyio==4.12.1
# via httpx
auditwheel-emscripten==0.2.0
auditwheel-emscripten==0.2.1
# via pyodide-build
build==1.2.2.post1
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
certifi==2025.10.5
certifi==2026.1.4
# via
# httpcore
# httpx
# requests
charset-normalizer==3.4.3
charset-normalizer==3.4.4
# via requests
click==8.1.8
# via
@@ -23,7 +23,7 @@ click==8.1.8
# typer
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
h11==0.16.0
# via httpcore
@@ -31,65 +31,62 @@ httpcore==1.0.9
# via httpx
httpx==0.28.1
# via unearth
idna==3.10
idna==3.11
# via
# anyio
# httpx
# requests
leb128==1.0.8
leb128==1.0.9
# via auditwheel-emscripten
markdown-it-py==4.0.0
# via rich
mdurl==0.1.2
# via markdown-it-py
packaging==25.0
packaging==26.0
# via
# auditwheel-emscripten
# build
# pyodide-build
# unearth
pip==25.2
# wheel
pip==25.3
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
platformdirs==4.5.0
platformdirs==4.5.1
# via
# pyodide-build
# virtualenv
pydantic==2.12.0
pydantic==2.12.5
# via
# pyodide-build
# pyodide-lock
pydantic-core==2.41.1
pydantic-core==2.41.5
# via pydantic
pygments==2.19.2
# via rich
pyodide-build==0.30.7
pyodide-build==0.31.2
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
pyodide-cli==0.4.0
pyodide-cli==0.4.2
# via
# auditwheel-emscripten
# pyodide-build
pyodide-lock==0.1.0
pyodide-lock==0.1.1
# via pyodide-build
pyproject-hooks==1.2.0
# via build
requests==2.32.5
# via pyodide-build
resolvelib==1.2.0
resolvelib==1.2.1
# via pyodide-build
rich==14.2.0
rich==14.3.1
# via
# pyodide-build
# pyodide-cli
# typer
ruamel-yaml==0.18.15
ruamel-yaml==0.19.1
# via pyodide-build
ruamel-yaml-clib==0.2.14
# via ruamel-yaml
shellingham==1.5.4
# via typer
sniffio==1.3.1
# via anyio
typer==0.19.2
typer==0.21.1
# via
# auditwheel-emscripten
# pyodide-build
@@ -102,15 +99,15 @@ typing-extensions==4.15.0
# typing-inspection
typing-inspection==0.4.2
# via pydantic
unearth==0.17.5
unearth==0.18.2
# via pyodide-build
urllib3==2.5.0
urllib3==2.6.3
# via requests
virtualenv==20.35.2
virtualenv==20.36.1
# via
# build
# pyodide-build
wheel==0.45.1
wheel==0.46.3
# via
# auditwheel-emscripten
# pyodide-build
@@ -1,36 +1,36 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.3.0
build==1.4.0
# via -r cibuildwheel/resources/constraints.in
delocate==0.13.0
# via -r cibuildwheel/resources/constraints.in
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
importlib-metadata==8.7.0
importlib-metadata==8.7.1
# via build
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
pip==25.2
pip==25.3
# via -r cibuildwheel/resources/constraints.in
platformdirs==4.5.0
platformdirs==4.5.1
# via virtualenv
pyproject-hooks==1.2.0
# via build
tomli==2.3.0
tomli==2.4.0
# via build
typing-extensions==4.15.0
# via
# delocate
# virtualenv
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
zipp==3.23.0
# via importlib-metadata
@@ -1,28 +1,28 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.3.0
build==1.4.0
# via -r cibuildwheel/resources/constraints.in
delocate==0.13.0
# via -r cibuildwheel/resources/constraints.in
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
pip==25.2
pip==25.3
# via -r cibuildwheel/resources/constraints.in
platformdirs==4.5.0
platformdirs==4.5.1
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.15.0
# via delocate
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
@@ -1,28 +1,28 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.3.0
build==1.4.0
# via -r cibuildwheel/resources/constraints.in
delocate==0.13.0
# via -r cibuildwheel/resources/constraints.in
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
pip==25.2
pip==25.3
# via -r cibuildwheel/resources/constraints.in
platformdirs==4.5.0
platformdirs==4.5.1
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.15.0
# via delocate
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
@@ -1,28 +1,28 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.3.0
build==1.4.0
# via -r cibuildwheel/resources/constraints.in
delocate==0.13.0
# via -r cibuildwheel/resources/constraints.in
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
pip==25.2
pip==25.3
# via -r cibuildwheel/resources/constraints.in
platformdirs==4.5.0
platformdirs==4.5.1
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.15.0
# via delocate
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
@@ -1,28 +1,28 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.3.0
build==1.4.0
# via -r cibuildwheel/resources/constraints.in
delocate==0.13.0
# via -r cibuildwheel/resources/constraints.in
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
pip==25.2
pip==25.3
# via -r cibuildwheel/resources/constraints.in
platformdirs==4.5.0
platformdirs==4.5.1
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.15.0
# via delocate
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
@@ -1,6 +1,6 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.2.2.post1
# via -r cibuildwheel/resources/constraints.in
@@ -12,9 +12,9 @@ filelock==3.16.1
# via virtualenv
importlib-metadata==8.5.0
# via build
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
@@ -24,13 +24,13 @@ platformdirs==4.3.6
# via virtualenv
pyproject-hooks==1.2.0
# via build
tomli==2.3.0
tomli==2.4.0
# via build
typing-extensions==4.13.2
# via
# delocate
# virtualenv
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
zipp==3.20.2
# via importlib-metadata
@@ -1,8 +1,8 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.3.0
build==1.4.0
# via -r cibuildwheel/resources/constraints.in
delocate==0.13.0
# via -r cibuildwheel/resources/constraints.in
@@ -10,27 +10,27 @@ distlib==0.4.0
# via virtualenv
filelock==3.19.1
# via virtualenv
importlib-metadata==8.7.0
importlib-metadata==8.7.1
# via build
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
pip==25.2
pip==25.3
# via -r cibuildwheel/resources/constraints.in
platformdirs==4.4.0
# via virtualenv
pyproject-hooks==1.2.0
# via build
tomli==2.3.0
tomli==2.4.0
# via build
typing-extensions==4.15.0
# via
# delocate
# virtualenv
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
zipp==3.23.0
# via importlib-metadata
+8 -8
View File
@@ -1,28 +1,28 @@
# This file was autogenerated by uv via the following command:
# nox -s update_constraints
altgraph==0.17.4
altgraph==0.17.5
# via macholib
build==1.3.0
build==1.4.0
# via -r cibuildwheel/resources/constraints.in
delocate==0.13.0
# via -r cibuildwheel/resources/constraints.in
distlib==0.4.0
# via virtualenv
filelock==3.20.0
filelock==3.20.3
# via virtualenv
macholib==1.16.3
macholib==1.16.4
# via delocate
packaging==25.0
packaging==26.0
# via
# build
# delocate
pip==25.2
pip==25.3
# via -r cibuildwheel/resources/constraints.in
platformdirs==4.5.0
platformdirs==4.5.1
# via virtualenv
pyproject-hooks==1.2.0
# via build
typing-extensions==4.15.0
# via delocate
virtualenv==20.35.2
virtualenv==20.36.1
# via -r cibuildwheel/resources/constraints.in
+2
View File
@@ -5,6 +5,7 @@ test-skip = ""
enable = []
archs = ["auto"]
audit = ""
build-frontend = "default"
config-settings = {}
dependency-versions = "pinned"
@@ -25,6 +26,7 @@ test-requires = []
test-extras = []
test-groups = []
test-environment = {}
test-runtime = {}
container-engine = "docker"
+3 -2
View File
@@ -1,3 +1,4 @@
url = "https://nodejs.org/dist/"
v22 = "v22.20.0"
v20 = "v20.19.5"
v24 = "v24.12.0"
v22 = "v22.21.1"
v20 = "v20.19.6"
+34 -33
View File
@@ -1,53 +1,54 @@
[x86_64]
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.10.10-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2026.01.04-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2026.01.04-1
[i686]
manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_i686:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_i686:2025.10.10-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_i686:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_i686:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_i686:2026.01.04-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2026.01.04-1
[aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.10.10-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2026.01.04-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2026.01.04-1
[ppc64le]
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_ppc64le:2025.10.10-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_ppc64le:2026.01.04-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2026.01.04-1
[s390x]
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_s390x:2025.10.10-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_s390x:2026.01.04-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2026.01.04-1
[pypy_x86_64]
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2026.01.04-1
[pypy_i686]
manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_i686:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_i686:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_i686:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_i686:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_i686:2026.01.04-1
[pypy_aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.10.10-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.10.10-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.10.10-1
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2026.01.04-1
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2026.01.04-1
manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2026.01.04-1
[armv7l]
manylinux_2_31 = quay.io/pypa/manylinux_2_31_armv7l:2025.10.10-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_armv7l:2025.10.10-1
manylinux_2_31 = quay.io/pypa/manylinux_2_31_armv7l:2026.01.04-1
manylinux_2_35 = quay.io/pypa/manylinux_2_35_armv7l:2026.01.04-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_armv7l:2026.01.04-1
[riscv64]
manylinux_2_39 = quay.io/pypa/manylinux_2_39_riscv64:2025.10.10-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_riscv64:2025.10.10-1
manylinux_2_39 = quay.io/pypa/manylinux_2_39_riscv64:2026.01.04-1
musllinux_1_2 = quay.io/pypa/musllinux_1_2_riscv64:2026.01.04-1
@@ -1,479 +1,483 @@
{
"releases": [
{
"tag": "20251010",
"tag": "20251217",
"assets": [
{
"name": "cpython-3.10.19+20251010-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-aarch64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-aarch64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-aarch64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-aarch64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-aarch64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-aarch64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-i686-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-i686-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-riscv64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-riscv64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-s390x-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-s390x-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.10.19+20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.10.19%2B20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.10.19+20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.10.19%2B20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-aarch64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-aarch64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-aarch64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-aarch64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-aarch64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-aarch64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-aarch64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-aarch64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-i686-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-i686-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-riscv64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-riscv64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-s390x-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-s390x-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.11.14+20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.11.14%2B20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.11.14+20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.11.14%2B20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-aarch64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-aarch64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-aarch64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-aarch64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-aarch64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-aarch64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-aarch64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-aarch64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-i686-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-i686-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-riscv64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-riscv64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-s390x-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-s390x-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.12.12+20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.12.12%2B20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.12.12+20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.12.12%2B20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-aarch64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-aarch64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-aarch64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-aarch64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-aarch64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-aarch64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-aarch64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-aarch64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-i686-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-i686-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-riscv64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-riscv64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-s390x-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-s390x-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.13.8+20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.13.8%2B20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.13.11+20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.13.11%2B20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-aarch64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-aarch64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-aarch64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-aarch64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-aarch64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-aarch64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-aarch64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-aarch64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-i686-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-i686-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-riscv64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-riscv64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-s390x-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-s390x-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.14.0+20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.14.0%2B20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.14.2+20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.14.2%2B20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-aarch64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-aarch64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-aarch64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-aarch64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-aarch64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-aarch64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-aarch64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-aarch64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-aarch64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-armv7-unknown-linux-gnueabi-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-aarch64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-aarch64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-armv7-unknown-linux-gnueabi-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-i686-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-armv7-unknown-linux-gnueabihf-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-ppc64le-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-i686-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-i686-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-riscv64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-ppc64le-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-s390x-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-riscv64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-riscv64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64-apple-darwin-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-s390x-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-s390x-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64-pc-windows-msvc-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64-apple-darwin-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64-apple-darwin-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64-pc-windows-msvc-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64-pc-windows-msvc-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64_v2-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64_v2-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64_v3-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64_v3-unknown-linux-musl-install_only.tar.gz"
},
{
"name": "cpython-3.9.24+20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251010/cpython-3.9.24%2B20251010-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
"name": "cpython-3.15.0a3+20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64_v4-unknown-linux-gnu-install_only.tar.gz"
},
{
"name": "cpython-3.15.0a3+20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz",
"url": "https://github.com/astral-sh/python-build-standalone/releases/download/20251217/cpython-3.15.0a3%2B20251217-x86_64_v4-unknown-linux-musl-install_only.tar.gz"
}
]
}
+1 -1
View File
@@ -1 +1 @@
default = { version = "20.35.2", url = "https://github.com/pypa/get-virtualenv/releases/download/20.35.2/virtualenv.pyz" }
default = { version = "20.35.4", url = "https://github.com/pypa/get-virtualenv/releases/download/20.35.4/virtualenv.pyz" }
+1 -2
View File
@@ -29,7 +29,6 @@ class EnableGroup(StrEnum):
Groups of build selectors that are not enabled by default.
"""
CPythonExperimentalRiscV64 = "cpython-experimental-riscv64"
CPythonFreeThreading = "cpython-freethreading"
CPythonPrerelease = "cpython-prerelease"
GraalPy = "graalpy"
@@ -39,7 +38,7 @@ class EnableGroup(StrEnum):
@classmethod
def all_groups(cls) -> frozenset["EnableGroup"]:
return frozenset(set(cls) - {cls.CPythonExperimentalRiscV64})
return frozenset(cls)
@classmethod
def parse_option_value(cls, value: str) -> frozenset["EnableGroup"]:
+1 -1
View File
@@ -72,7 +72,7 @@ def call(
if not capture_stdout:
return None
sys.stderr.write(result.stderr)
return typing.cast(str, result.stdout)
return typing.cast("str", result.stdout)
def shell(
+1 -28
View File
@@ -1,5 +1,5 @@
import shlex
from collections.abc import Mapping, MutableMapping, Sequence
from collections.abc import Mapping, Sequence
from dataclasses import dataclass, field
from pathlib import Path, PurePath
from typing import Any, Literal, Self, TypeVar
@@ -178,30 +178,3 @@ def find_compatible_wheel(wheels: Sequence[T], identifier: str) -> T | None:
return wheel
return None
def combine_constraints(
env: MutableMapping[str, str], /, constraints_path: Path, tmp_dir: Path | None
) -> None:
"""
This will workaround a bug in pip<=21.1.1 or uv<=0.2.0 if a tmp_dir is given.
If set to None, this will use the modern URI method.
"""
if tmp_dir:
if " " in str(constraints_path):
assert " " not in str(tmp_dir)
tmp_file = tmp_dir / "constraints.txt"
tmp_file.write_bytes(constraints_path.read_bytes())
constraints_path = tmp_file
our_constraints = str(constraints_path)
else:
our_constraints = (
constraints_path.as_uri() if " " in str(constraints_path) else str(constraints_path)
)
user_constraints = env.get("PIP_CONSTRAINT")
env["UV_CONSTRAINT"] = env["PIP_CONSTRAINT"] = " ".join(
c for c in [our_constraints, user_constraints] if c
)
+1 -1
View File
@@ -28,7 +28,7 @@ class PythonBuildStandaloneReleaseData(typing.TypedDict):
@functools.cache
def get_python_build_standalone_release_data() -> PythonBuildStandaloneReleaseData:
with open(PYTHON_BUILD_STANDALONE_RELEASES, "rb") as f:
return typing.cast(PythonBuildStandaloneReleaseData, json.load(f))
return typing.cast("PythonBuildStandaloneReleaseData", json.load(f))
class PythonBuildStandaloneError(Exception):
+20
View File
@@ -4,6 +4,26 @@ title: Changelog
# Changelog
### v3.3.1
_5 January 2026_
- 🛠 Update dependencies and container pins, including updating to CPython 3.14.2. (#2708)
### v3.3.0
_12 November 2025_
- 🐛 Fix an incompatibility with Docker v29 (#2660)
- ✨ Adds `test-runtime` option, to customise how tests on simulated/emulated environments are run (#2636)
- ✨ Adds support for new `manylinux_2_35` images on 32-bit ARM `armv7l`, offering better C++20 compatibility (#2656)
- ✨ `build[uv]` is now supported on Android (#2587)
- ✨ You can now install extras (such as `uv`) with a simple option on the GitHub Action (#2630)
- ✨ `{project}` and `{package}` placeholders are now supported in `repair-wheel-command` (#2589)
- 🛠 The versions set with `dependency-versions` no longer constrain packages specified by your `build-system.requires`. Previously, on platforms other than Linux, the constraints in this option would remain in the environment during the build. This has been tidied up make behaviour more consistent between platforms, and to prevent version conflicts. (#2583)
- 🛠 Improve the handling of `test-command` on Android, enabling more options to be passed (#2590)
- 📚 Docs improvements (#2618)
### v3.2.1
_12 October 2025_
+3 -17
View File
@@ -23,7 +23,9 @@ To build Linux, macOS, and Windows wheels using GitHub Actions, create a `.githu
Use `env:` to pass [build options](options.md) and `with:` to set
`package-dir: .`, `output-dir: wheelhouse` and `config-file: ''`
locations (those values are the defaults).
locations (those values are the defaults). You can also pass a
comma-separated list of extras to install additional packages.
For example, `extras: "uv"` to install UV into the virtual environment.
!!! tab "pipx"
The GitHub Actions runners have pipx installed, so you can easily build in
@@ -70,22 +72,6 @@ Commit this file, enable building of your repo on Azure Pipelines, and push.
Wheels will be stored for you and available through the Pipelines interface. For more info on this file, check out the [docs](https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema).
### Travis CI [linux/windows] {: #travis-ci}
To build Linux and Windows wheels on Travis CI, create a `.travis.yml` file in your repo.
> .travis.yml
```yaml
{% include "../examples/travis-ci-minimal.yml" %}
```
Commit this file, enable building of your repo on Travis CI, and push.
Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](deliver-to-pypi.md). For more info on `.travis.yml`, check out the [docs](https://docs.travis-ci.com/).
[`examples/travis-ci-deploy.yml`](https://github.com/pypa/cibuildwheel/blob/main/examples/travis-ci-deploy.yml) extends this minimal example with a demonstration of how to automatically upload the built wheels to PyPI.
### CircleCI [linux/mac] {: #circleci}
To build Linux and Mac wheels on CircleCI, create a `.circleci/config.yml` file in your repo,
-11
View File
@@ -30,17 +30,6 @@ cibuildwheel to run tests, add the following YAML to your CI config file:
CIBW_TEST_COMMAND: "pytest {project}/tests"
```
!!! tab "Travis CI"
> .travis.yml ([docs](https://docs.travis-ci.com/user/environment-variables/))
```yaml
env:
global:
- CIBW_TEST_REQUIRES=pytest
- CIBW_TEST_COMMAND="pytest {project}/tests"
```
!!! tab "CircleCI"
> .circleci/config.yml ([docs](https://circleci.com/docs/2.0/configuration-reference/#environment))
+2 -2
View File
@@ -172,13 +172,13 @@
- name: pyzmq
gh: zeromq/pyzmq
ci: [github, circleci]
ci: [github]
os: [windows, apple, linux]
ci_config: .github/workflows/wheels.yml
notes: |
Python bindings for zeromq, the networking library.
Uses Cython on CPython and CFFI on PyPy.
ARM wheels for linux are built natively on CircleCI.
ARM wheels for linux are built natively on GitHub Actions.
- name: python-rapidjson
gh: python-rapidjson/python-rapidjson
-6
View File
@@ -71,12 +71,6 @@ for an example configuration that automatically uploads wheels to PyPI. Also see
[scikit-hep.org/developer/gha_wheels](https://scikit-hep.org/developer/gha_wheels)
for a complete guide.
### TravisCI
See
[`examples/travis-ci-deploy.yml`](https://github.com/pypa/cibuildwheel/blob/main/examples/travis-ci-deploy.yml)
for an example configuration.
## Manual method
On your development machine, install [pipx](https://pipx.pypa.io/) and do the following:
+3 -3
View File
@@ -110,7 +110,7 @@ There are two suggested methods for keeping cibuildwheel up to date that instead
If you use GitHub Actions for builds, you can use cibuildwheel as an action:
```yaml
uses: pypa/cibuildwheel@v3.2.1
uses: pypa/cibuildwheel@v3.3.1
```
This is a composite step that just runs cibuildwheel using pipx. You can set command-line options as `with:` parameters, and use `env:` as normal.
@@ -132,7 +132,7 @@ The second option, and the only one that supports other CI systems, is using a `
```bash
# requirements-cibw.txt
cibuildwheel==3.2.1
cibuildwheel==3.3.1
```
Then your install step would have `python -m pip install -r requirements-cibw.txt` in it. Your `.github/dependabot.yml` file could look like this:
@@ -297,7 +297,7 @@ Solutions to this vary, but the simplest is to use pipx:
# most runners have pipx preinstalled, but in case you don't
python3 -m pip install pipx
pipx run cibuildwheel==3.2.1 --output-dir wheelhouse
pipx run cibuildwheel==3.3.1 --output-dir wheelhouse
pipx run twine upload wheelhouse/*.whl
```
+1 -1
View File
@@ -11,7 +11,7 @@ import rich.text
def define_env(env: Any) -> None:
"Hook function for mkdocs-macros"
@env.macro # type: ignore[misc]
@env.macro # type: ignore[untyped-decorator]
def subprocess_run(*args: str) -> str:
"Run a subprocess and return the stdout"
env = os.environ.copy()
+52 -13
View File
@@ -474,12 +474,12 @@ You can use "build\[uv\]", which will use an external [uv][] everywhere
possible, both through `--installer=uv` passed to build, as well as when making
all build and test environments. This will generally speed up cibuildwheel.
Make sure you have an external uv on Windows and macOS, either by
pre-installing it, or installing cibuildwheel with the uv extra,
`cibuildwheel[uv]`. uv currently does not support Windows on ARM,
musllinux on s390x, Android, or iOS. Legacy dependencies like
setuptools on Python < 3.12 and pip are not installed if using uv.
pre-installing it, or installing cibuildwheel with the `uv` extra, which is
possible by manually passing `cibuildwheel[uv]` to installers or by using the
`extras` option in the [cibuildwheel action](ci-services.md#github-actions).
uv currently does not support iOS or musllinux on s390x, ppc64le and riscv64.
On Android and Pyodide, only "build" is supported.
On Android and Pyodide, the "pip" frontend is not supported.
You can specify extra arguments to pass to the build frontend using the
optional `args` option.
@@ -572,6 +572,7 @@ A list of environment variables to set during the build and test phases. Bash sy
You must use this variable to pass variables to Linux builds, since they execute in a container. It also works for the other platforms.
You can use `$PATH` syntax to insert other variables, or the `$(pwd)` syntax to insert the output of other shell commands.
Variables are evaluated in the order they appear. Any variable referenced before it is set will evaluate to an empty string.
To specify more than one environment variable, separate the assignments by spaces.
@@ -757,9 +758,9 @@ Platform-specific environment variables also available:<br/>
here.](https://yaml-multiline.info).
Note that `manylinux_2_31` builds occur inside a Debian derivative docker
Note that `manylinux_2_31`/`manylinux_2_35` builds occur inside a Debian derivative docker
container, where `manylinux2014` builds occur inside a CentOS one. So for
`manylinux_2_31` the `before-all` command must use `apt-get -y`
`manylinux_2_31`/`manylinux_2_35` the `before-all` command must use `apt-get -y`
instead.
### `before-build` {: #before-build env-var toml}
@@ -905,6 +906,8 @@ The following placeholders must be used inside the command and will be replaced
- `{dest_dir}` for the absolute path of the directory where to create the repaired wheel
- `{delocate_archs}` (macOS only) comma-separated list of architectures in the wheel.
You can use the `{package}` or `{project}` placeholders in your `repair-wheel-command` to refer to the package being built or the project root, respectively.
The command is run in a shell, so you can run multiple commands like `cmd1 && cmd2`.
Platform-specific environment variables are also available:<br/>
@@ -1034,7 +1037,7 @@ Set the Docker image to be used for building [manylinux / musllinux](https://git
For `manylinux-*-image`, except `manylinux-armv7l-image` and `manylinux-riscv64-image`, the value of this option can either be set to `manylinux2014`, `manylinux_2_28` or `manylinux_2_34` to use a pinned version of the [official manylinux images](https://github.com/pypa/manylinux). Alternatively, set these options to any other valid Docker image name.
For `manylinux-armv7l-image`, the value of this option can either be set to `manylinux_2_31` or a custom image. Support is experimental for now. The `manylinux_2_31` value is only available for `armv7`.
For `manylinux-armv7l-image`, the value of this option can either be set to `manylinux_2_31`, `manylinux_2_35` or a custom image. Support is experimental for now. The `manylinux_2_31` and `manylinux_2_35` values are only available for `armv7`.
For `manylinux-riscv64-image`, the value of this option can either be set to `manylinux_2_39` or a custom image. Support is experimental for now. The `manylinux_2_39` value is only available for `riscv64`.
@@ -1317,7 +1320,7 @@ The available Pyodide versions are determined by the version of `pyodide-build`
### `test-command` {: #test-command env-var toml}
> The command to test each built wheel
Shell command to run tests after the build. The wheel will be installed
Command to run tests after the build. The wheel will be installed
automatically and available for import from the tests. If this variable is not
set, your wheel will not be installed after building.
@@ -1345,11 +1348,12 @@ tree. To access your test code, you have a couple of options:
On all platforms other than Android and iOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`.
On Android and iOS, the command is parsed by `shlex.split`, and is required to
be in one of the following forms:
On Android and iOS, the command is parsed by `shlex.split`, and must be a Python
command:
* `python -c command ...` (Android only)
* `python -m module-name ...`
* On Android, the command must must begin with `python` or `python3`, and contain `-m`
or `-c`.
* On iOS, the command must begin with `python -m`.
Platform-specific environment variables are also available:<br/>
`CIBW_TEST_COMMAND_MACOS` | `CIBW_TEST_COMMAND_WINDOWS` | `CIBW_TEST_COMMAND_LINUX` | `CIBW_TEST_COMMAND_ANDROID` | `CIBW_TEST_COMMAND_IOS` | `CIBW_TEST_COMMAND_PYODIDE`
@@ -1668,6 +1672,41 @@ Platform-specific environment variables are also available:<br/>
CIBW_TEST_ENVIRONMENT: PYTHONSAFEPATH=1
```
### `test-runtime` {: #test-runtime toml env-var }
> Controls how the tests will be executed.
On desktop environments, the tests are executed on the same machine/container as the wheel was built. However on Android and iOS, the tests are run inside a virtual machine a simulator or emulator representing the target.
For these embedded platforms, a testbed project is used to run the tests. The `test-runtime` setting can define an `args` key that defines additional arguments that will be used when starting the testbed project.
Platform-specific environment variables are also available:<br/>
`CIBW_TEST_RUNTIME_ANDROID` |`CIBW_TEST_RUNTIME_IOS`
#### Examples
!!! tab examples "pyproject.toml"
```toml
[tool.cibuildwheel.ios]
# Run the tests on an iPhone 16e simulator running iOS 18.5.
test-runtime = { args = ["--simulator='iPhone 16e,OS=18.5'"] }
[tool.cibuildwheel.android]
# Run the Android tests on the minimum supported Android version.
test-runtime = { args = ["--managed", "minVersion"] }
```
!!! tab examples "Environment variables"
```yaml
# Run the tests on an iPhone 16e simulator running iOS 18.5.
CIBW_TEST_RUNTIME_IOS: "args: --simulator='iPhone 16e,OS=18.5'"
# Run the Android tests on the minimum supported Android version.
CIBW_TEST_RUNTIME_ANDROID: "args: --managed minVersion"
```
## Debugging
+6 -2
View File
@@ -23,7 +23,7 @@ The only side effect to your system will be docker images being pulled.
Linux wheels are built in [`manylinux`/`musllinux` containers](https://github.com/pypa/manylinux) to provide binary compatible wheels on Linux, according to [PEP 600](https://www.python.org/dev/peps/pep-0600/) / [PEP 656](https://www.python.org/dev/peps/pep-0656/). Because of this, when building with `cibuildwheel` on Linux, a few things should be taken into account:
- Programs and libraries are not installed on the CI runner host, but rather should be installed inside the container - using `yum` for `manylinux2014`, `apt-get` for `manylinux_2_31`, `dnf` for `manylinux_2_28` and `apk` for `musllinux_1_1` or `musllinux_1_2`, or manually. The same goes for environment variables that are potentially needed to customize the wheel building.
- Programs and libraries are not installed on the CI runner host, but rather should be installed inside the container - using `yum` for `manylinux2014`, `apt-get` for `manylinux_2_31` or `manylinux_2_35`, `dnf` for `manylinux_2_28` and `apk` for `musllinux_1_1` or `musllinux_1_2`, or manually. The same goes for environment variables that are potentially needed to customize the wheel building.
`cibuildwheel` supports this by providing the [`environment`](options.md#environment) and [`before-all`](options.md#before-all) options to setup the build environment inside the running container.
@@ -233,6 +233,8 @@ machine for example, if you're building on an ARM64 machine, then you can te
ARM64 wheel. Wheels of other architectures can still be built, but testing will
automatically be skipped.
Any arguments specified using [`test-runtime`](options.md#test-runtime) will be passed as arguments to the Python script that starts the [testbed project](https://github.com/python/cpython/blob/main/Android/README.md#testing). cibuildwheel will automatically start the testbed project with `--site-packages` and `--cwd` arguments matching your test environment, as well as enabling verbose output with `-v` if [`build-verbosity`](options.md#build-verbosity) is enabled. The most common additional arguments to use will be `--managed minVersion` or `--managed maxVersion`, specifying the use of a managed Android emulator with the minimum or maximum supported Android version; or `--connected <serial>`, specifying the use of an existing booted Android emulator or device. By default, the testbed project will run with `--managed maxVersion`.
Running an emulator requires the build machine to either be bare-metal or support
nested virtualization. CI platforms known to meet this requirement are:
@@ -320,4 +322,6 @@ If tests have been configured, the test suite will be executed on the simulator
The iOS test environment can't support running shell scripts, so the [`test-command`](options.md#test-command) value must be specified as if it were a command line being passed to `python -m ...`.
The test process uses the same testbed used by CPython itself to run the CPython test suite. It is an Xcode project that has been configured to have a single Xcode "XCUnit" test - the result of which reports the success or failure of running `python -m <test-command>`.
The test process uses the [same testbed used by CPython itself](https://github.com/python/cpython/tree/main/Apple/iOS#testing-python-on-ios) to run the CPython test suite. It is an Xcode project that has been configured to have a single Xcode "XCUnit" test - the result of which reports the success or failure of running `python -m <test-command>`.
Any arguments specified using [`test-runtime`](options.md#test-runtime) will be passed as arguments to the Python script that starts the testbed project. The testbed project will be started with `-v` enabling verbose output if [`build-verbosity`](options.md#build-verbosity) is enabled; the most common additional argument to use will be `--simulator`, which allows the specification of a specific device or iOS version for the test simulator. By default, the testbed project will attempt to find an "SE class" simulator (i.e., an iPhone SE, iPhone 16e, or similar), running the newest iOS version available.
+29 -29
View File
@@ -12,8 +12,8 @@ title: Working examples
| [duckdb][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | DuckDB is an analytical in-process SQL database management system |
| [pytorch-fairseq][] | ![github icon][] | ![apple icon][] ![linux icon][] | Facebook AI Research Sequence-to-Sequence Toolkit written in Python. |
| [NumPy][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The fundamental package for scientific computing with Python. |
| [Tornado][] | ![github icon][] | ![linux icon][] ![apple icon][] ![windows icon][] | Tornado is a Python web framework and asynchronous networking library. Uses stable ABI for a small C extension. |
| [NCNN][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | ncnn is a high-performance neural network inference framework optimized for the mobile platform |
| [Tornado][] | ![github icon][] | ![linux icon][] ![apple icon][] ![windows icon][] | Tornado is a Python web framework and asynchronous networking library. Uses stable ABI for a small C extension. |
| [Matplotlib][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The venerable Matplotlib, a Python library with C++ portions |
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | The compiled version of MyPy using MyPyC. |
| [Prophet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth. |
@@ -24,15 +24,15 @@ title: Working examples
| [psutil][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Cross-platform lib for process and system monitoring in Python |
| [Google Benchmark][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A microbenchmark support library |
| [falcon][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Falcon is a no-magic ASGI/WSGI API and microservices framework; it uses cibuildwheel for (optional) Cython extensions. |
| [vaex][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Out-of-Core hybrid Apache Arrow/NumPy DataFrame for Python, ML, visualization and exploration of big tabular data at a billion rows per second 🚀 |
| [PyGame][] | ![github icon][] | ![apple icon][] ![linux icon][] | 🐍🎮 pygame (the library) is a Free and Open Source python programming language library for making multimedia applications like games built on top of the excellent SDL library. C, Python, Native, OpenGL. |
| [vaex][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Out-of-Core hybrid Apache Arrow/NumPy DataFrame for Python, ML, visualization and exploration of big tabular data at a billion rows per second 🚀 |
| [Apache Beam][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Apache Beam is a unified programming model for Batch and Streaming data processing. |
| [asyncpg][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A fast PostgreSQL Database Client Library for Python/asyncio. |
| [cmake][] | ![github icon][] ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Multitagged binary builds for all supported platforms, using cibw 2 config configuration. |
| [pyinstrument][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python profiler with a C extension. No external dependencies. |
| [scikit-image][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Image processing library. Uses cibuildwheel to build and test a project that uses Cython with platform-native code. |
| [PyOxidizer][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A modern Python application packaging and distribution tool |
| [cvxpy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A Python-embedded modeling language for convex optimization problems. |
| [PyOxidizer][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A modern Python application packaging and distribution tool |
| [twisted-iocpsupport][] | ![github icon][] | ![windows icon][] | A submodule of Twisted that hooks into native C APIs using Cython. |
| [pedalboard][] | ![github icon][] | ![windows icon][] ![linux icon][] ![apple icon][] | A Python library for working with audio data and audio plugins by wrapping the [JUCE](https://github.com/juce-framework/JUCE/) C++ framework. Uses cibuildwheel to deploy on as many operating systems and Python versions as possible with only one dependency (any NumPy). |
| [River][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | 🌊 Online machine learning in Python |
@@ -42,7 +42,7 @@ title: Working examples
| [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
| [UltraJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Ultra fast JSON decoder and encoder written in C with Python bindings |
| [CTranslate2][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes libraries from the [Intel oneAPI toolkit](https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit.html) and CUDA kernels compiled for multiple GPU architectures. |
| [pyzmq][] | ![github icon][] ![circleci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python bindings for zeromq, the networking library. Uses Cython on CPython and CFFI on PyPy. ARM wheels for linux are built natively on CircleCI. |
| [pyzmq][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python bindings for zeromq, the networking library. Uses Cython on CPython and CFFI on PyPy. ARM wheels for linux are built natively on GitHub Actions. |
| [Implicit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes GPU support for linux wheels |
| [tinyobjloader][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Tiny but powerful single file wavefront obj loader |
| [vispy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Main repository for Vispy |
@@ -54,38 +54,38 @@ title: Working examples
| [pikepdf][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python library for reading and writing PDF, powered by QPDF |
| [numexpr][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast numerical array expression evaluator for Python, NumPy, Pandas, PyTables and more |
| [Wrapt][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python module for decorators, wrappers and monkey patching. |
| [Psycopg 3][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A modern implementation of a PostgreSQL adapter for Python |
| [h5py][] | ![azurepipelines icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | HDF5 for Python -- The h5py package is a Pythonic interface to the HDF5 binary data format. |
| [envd][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A machine learning development environment build tool |
| [Psycopg 3][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A modern implementation of a PostgreSQL adapter for Python |
| [OpenColorIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A color management framework for visual effects and animation. |
| [ruptures][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Extensive Cython + NumPy [pyproject.toml](https://github.com/deepcharles/ruptures/blob/master/pyproject.toml) example. |
| [aioquic][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | QUIC and HTTP/3 implementation in Python |
| [SimpleJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | simplejson is a simple, fast, extensible JSON encoder/decoder for Python |
| [OpenTimelineIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Open Source API and interchange format for editorial timeline information. |
| [SimpleJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | simplejson is a simple, fast, extensible JSON encoder/decoder for Python |
| [PyTables][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python package to manage extremely large amounts of data |
| [google neuroglancer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | WebGL-based viewer for volumetric data |
| [Parselmouth][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python interface to the Praat software package, using pybind11, C++17 and CMake, with the core Praat static library built only once and shared between wheels. |
| [AutoPy][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
| [DeepForest][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | An Efficient, Scalable and Optimized Python Framework for Deep Forest (2021.2.1) |
| [H3-py][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for H3, a hierarchical hexagonal geospatial indexing system |
| [DeepForest][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | An Efficient, Scalable and Optimized Python Framework for Deep Forest (2021.2.1) |
| [time-machine][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Time mocking library using only the CPython C API. |
| [mosec][] | ![github icon][] | ![linux icon][] ![apple icon][] | A machine learning model serving framework powered by Rust |
| [Picologging][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A high-performance logging library for Python. |
| [pybind11 cmake_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a CMake-based build system |
| [markupsafe][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Safely add untrusted strings to HTML/XML markup. |
| [pybind11 cmake_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a CMake-based build system |
| [Rtree][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Rtree: spatial index for Python GIS |
| [KDEpy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Kernel Density Estimation in Python |
| [dd-trace-py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Uses custom alternate arch emulation on GitHub |
| [tgcalls][] | ![github icon][] | ![apple icon][] ![windows icon][] | Python `pybind11` binding to Telegram's WebRTC library with third party dependencies like `OpenSSL`, `MozJPEG`, `FFmpeg`, etc. |
| [pybind11 python_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a Python-based build system |
| [sourmash][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Quickly search, compare, and analyze genomic and metagenomic data sets. |
| [python-rapidjson][] | ![travisci icon][] ![gitlab icon][] | ![windows icon][] ![linux icon][] | Python wrapper around rapidjson |
| [pybind11 python_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a Python-based build system |
| [abess][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A fast best-subset selection library. It uses cibuildwheel to build a large project with C++ extensions. |
| [python-snappy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for the snappy google library |
| [jq.py][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Python bindings for jq |
| [cyvcf2][] | ![github icon][] | ![apple icon][] ![linux icon][] | cython + htslib == fast VCF and BCF processing |
| [matrixprofile][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python 3 library making time series data mining tasks, utilizing matrix profile algorithms, accessible to everyone. |
| [Confluent client for Kafka][] | ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | setup in `tools/wheels/build-wheels.bat` |
| [matrixprofile][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python 3 library making time series data mining tasks, utilizing matrix profile algorithms, accessible to everyone. |
| [Tokenizer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast and customizable text tokenization library with BPE and SentencePiece support |
| [iminuit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Jupyter-friendly Python interface for C++ MINUIT2 |
| [pillow-heif][] | ![github icon][] ![cirrusci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Bindings to libheif library with third party dependencies. Fully automated CI for tests and publishing including Apple Silicon builds. |
@@ -96,9 +96,9 @@ title: Working examples
| [power-grid-model][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python/C++ library for distribution power system analysis |
| [streaming-form-data][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Streaming parser for multipart/form-data written in Cython |
| [pybase64][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast Base64 encoding/decoding in Python |
| [Imagecodecs (fork)][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] | Over 20 external dependencies in compiled libraries, custom docker image, `libomp`, `openblas` and `install_name_tool` for macOS. |
| [bx-python][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | A library that includes Cython extensions. |
| [boost-histogram][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Supports full range of wheels, including PyPy and alternate archs. |
| [Imagecodecs (fork)][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] | Over 20 external dependencies in compiled libraries, custom docker image, `libomp`, `openblas` and `install_name_tool` for macOS. |
| [Python-WebRTC][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | a Python extension that provides bindings to WebRTC M92 |
| [pybind11 scikit_build_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | An example combining scikit-build and pybind11 |
| [fathon][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | python package for DFA (Detrended Fluctuation Analysis) and related algorithms |
@@ -109,13 +109,13 @@ title: Working examples
| [etebase-py][] | ![travisci icon][] | ![linux icon][] | Python bindings to a Rust library using `setuptools-rust`, and `sccache` for improved speed. |
| [cf-units][] | ![github icon][] | ![apple icon][] ![linux icon][] | Units of measure as required by the Climate and Forecast (CF) Metadata Conventions |
| [numpythia][] | ![github icon][] | ![apple icon][] ![linux icon][] | The interface between PYTHIA and NumPy |
| [pyjet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The interface between FastJet and NumPy |
| [SiPM][] | ![github icon][] | ![apple icon][] ![linux icon][] | High performance library for SiPM detectors simulation using C++17, OpenMP and AVX2 intrinsics. |
| [ril][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A python binding to Rust Imaging library using maturin and Pyo3, utilizes Github Action cache to improve speed. Builds abi3 wheels. |
| [aalink][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Async Python interface for Ableton Link. |
| [SiPM][] | ![github icon][] | ![apple icon][] ![linux icon][] | High performance library for SiPM detectors simulation using C++17, OpenMP and AVX2 intrinsics. |
| [pyjet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The interface between FastJet and NumPy |
| [ril][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A python binding to Rust Imaging library using maturin and Pyo3, utilizes Github Action cache to improve speed. Builds abi3 wheels. |
| [GSD][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Cython and NumPy project with 64-bit wheels. |
| [CorrectionLib][] | ![github icon][] | ![apple icon][] ![linux icon][] | Structured JSON powered correction library for HEP, designed for the CMS experiment at CERN. |
| [werpy][] | ![github icon][] | ![windows icon][] ![linux icon][] ![apple icon][] | An ultra-fast python package using optimized dynamic programming to compute the Word Error Rate (WER). |
| [CorrectionLib][] | ![github icon][] | ![apple icon][] ![linux icon][] | Structured JSON powered correction library for HEP, designed for the CMS experiment at CERN. |
| [xmlstarlet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python 3.6+ CFFI bindings with true MSVC build. |
| [pybind11 cross build example][] | ![github icon][] ![gitlab icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Same as pybind11 cmake_example but used to demo Linux ARM + Windows + macOS builds on GitLab |
@@ -123,8 +123,8 @@ title: Working examples
[duckdb]: https://github.com/duckdb/duckdb
[pytorch-fairseq]: https://github.com/facebookresearch/fairseq
[NumPy]: https://github.com/numpy/numpy
[Tornado]: https://github.com/tornadoweb/tornado
[NCNN]: https://github.com/Tencent/ncnn
[Tornado]: https://github.com/tornadoweb/tornado
[Matplotlib]: https://github.com/matplotlib/matplotlib
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
[Prophet]: https://github.com/facebook/prophet
@@ -135,15 +135,15 @@ title: Working examples
[psutil]: https://github.com/giampaolo/psutil
[Google Benchmark]: https://github.com/google/benchmark
[falcon]: https://github.com/falconry/falcon
[vaex]: https://github.com/vaexio/vaex
[PyGame]: https://github.com/pygame/pygame
[vaex]: https://github.com/vaexio/vaex
[Apache Beam]: https://github.com/apache/beam
[asyncpg]: https://github.com/MagicStack/asyncpg
[cmake]: https://github.com/scikit-build/cmake-python-distributions
[pyinstrument]: https://github.com/joerick/pyinstrument
[scikit-image]: https://github.com/scikit-image/scikit-image
[PyOxidizer]: https://github.com/indygreg/PyOxidizer
[cvxpy]: https://github.com/cvxpy/cvxpy
[PyOxidizer]: https://github.com/indygreg/PyOxidizer
[twisted-iocpsupport]: https://github.com/twisted/twisted-iocpsupport
[pedalboard]: https://github.com/spotify/pedalboard
[River]: https://github.com/online-ml/river
@@ -165,38 +165,38 @@ title: Working examples
[pikepdf]: https://github.com/pikepdf/pikepdf
[numexpr]: https://github.com/pydata/numexpr
[Wrapt]: https://github.com/GrahamDumpleton/wrapt
[Psycopg 3]: https://github.com/psycopg/psycopg
[h5py]: https://github.com/h5py/h5py
[envd]: https://github.com/tensorchord/envd
[Psycopg 3]: https://github.com/psycopg/psycopg
[OpenColorIO]: https://github.com/AcademySoftwareFoundation/OpenColorIO
[ruptures]: https://github.com/deepcharles/ruptures
[aioquic]: https://github.com/aiortc/aioquic
[SimpleJSON]: https://github.com/simplejson/simplejson
[OpenTimelineIO]: https://github.com/AcademySoftwareFoundation/OpenTimelineIO
[SimpleJSON]: https://github.com/simplejson/simplejson
[PyTables]: https://github.com/PyTables/PyTables
[google neuroglancer]: https://github.com/google/neuroglancer
[Parselmouth]: https://github.com/YannickJadoul/Parselmouth
[AutoPy]: https://github.com/autopilot-rs/autopy
[DeepForest]: https://github.com/LAMDA-NJU/Deep-Forest
[H3-py]: https://github.com/uber/h3-py
[DeepForest]: https://github.com/LAMDA-NJU/Deep-Forest
[time-machine]: https://github.com/adamchainz/time-machine
[mosec]: https://github.com/mosecorg/mosec
[Picologging]: https://github.com/microsoft/picologging
[pybind11 cmake_example]: https://github.com/pybind/cmake_example
[markupsafe]: https://github.com/pallets/markupsafe
[pybind11 cmake_example]: https://github.com/pybind/cmake_example
[Rtree]: https://github.com/Toblerity/rtree
[KDEpy]: https://github.com/tommyod/KDEpy
[dd-trace-py]: https://github.com/DataDog/dd-trace-py
[tgcalls]: https://github.com/MarshalX/tgcalls
[pybind11 python_example]: https://github.com/pybind/python_example
[sourmash]: https://github.com/sourmash-bio/sourmash
[python-rapidjson]: https://github.com/python-rapidjson/python-rapidjson
[pybind11 python_example]: https://github.com/pybind/python_example
[abess]: https://github.com/abess-team/abess
[python-snappy]: https://github.com/intake/python-snappy
[jq.py]: https://github.com/mwilliamson/jq.py
[cyvcf2]: https://github.com/brentp/cyvcf2
[matrixprofile]: https://github.com/matrix-profile-foundation/matrixprofile
[Confluent client for Kafka]: https://github.com/confluentinc/confluent-kafka-python
[matrixprofile]: https://github.com/matrix-profile-foundation/matrixprofile
[Tokenizer]: https://github.com/OpenNMT/Tokenizer
[iminuit]: https://github.com/scikit-hep/iminuit
[pillow-heif]: https://github.com/bigcat88/pillow_heif
@@ -207,9 +207,9 @@ title: Working examples
[power-grid-model]: https://github.com/PowerGridModel/power-grid-model
[streaming-form-data]: https://github.com/siddhantgoel/streaming-form-data
[pybase64]: https://github.com/mayeut/pybase64
[Imagecodecs (fork)]: https://github.com/czaki/imagecodecs_build
[bx-python]: https://github.com/bxlab/bx-python
[boost-histogram]: https://github.com/scikit-hep/boost-histogram
[Imagecodecs (fork)]: https://github.com/czaki/imagecodecs_build
[Python-WebRTC]: https://github.com/MarshalX/python-webrtc
[pybind11 scikit_build_example]: https://github.com/pybind/scikit_build_example
[fathon]: https://github.com/stfbnc/fathon
@@ -220,13 +220,13 @@ title: Working examples
[etebase-py]: https://github.com/etesync/etebase-py
[cf-units]: https://github.com/SciTools/cf-units
[numpythia]: https://github.com/scikit-hep/numpythia
[pyjet]: https://github.com/scikit-hep/pyjet
[SiPM]: https://github.com/EdoPro98/SimSiPM
[ril]: https://github.com/Cryptex-github/ril-py
[aalink]: https://github.com/artfwo/aalink
[SiPM]: https://github.com/EdoPro98/SimSiPM
[pyjet]: https://github.com/scikit-hep/pyjet
[ril]: https://github.com/Cryptex-github/ril-py
[GSD]: https://github.com/glotzerlab/gsd
[CorrectionLib]: https://github.com/cms-nanoAOD/correctionlib
[werpy]: https://github.com/analyticsinmotion/werpy
[CorrectionLib]: https://github.com/cms-nanoAOD/correctionlib
[xmlstarlet]: https://github.com/dimitern/xmlstarlet
[pybind11 cross build example]: https://github.com/wbarnha/pybind_cmake_example_crossbuild
+3 -3
View File
@@ -6,7 +6,7 @@ jobs:
- bash: |
set -o errexit
python3 -m pip install --upgrade pip
pip3 install cibuildwheel==3.2.1
pip3 install cibuildwheel==3.3.1
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
@@ -20,7 +20,7 @@ jobs:
- bash: |
set -o errexit
python3 -m pip install --upgrade pip
python3 -m pip install cibuildwheel==3.2.1
python3 -m pip install cibuildwheel==3.3.1
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
@@ -34,7 +34,7 @@ jobs:
- bash: |
set -o errexit
python -m pip install --upgrade pip
pip install cibuildwheel==3.2.1
pip install cibuildwheel==3.3.1
displayName: Install dependencies
- bash: cibuildwheel --output-dir wheelhouse .
displayName: Build wheels
+3 -3
View File
@@ -11,7 +11,7 @@ jobs:
- run:
name: Build the Linux wheels.
command: |
python3 -m pip install --user cibuildwheel==3.2.1
python3 -m pip install --user cibuildwheel==3.3.1
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
@@ -28,7 +28,7 @@ jobs:
- run:
name: Build the Linux aarch64 wheels.
command: |
python3 -m pip install --user cibuildwheel==3.2.1
python3 -m pip install --user cibuildwheel==3.3.1
python3 -m cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
@@ -44,7 +44,7 @@ jobs:
name: Build the OS X wheels.
command: |
sudo softwareupdate --install-rosetta --agree-to-license # for python<=3.8 or x86_64/universal2 tests
pip3 install cibuildwheel==3.2.1
pip3 install cibuildwheel==3.3.1
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
+1 -1
View File
@@ -1,6 +1,6 @@
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
install_cibuildwheel_script:
- python -m pip install cibuildwheel==3.2.1
- python -m pip install cibuildwheel==3.3.1
run_cibuildwheel_script:
- cibuildwheel
wheels_artifacts:
+1 -1
View File
@@ -1,6 +1,6 @@
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
install_cibuildwheel_script:
- python -m pip install cibuildwheel==3.2.1
- python -m pip install cibuildwheel==3.3.1
run_cibuildwheel_script:
- cibuildwheel
wheels_artifacts:
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
- uses: actions/checkout@v5
- name: Build wheels
uses: pypa/cibuildwheel@v3.2.1
uses: pypa/cibuildwheel@v3.3.1
env:
CIBW_PLATFORM: ${{ matrix.platform || 'auto' }}
CIBW_ARCHS: ${{ matrix.archs || 'auto' }}
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v5
- name: Build wheels
uses: pypa/cibuildwheel@v3.2.1
uses: pypa/cibuildwheel@v3.3.1
# env:
# CIBW_SOME_OPTION: value
# ...
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v5
- name: Build wheels
run: pipx run cibuildwheel==3.2.1
run: pipx run cibuildwheel==3.3.1
- uses: actions/upload-artifact@v4
with:
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
platforms: all
- name: Build wheels
uses: pypa/cibuildwheel@v3.2.1
uses: pypa/cibuildwheel@v3.3.1
env:
# configure cibuildwheel on Linux to build native archs ('auto'),
# and to split the remaining architectures between the x86_64 and
+3 -3
View File
@@ -12,7 +12,7 @@ linux:
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install cibuildwheel==3.2.1
- python -m pip install cibuildwheel==3.3.1
- cibuildwheel --output-dir wheelhouse
artifacts:
paths:
@@ -23,7 +23,7 @@ windows:
before_script:
- choco install python -y --allow-downgrade --version 3.12.4
- choco install git.install -y
- py -m pip install cibuildwheel==3.2.1
- py -m pip install cibuildwheel==3.3.1
script:
- py -m cibuildwheel --output-dir wheelhouse --platform windows
artifacts:
@@ -35,7 +35,7 @@ windows:
macos:
image: macos-14-xcode-15
before_script:
- python3 -m pip install cibuildwheel==3.2.1
- python3 -m pip install cibuildwheel==3.3.1
script:
- python3 -m cibuildwheel --output-dir wheelhouse
artifacts:
+1 -1
View File
@@ -14,7 +14,7 @@ linux:
- curl -sSL https://get.docker.com/ | sh
# Warning: This is extremely slow, be careful with how many wheels you build
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- python -m pip install cibuildwheel==3.2.1
- python -m pip install cibuildwheel==3.3.1
# Assuming your CI runner's default architecture is x86_64...
- cibuildwheel --output-dir wheelhouse --platform linux --archs aarch64
artifacts:
-36
View File
@@ -1,36 +0,0 @@
# As written, this configuration will build your wheels on every
# commit, but will only push to PyPI on tagged commits.
os: linux
dist: jammy
language: python
python: "3.12"
jobs:
include:
# perform a linux build
- services: docker
# and a windows build
- os: windows
language: shell
before_install:
- choco upgrade python -y --version 3.12.4
- export PATH="/c/Python312:/c/Python312/Scripts:$PATH"
# make sure it's on PATH as 'python3'
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
install:
- python3 -m pip install cibuildwheel==3.2.1
script:
# build the wheels, put them into './dist'
- python3 -m cibuildwheel --output-dir dist
deploy:
provider: pypi
username: "__token__"
skip_cleanup: true
on:
tags: true
password:
secure: "" # Set to an encrypted API token. See https://docs.travis-ci.com/user/deployment/pypi/
-33
View File
@@ -1,33 +0,0 @@
os: linux
dist: jammy
language: python
python: "3.12"
jobs:
include:
# perform a linux build
- services: docker
# perform a linux ARMv8 build
- services: docker
arch: arm64
# perform a linux PPC64LE build
- services: docker
arch: ppc64le
# perform a linux S390X build
- services: docker
arch: s390x
# and a windows build
- os: windows
language: shell
before_install:
- choco upgrade python -y --version 3.12.4
- export PATH="/c/Python312:/c/Python312/Scripts:$PATH"
# make sure it's on PATH as 'python3'
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
install:
- python3 -m pip install cibuildwheel==3.2.1
script:
# build the wheels, put them into './wheelhouse'
- python3 -m cibuildwheel --output-dir wheelhouse
-70
View File
@@ -1,70 +0,0 @@
# In this configuration, the package is tested against multiple versions of python
# on Linux and on one version of Python on Windows. If and only if all tests pass
# will the wheels be built and deployed. Further, deployment is only initiated if
# the current branch is "main", the current commit is tagged, and the current
# repo is yours (e.g. it won't run on a Pull Request). For convenience, a source
# distribution is also created.
os: linux
dist: jammy
language: python
python: "3.12"
before_install:
- |
if [[ "$TRAVIS_OS_NAME" = windows ]]; then
choco upgrade python -y --version 3.12.4
export PATH="/c/Python312:/c/Python312/Scripts:$PATH"
# make sure it's on PATH as 'python3'
ln -s /c/Python312/python.exe /c/Python312/python3.exe
fi
install:
- python3 -m pip install pytest
script:
- python3 -m pip install .
- pytest
stages:
- test
# Only execute deployment stage on tagged commits, and from your repository
# (e.g. not PRs). Replace with your repo name.
- name: deploy
if: tag IS PRESENT AND repo = pypa/cibuildwheel
# To only build tags that look like vX.Y.Z:
# if: tag =~ ^v\d+\.\d+\.\d+$ AND repo = pypa/cibuildwheel
jobs:
include:
# Optional: run a test on Windows
- os: windows
language: shell
name: Test on Windows
# Deploy source distribution
- stage: deploy
name: Deploy source distribution
install: python3 -m pip install build twine
script: python3 -m build --sdist --formats=gztar
after_success: python3 -m twine upload --skip-existing dist/*.tar.gz
# Deploy on linux
- stage: deploy
name: Build and deploy Linux wheels
services: docker
install: python3 -m pip install cibuildwheel==3.2.1 twine
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
# Deploy on windows
- stage: deploy
name: Build and deploy Windows wheels
os: windows
language: shell
install: python3 -m pip install cibuildwheel==3.2.1 twine
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
env:
global:
- TWINE_USERNAME=__token__
# Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings
+2 -2
View File
@@ -33,8 +33,8 @@ def lint(session: nox.Session) -> None:
"""
Run the linter.
"""
session.install("pre-commit")
session.run("pre-commit", "run", "--all-files", *session.posargs)
session.install("prek")
session.run("prek", "run", "--all-files", *session.posargs)
@nox.session(tags=["lint"])
+12 -7
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "cibuildwheel"
version = "3.2.1"
version = "3.3.1"
description = "Build Python wheels on CI with minimal configuration."
readme = "README.md"
license = "BSD-2-Clause"
@@ -19,7 +19,6 @@ keywords = [
"macos",
"packaging",
"pypi",
"travis",
"wheel",
"windows",
]
@@ -79,13 +78,10 @@ bin = [
docs = [
"jinja2>=3.1.2",
"mkdocs-include-markdown-plugin==6.2.2",
"mkdocs-macros-plugin",
"mkdocs-macros-plugin>=1.4.1",
"mkdocs==1.6.1",
"pymdown-extensions",
"rich",
# transitive dep of mkdocs-macros-plugin
# https://github.com/fralau/mkdocs-macros-plugin/issues/269
"requests",
]
test = [
"build",
@@ -113,7 +109,7 @@ addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config", "--xdoc
junit_family = "xunit2"
xfail_strict = true
filterwarnings = ["error"]
log_cli_level = "INFO"
log_level = "INFO"
markers = [
"serial: tests that must *not* be run in parallel (deselect with '-m \"not serial\"')",
"ios: tests that run on iOS",
@@ -219,6 +215,15 @@ extend-select = [
"EXE", # flake8-executable
"PYI", # flake8-pyi
"PERF101", "PERF102", "PERF401", "PERF402", "PERF403", # A selection of perflint codes
"DTZ", # flake8-datetimez
"FA", # flake8-future-annotations
"FLY", # flynt
"FURB", # refurb
"LOG", # flake8-logging
"Q", # flake8-quotes
"SLOT", # flake8-slots
"T10", # flake8-debugger
"TC", # flake8-type-checking
]
ignore = [
"PLR", # Design related pylint codes
+20
View File
@@ -0,0 +1,20 @@
import sys
import sysconfig
from pathlib import Path
assert sys.platform == "android"
assert sysconfig.get_platform().startswith("android-")
android_prefix = Path(f"{sys.prefix}/../python/prefix").resolve()
assert android_prefix.is_dir()
vars = sysconfig.get_config_vars()
assert vars["INCLUDEDIR"] == f"{android_prefix}/include"
assert vars["LDVERSION"] == f"{sys.version_info[0]}.{sys.version_info[1]}{sys.abiflags}"
assert vars["INCLUDEPY"] == f"{vars['INCLUDEDIR']}/python{vars['LDVERSION']}"
assert vars["LIBDIR"] == f"{android_prefix}/lib"
assert vars["Py_ENABLE_SHARED"] == 1
paths = sysconfig.get_paths()
assert paths["include"] == vars["INCLUDEPY"]
assert paths["platinclude"] == vars["INCLUDEPY"]
+27 -7
View File
@@ -154,19 +154,39 @@ def docker_warmup_fixture(
@pytest.fixture(params=["pip", "build"])
def build_frontend_env_nouv(request: pytest.FixtureRequest) -> dict[str, str]:
frontend = request.param
if get_platform() == "pyodide" and frontend == "pip":
marks = {m.name for m in request.node.iter_markers()}
platform = "pyodide" if "pyodide" in marks else get_platform()
if platform == "pyodide" and frontend == "pip":
pytest.skip("Can't use pip as build frontend for pyodide platform")
return {"CIBW_BUILD_FRONTEND": frontend}
@pytest.fixture
def build_frontend_env(build_frontend_env_nouv: dict[str, str]) -> dict[str, str]:
frontend = build_frontend_env_nouv["CIBW_BUILD_FRONTEND"]
if frontend != "build" or get_platform() == "pyodide" or find_uv() is None:
return build_frontend_env_nouv
@pytest.fixture(params=["pip", "build", "build[uv]"])
def build_frontend_env(request: pytest.FixtureRequest) -> dict[str, str]:
frontend = request.param
marks = {m.name for m in request.node.iter_markers()}
if "android" in marks:
platform = "android"
elif "ios" in marks:
platform = "ios"
elif "pyodide" in marks:
platform = "pyodide"
else:
platform = get_platform()
return {"CIBW_BUILD_FRONTEND": "build[uv]"}
if platform in {"pyodide", "ios", "android"} and frontend == "pip":
pytest.skip(f"Can't use pip as build frontend for {platform}")
if platform == "pyodide" and frontend == "build[uv]":
pytest.skip("Can't use uv with pyodide yet")
uv_path = find_uv()
if uv_path is None and frontend == "build[uv]":
pytest.skip("Can't find uv, so skipping uv tests")
if uv_path is not None and frontend == "build" and platform not in {"android", "ios"}:
pytest.skip("No need to check build when uv is present")
return {"CIBW_BUILD_FRONTEND": frontend}
@pytest.fixture
+247 -54
View File
@@ -4,7 +4,7 @@ import re
import sys
from dataclasses import dataclass
from pathlib import Path
from shutil import rmtree
from shutil import rmtree, which
from subprocess import CalledProcessError
from textwrap import dedent
from zipfile import ZipFile
@@ -32,22 +32,25 @@ if (platform.system(), platform.machine()) not in [
allow_module_level=True,
)
# Detect CI services which have the Android SDK pre-installed.
ci_supports_build = (
("CIRRUS_CI" in os.environ and platform.system() == "Darwin")
or "GITHUB_ACTIONS" in os.environ
or "TF_BUILD" in os.environ # Azure Pipelines
)
# Azure Pipelines does not set the CI variable.
ci = any(key in os.environ for key in ["CI", "TF_BUILD"])
if "ANDROID_HOME" not in os.environ:
msg = "ANDROID_HOME environment variable is not set"
if ci_supports_build:
# Fail if we're on a CI service which is supposed to have the Android SDK
# pre-installed; otherwise skip the module.
if (
("CIRRUS_CI" in os.environ and platform.system() == "Darwin")
or "GITHUB_ACTIONS" in os.environ
or "TF_BUILD" in os.environ
):
pytest.fail(msg)
else:
pytest.skip(msg, allow_module_level=True)
# Many CI services don't support running the Android emulator: see platforms.md.
ci_supports_emulator = "GITHUB_ACTIONS" in os.environ and platform.system() == "Linux"
supports_emulator = (not ci) or ("GITHUB_ACTIONS" in os.environ and platform.system() == "Linux")
def needs_emulator(test):
@@ -55,7 +58,7 @@ def needs_emulator(test):
# application ID, so these tests must be run serially.
test = pytest.mark.serial(test)
if ci_supports_build and not ci_supports_emulator:
if not supports_emulator:
test = pytest.mark.skip("This CI platform doesn't support the emulator")(test)
return test
@@ -92,27 +95,40 @@ def test_android_home(tmp_path, capfd):
assert "ANDROID_HOME environment variable is not set" in capfd.readouterr().err
# the first build can fail to setup - mark as flaky, and serial to make sure it runs first
# android-env.sh may need to install the NDK, and it isn't safe to do that multiple
# times in parallel. So make sure there's at least one test which gets as far as doing
# a build, which is marked as serial so it will run before the parallel tests, but isn't
# marked as needs_emulator so it will run on all CI platforms.
@pytest.mark.serial
@pytest.mark.flaky(reruns=2)
def test_expected_wheels(tmp_path):
new_c_project().generate(tmp_path)
wheels = cibuildwheel_run(tmp_path, add_env={"CIBW_PLATFORM": "android"})
def test_expected_wheels(tmp_path, spam_env):
# Since this test covers all Python versions, check the cross venv.
test_module = "_cross_venv_test_android"
project = new_c_project(setup_py_add=f"import {test_module}")
project.files[f"{test_module}.py"] = (Path(__file__).parent / f"{test_module}.py").read_text()
project.generate(tmp_path)
# Build wheels for all Python versions on the current architecture.
del spam_env["CIBW_BUILD"]
if not supports_emulator:
del spam_env["CIBW_TEST_COMMAND"]
wheels = cibuildwheel_run(tmp_path, add_env=spam_env)
assert wheels == expected_wheels(
"spam", "0.1.0", platform="android", machine_arch=native_arch.android_abi
)
def test_frontend_good(tmp_path):
@needs_emulator
def test_frontend_good(tmp_path, build_frontend_env):
new_c_project().generate(tmp_path)
wheels = cibuildwheel_run(
tmp_path,
add_env={**cp313_env, "CIBW_BUILD_FRONTEND": "build"},
add_env={**cp313_env, **build_frontend_env, "CIBW_TEST_COMMAND": "python -m site"},
)
assert wheels == [f"spam-0.1.0-cp313-cp313-android_21_{native_arch.android_abi}.whl"]
@pytest.mark.parametrize("frontend", ["build[uv]", "pip"])
@pytest.mark.parametrize("frontend", ["pip"])
def test_frontend_bad(frontend, tmp_path, capfd):
new_c_project().generate(tmp_path)
with pytest.raises(CalledProcessError):
@@ -222,12 +238,20 @@ def spam_env(tmp_path):
print("Spam test passed")
"""
)
project.files["test_empty.py"] = dedent(
"""\
def test_empty():
pass
"""
)
project.generate(tmp_path)
return {
**cp313_env,
"CIBW_TEST_SOURCES": "test_spam.py",
"CIBW_TEST_SOURCES": "test_spam.py test_empty.py",
"CIBW_TEST_REQUIRES": "pytest==8.3.5",
"CIBW_TEST_COMMAND": "python -m pytest",
}
@@ -235,7 +259,8 @@ def spam_env(tmp_path):
@pytest.mark.parametrize(
("command", "expected_output"),
[
("python -c 'import test_spam; test_spam.test_spam()'", "Spam test passed"),
("python3 -c 'import test_spam; test_spam.test_spam()'", "Spam test passed"),
("python -m pytest", "=== 2 passed in "),
("python -m pytest test_spam.py", "=== 1 passed in "),
("pytest test_spam.py", "=== 1 passed in "),
],
@@ -252,27 +277,25 @@ def test_test_command_good(command, expected_output, tmp_path, spam_env, capfd):
) in stderr
BAD_FORMAT_ERROR = (
"Test command '{}' is not supported on Android. "
"Command must begin with 'python' or 'python3', and contain '-m' or '-c'."
)
BAD_PLACEHOLDER_ERROR = (
"Test command '{}' with a '{{project}}' or '{{package}}' placeholder "
"is not supported on Android"
)
@needs_emulator
@pytest.mark.parametrize(
("command", "expected_output"),
[
# Build-time failure: unrecognized command
(
"./test_spam.py",
"Test command './test_spam.py' is not supported on Android. "
"Supported commands are 'python -m' and 'python -c'.",
),
# Build-time failure: unrecognized placeholder
(
"pytest {project}",
"Test command 'pytest {project}' with a '{project}' or '{package}' "
"placeholder is not supported on Android",
),
(
"pytest {package}",
"Test command 'pytest {package}' with a '{project}' or '{package}' "
"placeholder is not supported on Android",
),
# Build-time failure
("./test_spam.py", BAD_FORMAT_ERROR.format("./test_spam.py")),
("python test_spam.py", BAD_FORMAT_ERROR.format("python test_spam.py")),
("pytest {project}", BAD_PLACEHOLDER_ERROR.format("pytest {project}")),
("pytest {package}", BAD_PLACEHOLDER_ERROR.format("pytest {package}")),
# Runtime failure
("pytest test_ham.py", "not found: test_ham.py"),
],
@@ -283,6 +306,29 @@ def test_test_command_bad(command, expected_output, tmp_path, spam_env, capfd):
assert expected_output in capfd.readouterr().err
@needs_emulator
@pytest.mark.parametrize(
("options", "expected"),
[
("", 0),
("-E", 1),
],
)
def test_test_command_python_options(options, expected, tmp_path, capfd):
project = new_c_project()
project.generate(tmp_path)
command = 'import sys; print(f"{sys.flags.ignore_environment=}")'
cibuildwheel_run(
tmp_path,
add_env={
**cp313_env,
"CIBW_TEST_COMMAND": f"python {options} -c '{command}'",
},
)
assert f"sys.flags.ignore_environment={expected}" in capfd.readouterr().out
@needs_emulator
def test_package_subdir(tmp_path, spam_env, capfd):
spam_paths = list(tmp_path.iterdir())
@@ -291,17 +337,11 @@ def test_package_subdir(tmp_path, spam_env, capfd):
for path in spam_paths:
path.rename(package_dir / path.name)
test_filename = "package/" + spam_env["CIBW_TEST_SOURCES"]
cibuildwheel_run(
tmp_path,
package_dir,
add_env={
**spam_env,
"CIBW_TEST_SOURCES": test_filename,
"CIBW_TEST_COMMAND": f"python -m pytest {test_filename}",
},
spam_env["CIBW_TEST_SOURCES"] = " ".join(
f"package/{path}" for path in spam_env["CIBW_TEST_SOURCES"].split()
)
assert "=== 1 passed in " in capfd.readouterr().out
cibuildwheel_run(tmp_path, package_dir, add_env=spam_env)
assert "=== 2 passed in " in capfd.readouterr().out
@needs_emulator
@@ -346,13 +386,7 @@ def test_environment_markers(tmp_path):
**cp313_env,
"CIBW_TEST_COMMAND": f"python -m pytest {test_filename}",
"CIBW_TEST_SOURCES": test_filename,
"CIBW_TEST_REQUIRES": " ".join(
[
"pytest",
"certifi;sys_platform=='android'",
"platformdirs;sys_platform!='android'",
]
),
"CIBW_TEST_REQUIRES": "pytest certifi;sys_platform=='android' platformdirs;sys_platform!='android'",
},
)
@@ -462,3 +496,162 @@ def test_libcxx(tmp_path, capfd):
assert len(wheels) == 1
for name in ZipFile(output_dir / wheels[0]).namelist():
assert ".libs" not in name
@needs_emulator
def test_setuptools_rust(tmp_path, capfd):
"""
Test Android cross-compilation using the setuptools-rust toolchain.
"""
if not which("rustup") or not which("cargo"):
pytest.skip("rustup and cargo are required for this test")
# Initialize a basic project and override files for setuptools-rust
project = new_c_project()
project.files["pyproject.toml"] = dedent(
"""\
[build-system]
requires = ["setuptools", "wheel", "setuptools-rust"]
"""
)
project.files["setup.py"] = dedent(
"""\
from setuptools import setup
from setuptools_rust import Binding, RustExtension
setup(
name="spam",
version="0.1.0",
rust_extensions=[RustExtension("spam.rust_ext", binding=Binding.PyO3)],
zip_safe=False,
)
"""
)
project.files["Cargo.toml"] = dedent(
"""\
[package]
name = "rust_ext"
version = "0.1.0"
edition = "2021"
[lib]
name = "rust_ext"
crate-type = ["cdylib"]
[dependencies]
pyo3 = { version = "0.23.3", features = ["extension-module"] }
"""
)
# Create the Rust source directory and file
(tmp_path / "src").mkdir()
project.files["src/lib.rs"] = dedent(
"""\
use pyo3::prelude::*;
#[pyfunction]
fn hello() -> PyResult<String> {
Ok("Hello from Rust via setuptools-rust!".to_string())
}
#[pymodule]
fn rust_ext(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(hello, m)?)?;
Ok(())
}
"""
)
project.generate(tmp_path)
# Command to verify the built extension on the Android emulator
test_command = "python -c 'import spam.rust_ext; print(spam.rust_ext.hello())'"
# Run cibuildwheel to build and test the wheel
wheels = cibuildwheel_run(
tmp_path,
add_env={
**cp313_env,
"CIBW_TEST_COMMAND": test_command,
"CIBW_BUILD_VERBOSITY": "1",
},
)
# Verification
assert len(wheels) == 1
stdout = capfd.readouterr().out
assert "Hello from Rust via setuptools-rust!" in stdout
@needs_emulator
def test_maturin(tmp_path, capfd):
"""
Test Android cross-compilation using the maturin backend.
"""
if not which("rustup") or not which("cargo"):
pytest.skip("rustup and cargo are required for this test")
project = new_c_project()
project.files["pyproject.toml"] = dedent(
"""\
[build-system]
# maturin >= 1.11.0 is required for reliable Android cross-compilation support.
requires = ["maturin>=1.11.0,<2.0"]
build-backend = "maturin"
[project]
name = "spam"
version = "0.1.0"
"""
)
project.files["Cargo.toml"] = dedent(
"""\
[package]
name = "spam"
version = "0.1.0"
edition = "2021"
[lib]
name = "spam"
crate-type = ["cdylib"]
[dependencies]
pyo3 = { version = "0.23.3", features = ["extension-module"] }
"""
)
(tmp_path / "src").mkdir()
project.files["src/lib.rs"] = dedent(
"""\
use pyo3::prelude::*;
#[pyfunction]
fn hello() -> PyResult<String> {
Ok("Hello from Rust via maturin!".to_string())
}
#[pymodule]
fn spam(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(hello, m)?)?;
Ok(())
}
"""
)
project.generate(tmp_path)
(tmp_path / "setup.py").unlink()
test_command = "python -c 'import spam; print(spam.hello())'"
wheels = cibuildwheel_run(
tmp_path,
add_env={
**cp313_env,
"CIBW_TEST_COMMAND": test_command,
"CIBW_BUILD_VERBOSITY": "1",
},
)
assert len(wheels) == 1
stdout = capfd.readouterr().out
assert "Hello from Rust via maturin!" in stdout
+40
View File
@@ -1,4 +1,5 @@
import subprocess
import textwrap
from contextlib import nullcontext as does_not_raise
import pytest
@@ -56,3 +57,42 @@ def test(tmp_path, capfd):
# We only produced one wheel (perhaps Pyodide)
# check that it has the right name
assert result[0].startswith("spam-0.1.0-py2-none-")
@pytest.mark.parametrize(
"repair_command",
[
"python repair.py {wheel} {dest_dir}",
"python {package}/repair.py {wheel} {dest_dir}",
"python {project}/repair.py {wheel} {dest_dir}",
],
ids=["no-placeholder", "package-placeholder", "project-placeholder"],
)
def test_repair_wheel_command_structure(tmp_path, repair_command):
project_dir = tmp_path / "project"
project = test_projects.new_c_project()
project.files["repair.py"] = textwrap.dedent("""
import shutil
import sys
from pathlib import Path
wheel = Path(sys.argv[1])
dest_dir = Path(sys.argv[2])
dest_dir.mkdir(parents=True, exist_ok=True)
shutil.copy(wheel, dest_dir / "spamrepaired-0.0.1-py-none-any.whl")
""")
# Combined test for repair wheel command formats (plain, {package}, {project})
project.generate(project_dir)
result = utils.cibuildwheel_run(
project_dir,
add_env={
"CIBW_REPAIR_WHEEL_COMMAND": repair_command,
"CIBW_ARCHS": "native",
},
single_python=True,
)
assert result == ["spamrepaired-0.0.1-py-none-any.whl"]
+78 -54
View File
@@ -1,5 +1,7 @@
import json
import platform
import re
import subprocess
import textwrap
from pathlib import Path
@@ -9,40 +11,62 @@ from cibuildwheel.util import resources
from . import test_projects, utils
project_with_expected_version_checks = test_projects.new_c_project(
setup_py_add=textwrap.dedent(
r"""
import subprocess
import os
import sys
VERSION_REGEX = r"([\w-]+)==([^\s]+)"
versions_output_text = subprocess.check_output(
[sys.executable, '-m', 'pip', 'freeze', '--all', '-qq'],
universal_newlines=True,
)
versions = versions_output_text.strip().splitlines()
CHECK_VERSIONS_SCRIPT = """\
'''
Checks that the versions in the env var EXPECTED_VERSIONS match those
installed in the active venv.
'''
import os, subprocess, sys, json
# `versions` now looks like:
# ['pip==x.x.x', 'setuptools==x.x.x', 'wheel==x.x.x']
print('Gathered versions', versions)
expected_version = os.environ['EXPECTED_PIP_VERSION']
assert f'pip=={expected_version}' in versions, (
f'error: pip version should equal {expected_version}'
)
"""
)
versions_raw = json.loads(
subprocess.check_output([
sys.executable, '-m', 'pip', 'list', '--format=json',
], text=True)
)
versions = {item['name']: item['version'] for item in versions_raw}
expected_versions = json.loads(os.environ['EXPECTED_VERSIONS'])
project_with_expected_version_checks.files["pyproject.toml"] = r"""
[build-system]
requires = ["setuptools", "pip"]
build-backend = "setuptools.build_meta"
for name, expected_version in expected_versions.items():
if name not in versions:
continue
if versions[name] != expected_version:
raise SystemExit(f'error: {name} version should equal {expected_version}. Versions: {versions}')
"""
VERSION_REGEX = r"([\w-]+)==([^\s]+)"
def test_check_versions_script(tmp_path, build_frontend_env_nouv, capfd):
if utils.get_platform() == "linux":
pytest.skip("we don't test dependency versions on linux, refer to other tests")
# sanity check that the CHECK_VERSIONS_SCRIPT fails when it should
project_dir = tmp_path / "project"
test_projects.new_c_project().generate(project_dir)
expected_versions = {
"pip": "0.0.1",
"build": "0.0.2",
}
script = project_dir / "check_versions.py"
script.write_text(CHECK_VERSIONS_SCRIPT)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(
project_dir,
add_env={
"CIBW_BEFORE_BUILD": f"python {script.name}",
"EXPECTED_VERSIONS": json.dumps(expected_versions),
**build_frontend_env_nouv,
},
)
captured = capfd.readouterr()
assert (
"error: pip version should equal 0.0.1" in captured.err
or "error: build version should equal 0.0.2" in captured.err
)
def get_versions_from_constraint_file(constraint_file: Path) -> dict[str, str]:
@@ -65,11 +89,15 @@ def test_pinned_versions(tmp_path, python_version, build_frontend_env_nouv):
pytest.skip(f"Windows ARM64 does not support Python {python_version}")
project_dir = tmp_path / "project"
project_with_expected_version_checks.generate(project_dir)
test_projects.new_c_project().generate(project_dir)
# read the expected versions from the appropriate constraint file
version_no_dot = python_version.replace(".", "")
build_environment = {}
build_pattern = f"[cp]p{version_no_dot}-*"
# create cross-platform Python before-build script to verify versions pre-build
before_build_script = project_dir / "check_versions.py"
before_build_script.write_text(CHECK_VERSIONS_SCRIPT)
if utils.get_platform() == "pyodide":
constraint_filename = f"constraints-pyodide{version_no_dot}.txt"
else:
@@ -77,16 +105,13 @@ def test_pinned_versions(tmp_path, python_version, build_frontend_env_nouv):
constraint_file = resources.PATH / constraint_filename
constraint_versions = get_versions_from_constraint_file(constraint_file)
build_environment["EXPECTED_PIP_VERSION"] = constraint_versions["pip"]
cibw_environment_option = " ".join(f"{k}={v}" for k, v in build_environment.items())
# build and test the wheels
# build and test the wheels (dependency version check occurs before-build)
actual_wheels = utils.cibuildwheel_run(
project_dir,
add_env={
"CIBW_BUILD": build_pattern,
"CIBW_ENVIRONMENT": cibw_environment_option,
"CIBW_BUILD": f"[cp]p{version_no_dot}-*",
"CIBW_BEFORE_BUILD": f"python {before_build_script.name}",
"EXPECTED_VERSIONS": json.dumps(constraint_versions),
**build_frontend_env_nouv,
},
)
@@ -107,10 +132,11 @@ def test_dependency_constraints(method, tmp_path, build_frontend_env_nouv):
pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead")
project_dir = tmp_path / "project"
project_with_expected_version_checks.generate(project_dir)
test_projects.new_c_project().generate(project_dir)
tool_versions = {
"pip": "23.1.2",
"build": "1.2.2",
"delocate": "0.10.3",
}
@@ -120,6 +146,7 @@ def test_dependency_constraints(method, tmp_path, build_frontend_env_nouv):
textwrap.dedent(
"""
pip=={pip}
build=={build}
delocate=={delocate}
""".format(**tool_versions)
)
@@ -133,7 +160,7 @@ def test_dependency_constraints(method, tmp_path, build_frontend_env_nouv):
msg = f"Unknown method: {method}"
raise ValueError(msg)
build_environment = {}
skip = ""
if (
utils.get_platform() == "windows"
@@ -144,32 +171,29 @@ def test_dependency_constraints(method, tmp_path, build_frontend_env_nouv):
# from a virtualenv seeded executable. See
# https://github.com/oracle/graalpython/issues/491 and remove this once
# GraalPy 24 is dropped
build_frontend_env_nouv["CIBW_SKIP"] = "gp311*"
skip = "gp311*"
for package_name, version in tool_versions.items():
env_name = f"EXPECTED_{package_name.upper()}_VERSION"
build_environment[env_name] = version
# cross-platform Python script for dependency constraint checks
before_build_script = project_dir / "check_versions.py"
before_build_script.write_text(CHECK_VERSIONS_SCRIPT)
cibw_environment_option = " ".join(f"{k}={v}" for k, v in build_environment.items())
# build and test the wheels
# build and test the wheels (dependency version check occurs pre-build)
actual_wheels = utils.cibuildwheel_run(
project_dir,
add_env={
"CIBW_ENVIRONMENT": cibw_environment_option,
"CIBW_SKIP": skip,
"CIBW_DEPENDENCY_VERSIONS": dependency_version_option,
"CIBW_BEFORE_BUILD": f"python {before_build_script.name}",
"EXPECTED_VERSIONS": json.dumps(tool_versions),
**build_frontend_env_nouv,
},
single_python=True,
)
# also check that we got the right wheels
expected_wheels = utils.expected_wheels("spam", "0.1.0")
expected_wheels = utils.expected_wheels("spam", "0.1.0", single_python=True)
if (
utils.get_platform() == "windows"
and method == "file"
and build_frontend_env_nouv["CIBW_BUILD_FRONTEND"] == "build"
):
if skip == "gp*":
# See reference to https://github.com/oracle/graalpython/issues/491
# above
expected_wheels = [w for w in expected_wheels if "graalpy311" not in w]
+2 -2
View File
@@ -84,7 +84,7 @@ def test(manylinux_image, tmp_path):
"CIBW_MANYLINUX_PYPY_I686_IMAGE": manylinux_image,
}
if platform.machine() == "aarch64":
# We just have a manylinux_2_31 image for armv7l
# We just have a manylinux_2_31/manylinux_2_35 image for armv7l
add_env["CIBW_ARCHS"] = "aarch64"
actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env)
@@ -100,7 +100,7 @@ def test(manylinux_image, tmp_path):
)
if platform.machine() == "aarch64":
# We just have a manylinux_2_31 image for armv7l
# We just have a manylinux_2_31/manylinux_2_35 image for armv7l
expected_wheels = [w for w in expected_wheels if "armv7l" not in w]
assert set(actual_wheels) == set(expected_wheels)
+1 -1
View File
@@ -99,7 +99,7 @@ def test_pyodide_version_incompatible(tmp_path, capfd):
tmp_path,
add_args=["--platform", "pyodide"],
add_env={
"CIBW_DEPENDENCY_VERSIONS": "packages: pyodide-build==0.29.3",
"CIBW_DEPENDENCY_VERSIONS": "packages: pyodide-build==0.31.2",
"CIBW_PYODIDE_VERSION": "0.26.0a6",
},
)
+134
View File
@@ -0,0 +1,134 @@
from pathlib import Path
import pytest
from cibuildwheel.audit import is_abi3_wheel, run_audit
class TestIsAbi3Wheel:
def test_abi3_wheel(self) -> None:
assert is_abi3_wheel(Path("example-1.0.0-cp38-abi3-manylinux_2_17_x86_64.whl"))
def test_abi3_wheel_macos(self) -> None:
assert is_abi3_wheel(Path("example-1.0.0-cp39-abi3-macosx_10_9_x86_64.whl"))
def test_abi3_wheel_windows(self) -> None:
assert is_abi3_wheel(Path("example-1.0.0-cp310-abi3-win_amd64.whl"))
def test_non_abi3_wheel(self) -> None:
assert not is_abi3_wheel(Path("example-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl"))
def test_pure_python_wheel(self) -> None:
assert not is_abi3_wheel(Path("example-1.0.0-py3-none-any.whl"))
class TestRunAudit:
def test_empty_command_does_nothing(self, tmp_path: Path) -> None:
# Create a wheel file
wheel_path = tmp_path / "example-1.0.0-cp38-abi3-manylinux_2_17_x86_64.whl"
wheel_path.touch()
# Should not raise and should be a no-op
run_audit(
audit_command="",
output_dir=tmp_path,
wheels_before=set(),
)
def test_audit_runs_on_new_wheels(self, tmp_path: Path) -> None:
# Create a wheel file (simulating a build)
wheel_path = tmp_path / "example-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl"
wheel_path.touch()
# Create a marker file to verify command ran
marker = tmp_path / "audit_ran.txt"
run_audit(
audit_command=f"touch {marker}",
output_dir=tmp_path,
wheels_before=set(),
)
assert marker.exists()
def test_audit_skips_old_wheels(self, tmp_path: Path) -> None:
# Create a wheel file
wheel_path = tmp_path / "example-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl"
wheel_path.touch()
# Create a marker file to verify command ran
marker = tmp_path / "audit_ran.txt"
# Pre-existing wheel should be skipped
run_audit(
audit_command=f"touch {marker}",
output_dir=tmp_path,
wheels_before={wheel_path.name},
)
assert not marker.exists()
def test_abi3_only_mode_skips_non_abi3(self, tmp_path: Path) -> None:
# Create a non-abi3 wheel
wheel_path = tmp_path / "example-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl"
wheel_path.touch()
# Create a marker file to verify command ran
marker = tmp_path / "audit_ran.txt"
run_audit(
audit_command=f"echo {{abi3_wheel}} && touch {marker}",
output_dir=tmp_path,
wheels_before=set(),
)
# Should not run because no abi3 wheels
assert not marker.exists()
def test_abi3_only_mode_runs_on_abi3(self, tmp_path: Path) -> None:
# Create an abi3 wheel
wheel_path = tmp_path / "example-1.0.0-cp38-abi3-manylinux_2_17_x86_64.whl"
wheel_path.touch()
# Create a marker file to verify command ran
marker = tmp_path / "audit_ran.txt"
run_audit(
audit_command=f"echo {{abi3_wheel}} && touch {marker}",
output_dir=tmp_path,
wheels_before=set(),
)
assert marker.exists()
def test_wheel_placeholder_expanded(self, tmp_path: Path) -> None:
# Create a wheel file
wheel_path = tmp_path / "example-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl"
wheel_path.touch()
# Write wheel path to a file to verify expansion
output_file = tmp_path / "wheel_path.txt"
run_audit(
audit_command=f"echo {{wheel}} > {output_file}",
output_dir=tmp_path,
wheels_before=set(),
)
assert output_file.exists()
content = output_file.read_text().strip()
assert content == str(wheel_path)
def test_audit_fails_on_error(self, tmp_path: Path) -> None:
# Create a wheel file
wheel_path = tmp_path / "example-1.0.0-cp310-cp310-manylinux_2_17_x86_64.whl"
wheel_path.touch()
with pytest.raises(SystemExit) as exc_info:
run_audit(
audit_command="exit 1",
output_dir=tmp_path,
wheels_before=set(),
)
assert exc_info.value.code == 1
-65
View File
@@ -1,4 +1,3 @@
import os
import sys
import tomllib
from fnmatch import fnmatch
@@ -142,70 +141,6 @@ def test_empty_selector(monkeypatch):
assert e.value.code == 3
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_riscv64_warning1(monkeypatch, capsys):
monkeypatch.setenv("CIBW_ENABLE", "cpython-experimental-riscv64")
main()
_, err = capsys.readouterr()
print(err)
assert "'cpython-experimental-riscv64' enable is deprecated" in err
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_riscv64_warning2(monkeypatch, capsys, tmp_path):
local_path = tmp_path / "tmp_project"
os.mkdir(local_path) # noqa:PTH102 Path.mkdir has been monkeypatched already
local_path.joinpath("setup.py").touch()
monkeypatch.setattr(
sys, "argv", ["cibuildwheel", "--only", "cp313-manylinux_riscv64", str(local_path)]
)
monkeypatch.setenv("CIBW_ENABLE", "cpython-experimental-riscv64")
main()
_, err = capsys.readouterr()
print(err)
assert "'cpython-experimental-riscv64' enable is deprecated" in err
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_riscv64_no_warning(monkeypatch, capsys, tmp_path):
local_path = tmp_path / "tmp_project"
os.mkdir(local_path) # noqa:PTH102 Path.mkdir has been monkeypatched already
local_path.joinpath("setup.py").touch()
monkeypatch.setattr(
sys, "argv", ["cibuildwheel", "--only", "cp313-manylinux_riscv64", str(local_path)]
)
main()
_, err = capsys.readouterr()
print(err)
assert "'cpython-experimental-riscv64' enable is deprecated" not in err
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_riscv64_no_warning2(monkeypatch, capsys, tmp_path):
local_path = tmp_path / "tmp_project"
os.mkdir(local_path) # noqa:PTH102 Path.mkdir has been monkeypatched already
local_path.joinpath("setup.py").touch()
monkeypatch.setattr(
sys, "argv", ["cibuildwheel", "--only", "cp313-manylinux_riscv64", str(local_path)]
)
monkeypatch.setenv("CIBW_ENABLE", "all")
main()
_, err = capsys.readouterr()
print(err)
assert "'cpython-experimental-riscv64' enable is deprecated" not in err
@pytest.mark.parametrize(
("architecture", "image", "full_image"),
[
+5
View File
@@ -628,6 +628,11 @@ def test_multiarch_image(container_engine, platform):
'{"Client":{"Version":"24.0.0","ApiVersion":"1.43"},"Server":{"ApiVersion":"1.43"}}',
nullcontext(),
),
(
"docker",
'{"Client":{"Version":"29.0.0","ApiVersion":"1.52"},"Server":{"APIVersion":"1.52"}}',
nullcontext(),
),
(
"docker",
'{"Client":{"ApiVersion":"1.43"},"Server":{"ApiVersion":"1.30"}}',
+2 -2
View File
@@ -56,7 +56,7 @@ def test_build_default_launches(monkeypatch):
main()
build_in_container = typing.cast(mock.Mock, platforms.linux.build_in_container)
build_in_container = typing.cast("mock.Mock", platforms.linux.build_in_container)
assert build_in_container.call_count == 4
@@ -126,7 +126,7 @@ before-all = "true"
main()
build_in_container = typing.cast(mock.Mock, platforms.linux.build_in_container)
build_in_container = typing.cast("mock.Mock", platforms.linux.build_in_container)
assert build_in_container.call_count == 7
+34
View File
@@ -2,6 +2,7 @@ import os
import platform as platform_module
import textwrap
import unittest.mock
from collections.abc import Sequence
from pathlib import Path
from typing import Literal
@@ -626,6 +627,39 @@ def test_get_build_frontend_extra_flags_warning(
mock_warning.assert_called_once()
@pytest.mark.parametrize(
("definition", "expected_args"),
[
("", ()),
('test-runtime = ""', ()),
("test-runtime = {}", ()),
('test-runtime = {args = ""}', []),
('test-runtime = "args: --simulator foo"', ["--simulator", "foo"]),
('test-runtime = {args = ["--simulator", "foo"]}', ["--simulator", "foo"]),
],
)
def test_test_runtime_handling(
tmp_path: Path, definition: str, expected_args: Sequence[str] | None
) -> None:
args = CommandLineArguments.defaults()
args.package_dir = tmp_path
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
textwrap.dedent(
f"""\
[tool.cibuildwheel]
{definition}
"""
)
)
options = Options(platform="ios", command_line_arguments=args, env={})
local = options.build_options("cp313-ios_13_0_arm64_iphoneos")
assert local.test_runtime.args == expected_args
@pytest.mark.parametrize(
("definition", "expected"),
[
+47 -1
View File
@@ -1,5 +1,5 @@
import shlex
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
@@ -13,6 +13,9 @@ from cibuildwheel.options import (
_resolve_cascade,
)
if TYPE_CHECKING:
from pathlib import Path
PYPROJECT_1 = """
[tool.cibuildwheel]
build = "cp39*"
@@ -538,3 +541,46 @@ before-all = ["override2"]
options_reader.get("config-settings", option_format=ShlexTableFormat())
== "key1=value1 key2=override2 empty='' key3=value3"
)
def test_audit_option(tmp_path, platform):
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
[tool.cibuildwheel]
audit = "abi3audit {abi3_wheel}"
"""
)
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
assert options_reader.get("audit", option_format=ListFormat(" && ")) == "abi3audit {abi3_wheel}"
def test_audit_option_list(tmp_path, platform):
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
[tool.cibuildwheel]
audit = ["first command", "second command"]
"""
)
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
assert (
options_reader.get("audit", option_format=ListFormat(" && "))
== "first command && second command"
)
def test_audit_option_env(tmp_path, platform):
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
[tool.cibuildwheel]
"""
)
options_reader = OptionsReader(
pyproject_toml, platform=platform, env={"CIBW_AUDIT": "my-audit-tool {wheel}"}
)
assert options_reader.get("audit", option_format=ListFormat(" && ")) == "my-audit-tool {wheel}"