Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7da7df1efc | ||
|
|
9deb1b6794 | ||
|
|
271c5fe6e4 | ||
|
|
c716cfaeb8 | ||
|
|
099d397aee | ||
|
|
72222654f4 | ||
|
|
7a8b8012ff | ||
|
|
0ccf1dc016 | ||
|
|
ba11212a13 | ||
|
|
6d0890e7e0 | ||
|
|
cf7586ce7e | ||
|
|
137dc1a2cf | ||
|
|
1646b08659 | ||
|
|
a873dd9cbf | ||
|
|
e8ba0d49ed | ||
|
|
f0feaffbaa | ||
|
|
80a54b0226 | ||
|
|
76dba0b9ba | ||
|
|
0954ffaa65 | ||
|
|
753cbd1ca5 | ||
|
|
825d89818a | ||
|
|
f5e60d647f | ||
|
|
adc991c47b | ||
|
|
cc50337ecd | ||
|
|
db6d3095b9 | ||
|
|
f6a95d3d0b | ||
|
|
028455f481 | ||
|
|
05d5c9bada | ||
|
|
f34ae7731d | ||
|
|
4f888e27c3 | ||
|
|
e5d0cc0b0d | ||
|
|
a449142802 | ||
|
|
82a1f99268 | ||
|
|
1280565f7f | ||
|
|
386d36f5ad | ||
|
|
be0e07ac31 | ||
|
|
001f11c755 | ||
|
|
5f37a3bb02 | ||
|
|
5311f88684 | ||
|
|
81ef5fac43 | ||
|
|
53b641caaf | ||
|
|
ae6b3d40b5 | ||
|
|
061ea627e2 | ||
|
|
297e4a6099 | ||
|
|
e8bb208374 | ||
|
|
18ff2c57c2 | ||
|
|
98b83afe63 | ||
|
|
25428deff2 | ||
|
|
ce71f445de | ||
|
|
12d548865f | ||
|
|
9afd31017a | ||
|
|
7508943e06 | ||
|
|
26c5e18e62 | ||
|
|
c655dbdaab | ||
|
|
39a63b5912 | ||
|
|
47e5d3c2cd | ||
|
|
a63e11a1c4 | ||
|
|
df94b5db67 | ||
|
|
8946bfb2e8 | ||
|
|
36049d86a2 | ||
|
|
229f8570b4 | ||
|
|
5b32ee7d7b | ||
|
|
3f3bd9cff6 | ||
|
|
8df6d59adf | ||
|
|
4135c0a01d | ||
|
|
6282bc5a83 | ||
|
|
ddbcf561db | ||
|
|
f21bb8376a | ||
|
|
a5b2e543e5 | ||
|
|
bd9675d05b | ||
|
|
661ba2d0de | ||
|
|
66b46d0868 | ||
|
|
b0a5c951f5 | ||
|
|
f5960020cd | ||
|
|
8bfc92df50 | ||
|
|
9afee48243 | ||
|
|
7f6fe8a031 | ||
|
|
c824c7e87a | ||
|
|
f44d2784f8 | ||
|
|
740f081606 | ||
|
|
8c6ff25315 | ||
|
|
b77cedba39 | ||
|
|
6415878631 | ||
|
|
ac34701e98 | ||
|
|
4b19db8454 | ||
|
|
af42be1f3b | ||
|
|
aeb0a3ee83 | ||
|
|
33f02f2e1d | ||
|
|
062a745fc9 | ||
|
|
b8a3cfa4f9 | ||
|
|
cee0848b49 | ||
|
|
2b769c9052 | ||
|
|
8f569c42ec | ||
|
|
28b03782f8 | ||
|
|
5ef9f081bd | ||
|
|
1ce209198a | ||
|
|
3192cdcbfa | ||
|
|
983347f370 | ||
|
|
b1929b7eaf | ||
|
|
0a7800c9d9 | ||
|
|
43cb682c24 | ||
|
|
c9e0981955 | ||
|
|
aae0524f8a | ||
|
|
ada476e3c1 | ||
|
|
0ecddd92b6 | ||
|
|
f35d309173 | ||
|
|
3160e8dbca | ||
|
|
012ae48172 | ||
|
|
1c3b8e112e | ||
|
|
ca7b0f75c6 | ||
|
|
8d126bc281 | ||
|
|
2ca5ff2dcd | ||
|
|
7d45cf3dac | ||
|
|
f6edc817df | ||
|
|
3fa6615e92 | ||
|
|
d9ca5fa476 | ||
|
|
89aea5681c | ||
|
|
dd4c36f68a | ||
|
|
3cf96726f6 | ||
|
|
51f5c7fe68 | ||
|
|
8499628a5b | ||
|
|
b2bc6fdda6 | ||
|
|
754a47388d | ||
|
|
f25c8a64f6 | ||
|
|
9b904777d4 | ||
|
|
e14b8e8e2f | ||
|
|
da9be0a27b | ||
|
|
301dca264f | ||
|
|
c74083cfda | ||
|
|
d16375e101 | ||
|
|
abc10b603b | ||
|
|
4a7aeffbf5 | ||
|
|
6bf13bff03 | ||
|
|
3486f0f207 | ||
|
|
580205affc | ||
|
|
2afeca62a1 | ||
|
|
bf5db55bfa | ||
|
|
e56b444cd8 | ||
|
|
5fdbbcbe3a | ||
|
|
635c64eeb7 | ||
|
|
f29da13c2c | ||
|
|
290a55097d | ||
|
|
bda7ff6351 | ||
|
|
da2726449c | ||
|
|
4b88d36b20 | ||
|
|
58c647acf0 | ||
|
|
7a7e53e8d4 | ||
|
|
5cb0964111 | ||
|
|
de419eef44 | ||
|
|
d7759bf876 | ||
|
|
2bd344260e | ||
|
|
c2fb0e4e96 | ||
|
|
00f6526ff5 | ||
|
|
7efc7dbb91 | ||
|
|
ba4a993591 | ||
|
|
f8ef7fa826 | ||
|
|
5e15bb25b4 | ||
|
|
52572ccdd0 | ||
|
|
c6027e4fc7 | ||
|
|
aff6dd5adc | ||
|
|
31bd9c9174 | ||
|
|
d996af554a | ||
|
|
e42f243b52 | ||
|
|
9f18d385cb | ||
|
|
dfbc6c3902 | ||
|
|
8c5f89c035 | ||
|
|
6d038dfbdf | ||
|
|
ec9919a088 | ||
|
|
1512427455 | ||
|
|
440e18c275 | ||
|
|
063161f5af | ||
|
|
2246313344 | ||
|
|
fdc0eae932 | ||
|
|
fa72100d49 | ||
|
|
7c9b837780 | ||
|
|
1c1df68a50 | ||
|
|
4a9d2a37a9 | ||
|
|
05bf46f059 | ||
|
|
420ef86679 | ||
|
|
ae0ac92167 | ||
|
|
26dd3f399e | ||
|
|
33f642dc0b | ||
|
|
3ed1b65b3e | ||
|
|
e0a01d9986 | ||
|
|
c0873c9198 | ||
|
|
374d786812 | ||
|
|
8a307031a9 | ||
|
|
0036ac5254 | ||
|
|
2f3949953a | ||
|
|
d018570bc4 | ||
|
|
bd5294b3f3 | ||
|
|
f16ccf4e3d | ||
|
|
e6c926f7f8 | ||
|
|
7c64170c33 | ||
|
|
177cb142b5 | ||
|
|
2d89ecc140 | ||
|
|
7106da2c6b | ||
|
|
03ece1f81d | ||
|
|
93e1464e6a | ||
|
|
6e4dfaefad | ||
|
|
a2efed2aeb | ||
|
|
8812101cc6 | ||
|
|
a6028923d6 | ||
|
|
cd6c1409fb | ||
|
|
e049c2bd83 | ||
|
|
37c749e507 | ||
|
|
04a0ca0e04 | ||
|
|
2c3e01287a | ||
|
|
b2d0292204 | ||
|
|
cd32569937 | ||
|
|
ed320412b0 | ||
|
|
567fe2a923 | ||
|
|
c7643f08e7 | ||
|
|
96cffc2c7c | ||
|
|
cc0bb5da34 | ||
|
|
5be1d17d5f |
@@ -1,3 +1,5 @@
|
||||
skip: changesIncludeOnly('docs/*', '.pre-commit-config.yaml')
|
||||
|
||||
run_tests: &RUN_TESTS
|
||||
install_cibuildwheel_script:
|
||||
- python -m pip install -e ".[dev]" pytest-custom-exit-code
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
* text=auto
|
||||
|
||||
*.py diff=python
|
||||
*.md diff=markdown
|
||||
|
||||
*.svg -diff
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
dist:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build SDist and wheel
|
||||
run: pipx run build
|
||||
@@ -27,6 +27,9 @@ jobs:
|
||||
needs: [dist]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
environment: pypi
|
||||
permissions:
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
@@ -34,7 +37,4 @@ jobs:
|
||||
name: artifact
|
||||
path: dist
|
||||
|
||||
- uses: pypa/gh-action-pypi-publish@v1.6.4
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_password }}
|
||||
- uses: pypa/gh-action-pypi-publish@release/v1
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- .pre-commit-config.yaml
|
||||
workflow_dispatch:
|
||||
# allow manual runs on branches without a PR
|
||||
|
||||
@@ -19,7 +20,7 @@ jobs:
|
||||
name: Linters (mypy, flake8, etc.)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
@@ -39,9 +40,12 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, windows-latest, macos-11]
|
||||
python_version: ['3.11']
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
python_version: '3.8'
|
||||
timeout-minutes: 180
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
name: Install Python ${{ matrix.python_version }}
|
||||
with:
|
||||
@@ -58,6 +62,13 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install podman
|
||||
|
||||
# free some space to prevent reaching GHA disk space limits
|
||||
- name: Clean docker images
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
docker system prune -a -f
|
||||
df -h
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install ".[test]"
|
||||
@@ -89,7 +100,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 180
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
@@ -99,7 +110,7 @@ jobs:
|
||||
|
||||
- name: Set up QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ jobs:
|
||||
if: github.repository_owner == 'pypa' || github.event_name != 'schedule'
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: wntrblm/nox@2022.11.21
|
||||
- uses: wntrblm/nox@2023.04.22
|
||||
with:
|
||||
python-versions: "3.6, 3.7, 3.8, 3.9, 3.10, 3.11"
|
||||
python-versions: "3.7, 3.8, 3.9, 3.10, 3.11, 3.12-dev"
|
||||
|
||||
- name: "Run update: dependencies"
|
||||
run: nox --force-color -s update_constraints
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
|
||||
# we use this step to grab a Github App auth token, so that PRs generated by this workflow
|
||||
# run the GHA tests.
|
||||
- uses: tibdex/github-app-token@v1
|
||||
- uses: tibdex/github-app-token@v2
|
||||
id: generate-token
|
||||
if: github.ref == 'refs/heads/main' && github.repository == 'pypa/cibuildwheel'
|
||||
with:
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
if: github.ref == 'refs/heads/main' && github.repository == 'pypa/cibuildwheel'
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
commit-message: Update dependencies
|
||||
title: '[Bot] Update dependencies'
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
name: Update the vX.Y tag
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
TAG_NAME:
|
||||
description: 'Tag name that the major.minor tag will point to'
|
||||
required: true
|
||||
|
||||
env:
|
||||
TAG_NAME: ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }}
|
||||
|
||||
jobs:
|
||||
update_tag:
|
||||
name: Update the major.minor tag to include the ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }} changes
|
||||
environment:
|
||||
name: releaseNewActionVersion
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
id: update-major-minor-tag
|
||||
uses: joerick/update-vX.Y-tag-action@v1.0
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
+15
-17
@@ -13,53 +13,51 @@ repos:
|
||||
- id: mixed-line-ending
|
||||
- id: trailing-whitespace
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.1.0
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 23.9.1
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.254
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.0.291
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix"]
|
||||
args: ["--fix", "--show-fixes"]
|
||||
|
||||
- repo: https://github.com/asottile/setup-cfg-fmt
|
||||
rev: v2.2.0
|
||||
rev: v2.4.0
|
||||
hooks:
|
||||
- id: setup-cfg-fmt
|
||||
args: [--include-version-classifiers, --max-py-version=3.11]
|
||||
args: [--include-version-classifiers, --min-py-version=3.8, --max-py-version=3.11]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.0.1
|
||||
rev: v1.5.1
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy 3.7 on cibuildwheel/
|
||||
name: mypy 3.8 on cibuildwheel/
|
||||
exclude: ^cibuildwheel/resources/.*py$
|
||||
args: ["--python-version=3.7"]
|
||||
args: ["--python-version=3.8"]
|
||||
additional_dependencies: &mypy-dependencies
|
||||
- nox
|
||||
- packaging~=21.0
|
||||
- packaging
|
||||
- pygithub
|
||||
- rich
|
||||
- tomli
|
||||
- tomli_w
|
||||
- types-certifi
|
||||
- types-click
|
||||
- types-dataclasses
|
||||
- types-jinja2
|
||||
- types-pyyaml
|
||||
- types-requests
|
||||
- bracex
|
||||
- dataclasses
|
||||
- id: mypy
|
||||
name: mypy 3.10
|
||||
name: mypy 3.11
|
||||
exclude: ^cibuildwheel/resources/.*py$
|
||||
args: ["--python-version=3.10"]
|
||||
args: ["--python-version=3.11"]
|
||||
additional_dependencies: *mypy-dependencies
|
||||
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.9.0.2
|
||||
rev: v0.9.0.5
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
||||
@@ -79,7 +77,7 @@ repos:
|
||||
files: ^docs/changelog.md$
|
||||
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.2
|
||||
rev: v2.2.5
|
||||
hooks:
|
||||
- id: codespell
|
||||
args: ["-L", "sur"]
|
||||
|
||||
+7
-3
@@ -2,13 +2,17 @@
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
version: 2
|
||||
|
||||
mkdocs:
|
||||
configuration: mkdocs.yml
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
python:
|
||||
version: 3.8
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
|
||||
mkdocs:
|
||||
configuration: mkdocs.yml
|
||||
|
||||
+11
-13
@@ -8,21 +8,21 @@ branches:
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: Linux | x86_64 + i686 | Python 3.7
|
||||
python: 3.7
|
||||
- name: Linux | x86_64 + i686 | Python 3.9
|
||||
python: 3.9
|
||||
services: docker
|
||||
env: PYTHON=python
|
||||
|
||||
- name: Linux | arm64 | Python 3.7
|
||||
python: 3.7
|
||||
- name: Linux | arm64 | Python 3.9
|
||||
python: 3.9
|
||||
services: docker
|
||||
arch: arm64-graviton2
|
||||
group: edge
|
||||
virt: vm
|
||||
env: PYTHON=python
|
||||
|
||||
- name: Linux | ppc64le | Python 3.7
|
||||
python: 3.7
|
||||
- name: Linux | ppc64le | Python 3.9
|
||||
python: 3.9
|
||||
services: docker
|
||||
arch: ppc64le
|
||||
allow_failure: True
|
||||
@@ -32,18 +32,16 @@ jobs:
|
||||
# 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"'
|
||||
|
||||
- name: Windows | x86_64 | Python 3.7
|
||||
- name: Windows | x86_64 | Python 3.9
|
||||
os: windows
|
||||
language: shell
|
||||
before_install:
|
||||
- choco upgrade python3 -y --version 3.7.9 --limit-output
|
||||
# Update root certificates to fix SSL error; see http://www.chawn.com/RootCerts.htm
|
||||
- powershell "md C:\temp\certs; CertUtil -generateSSTFromWU C:\temp\certs\RootStore.sst; Get-ChildItem -Path C:\\temp\certs\Rootstore.sst | Import-Certificate -CertStoreLocation Cert:\\LocalMachine\\Root\\ | out-null"
|
||||
- choco upgrade python3 -y --version 3.9.13 --limit-output --params "/InstallDir:C:\\Python39"
|
||||
env:
|
||||
- PYTHON=C:\\Python37\\python
|
||||
- PYTHON=C:\\Python39\\python
|
||||
|
||||
- name: Linux | s390x | Python 3.7
|
||||
python: 3.7
|
||||
- name: Linux | s390x | Python 3.9
|
||||
python: 3.9
|
||||
services: docker
|
||||
arch: s390x
|
||||
env: PYTHON=python
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
This is a summary of the Python versions and platforms covered by the different CI platforms:
|
||||
|
||||
| | 3.7 | 3.8 | 3.9 | 3.10 | 3.11 |
|
||||
|---------|-----------|---------------------------------------|-----------|-----------|----------------|
|
||||
| Linux | Travis CI | AppVeyor¹ / Azure Pipelines / GitLab¹ | CircleCI¹ | Cirrus CI | GitHub Actions |
|
||||
| macOS | Travis CI | AppVeyor¹ / Azure Pipelines | CircleCI¹ | Cirrus CI | GitHub Actions |
|
||||
| Windows | Travis CI | AppVeyor¹ / Azure Pipelines / GitLab¹ | | Cirrus CI | GitHub Actions |
|
||||
| | 3.8 | 3.9 | 3.10 | 3.11 |
|
||||
|---------|--------------------------------------------------------|-----------------------|-----------|----------------|
|
||||
| Linux | AppVeyor¹ / Azure Pipelines / GitLab¹ / GitHub Actions | CircleCI¹ / Travis CI | Cirrus CI | GitHub Actions |
|
||||
| macOS | AppVeyor¹ / Azure Pipelines | CircleCI¹ / Travis CI | Cirrus CI | GitHub Actions |
|
||||
| Windows | AppVeyor¹ / Azure Pipelines / GitLab¹ | Travis CI | Cirrus CI | GitHub Actions |
|
||||
|
||||
> ¹ Runs a reduced set of tests to reduce CI load
|
||||
|
||||
Non-x86 architectures are covered on Travis CI using Python 3.7.
|
||||
Non-x86 architectures are covered on Travis CI using Python 3.9.
|
||||
|
||||
@@ -24,21 +24,24 @@ What does it do?
|
||||
----------------
|
||||
|
||||
| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux<br/>musllinux x86_64 | manylinux<br/>musllinux i686 | manylinux<br/>musllinux aarch64 | manylinux<br/>musllinux ppc64le | manylinux<br/>musllinux s390x |
|
||||
|---------------|----|-----|-----|-----|-----|----|-----|----|-----|-----|
|
||||
| CPython 3.6 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.7 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅³ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| PyPy 3.7 v7.3 | ✅ | N/A | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||
| PyPy 3.8 v7.3 | ✅ | ✅⁴ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||
| PyPy 3.9 v7.3 | ✅ | ✅⁴ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||
|----------------|----|-----|-----|-----|-----|----|-----|----|-----|-----|
|
||||
| CPython 3.6 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.7 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅³ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| CPython 3.12⁵ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| PyPy 3.7 v7.3 | ✅ | N/A | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||
| PyPy 3.8 v7.3 | ✅ | ✅⁴ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||
| PyPy 3.9 v7.3 | ✅ | ✅⁴ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||
| PyPy 3.10 v7.3 | ✅ | ✅⁴ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||
|
||||
<sup>¹ PyPy is only supported for manylinux wheels.</sup><br>
|
||||
<sup>² Windows arm64 support is experimental.</sup><br>
|
||||
<sup>³ Alpine 3.14 and very briefly 3.15's default python3 [was not able to load](https://github.com/pypa/cibuildwheel/issues/934) musllinux wheels. This has been fixed; please upgrade the python package if using Alpine from before the fix.</sup><br>
|
||||
<sup>⁴ Cross-compilation not supported with PyPy - to build these wheels you need to run cibuildwheel on an Apple Silicon machine.</sup><br>
|
||||
<sup>⁵ CPython 3.12 is built by default using Python RCs, starting with cibuildwheel 2.15.</sup><br>
|
||||
|
||||
- Builds manylinux, musllinux, macOS 10.9+, and Windows wheels for CPython and PyPy
|
||||
- Works on GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, CircleCI, GitLab CI, and Cirrus CI
|
||||
@@ -88,13 +91,13 @@ jobs:
|
||||
os: [ubuntu-20.04, windows-2019, macOS-11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Used to host cibuildwheel
|
||||
- uses: actions/setup-python@v3
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: python -m pip install cibuildwheel==2.12.1
|
||||
run: python -m pip install cibuildwheel==2.16.1
|
||||
|
||||
- name: Build wheels
|
||||
run: python -m cibuildwheel --output-dir wheelhouse
|
||||
@@ -158,26 +161,26 @@ Here are some repos that use cibuildwheel.
|
||||
| Name | CI | OS | Notes |
|
||||
|-----------------------------------|----|----|:------|
|
||||
| [scikit-learn][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The machine learning library. A complex but clean config using many of cibuildwheel's features to build a large project with Cython and C++ extensions. |
|
||||
| [NumPy][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The fundamental package for scientific computing with Python. |
|
||||
| [pytorch-fairseq][] | ![github icon][] | ![apple icon][] ![linux icon][] | Facebook AI Research Sequence-to-Sequence Toolkit written in Python. |
|
||||
| [Tornado][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. |
|
||||
| [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. |
|
||||
| [Matplotlib][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The venerable Matplotlib, a Python library with C++ portions |
|
||||
| [NCNN][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | ncnn is a high-performance neural network inference framework optimized for the mobile platform |
|
||||
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
|
||||
| [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. |
|
||||
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | The compiled version of MyPy using MyPyC. |
|
||||
| [pydantic][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Data validation using Python type hints |
|
||||
| [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. |
|
||||
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
|
||||
| [duckdb][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | DuckDB is an in-process SQL OLAP Database Management System |
|
||||
|
||||
[scikit-learn]: https://github.com/scikit-learn/scikit-learn
|
||||
[NumPy]: https://github.com/numpy/numpy
|
||||
[pytorch-fairseq]: https://github.com/pytorch/fairseq
|
||||
[NumPy]: https://github.com/numpy/numpy
|
||||
[Tornado]: https://github.com/tornadoweb/tornado
|
||||
[Matplotlib]: https://github.com/matplotlib/matplotlib
|
||||
[NCNN]: https://github.com/Tencent/ncnn
|
||||
[Kivy]: https://github.com/kivy/kivy
|
||||
[Prophet]: https://github.com/facebook/prophet
|
||||
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
|
||||
[pydantic]: https://github.com/samuelcolvin/pydantic
|
||||
[Prophet]: https://github.com/facebook/prophet
|
||||
[Kivy]: https://github.com/kivy/kivy
|
||||
[duckdb]: https://github.com/duckdb/duckdb
|
||||
|
||||
[appveyor icon]: docs/data/readme_icons/appveyor.svg
|
||||
[github icon]: docs/data/readme_icons/github.svg
|
||||
@@ -210,47 +213,47 @@ Changelog
|
||||
|
||||
<!-- this section was generated by bin/update_readme_changelog.py -- do not edit manually -->
|
||||
|
||||
### v2.12.1
|
||||
### v2.16.1
|
||||
|
||||
_11 March 2023_
|
||||
_26 September 2023_
|
||||
|
||||
- 🐛 Fix a bug that prevented the use of CIBW_CONFIG_SETTINGS with the 'pip' build backend. (#1430)
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0rc3 (#1625)
|
||||
- 🛠 Only calls `linux32` in containers when necessary (#1599)
|
||||
|
||||
### v2.12.0
|
||||
### v2.16.0
|
||||
|
||||
_16 Jan 2023_
|
||||
_18 September 2023_
|
||||
|
||||
- ✨ Adds support for PyPy arm64 wheels. This means that you can build PyPy wheels for Apple Silicon machines. Cross-compilation is not supported for these wheels, so you'll have to build on an Apple Silicon machine. (#1372)
|
||||
- 🛠 Pinned version updates, including PyPy to v7.3.11 and setuptools to 66.0.0.
|
||||
- ✨ Add the ability to pass additional flags to a build frontend through the [CIBW_BUILD_FRONTEND](https://cibuildwheel.readthedocs.io/en/stable/options/#build-frontend) option (#1588).
|
||||
- ✨ The environment variable SOURCE_DATE_EPOCH is now automatically passed through to container Linux builds (useful for [reproducible builds](https://reproducible-builds.org/docs/source-date-epoch/)!) (#1589)
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0rc2 (#1604)
|
||||
- 🐛 Fix `requires_python` auto-detection from setup.py when the call to `setup()` is within an `if __name__ == "__main__" block (#1613)
|
||||
- 🐛 Fix a bug that prevented building Linux wheels in Docker on a Windows host (#1573)
|
||||
- 🐛 `--only` can now select prerelease-pythons (#1564)
|
||||
- 📚 Docs & examples updates (#1582, #1593, #1598, #1615)
|
||||
|
||||
### v2.11.4
|
||||
### v2.15.0
|
||||
|
||||
_24 Dec 2022_
|
||||
_8 August 2023_
|
||||
|
||||
- 🐛 Fix a bug that caused missing wheels on Windows when a test was skipped using CIBW_TEST_SKIP (#1377)
|
||||
- 🛠 Updates CPython 3.11 to 3.11.1 (#1371)
|
||||
- 🛠 Updates PyPy to 7.3.10, except on macOS which remains on 7.3.9 due to a bug on that platform. (#1371)
|
||||
- 📚 Added a reference to abi3audit to the docs (#1347)
|
||||
- 🌟 CPython 3.12 wheels are now built by default - without the CIBW_PRERELEASE_PYTHONS flag. It's time to build and upload these wheels to PyPI! This release includes CPython 3.12.0rc1, which is guaranteed to be ABI compatible with the final release. (#1565)
|
||||
- ✨ Adds musllinux_1_2 support - this allows packagers to build for musl-based Linux distributions on a more recent Alpine image, and a newer musl libc. (#1561)
|
||||
|
||||
### v2.11.3
|
||||
### v2.14.1
|
||||
|
||||
_5 Dec 2022_
|
||||
_15 July 2023_
|
||||
|
||||
- ✨ Improves the 'build options' log output that's printed at the start of each run (#1352)
|
||||
- ✨ Added a friendly error message to a common misconfiguration of the `CIBW_TEST_COMMAND` option - not specifying path using the `{project}` placeholder (#1336)
|
||||
- 🛠 The GitHub Action now uses Powershell on Windows to avoid occasional incompabilities with bash (#1346)
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0b4 (#1550)
|
||||
|
||||
### v2.11.2
|
||||
### v2.14.0
|
||||
|
||||
_26 October 2022_
|
||||
_10 July 2023_
|
||||
|
||||
- 🛠 Updates CPython 3.11 to 3.11.0 - final release (#1327)
|
||||
- 🛠 Simplify the default macOS repair command (#1322)
|
||||
- 🛠 Fix the default `MACOSX_DEPLOYMENT_TARGET` on arm64 (#1312)
|
||||
- 🛠 Hide irrelevant pip warnings on linux (#1311)
|
||||
- 🐛 Fix a bug that caused the stdout and stderr of commands in containers to be in the wrong order Previously, stdout could appear after stderr. (#1324)
|
||||
- 📚 Added [a FAQ entry](https://cibuildwheel.readthedocs.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64) describing how to perform native builds of CPython 3.8 wheels on Apple Silicon. (#1323)
|
||||
- 📚 Other docs improvements
|
||||
- ✨ Adds support for building PyPy 3.10 wheels. (#1525)
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0b3.
|
||||
- ✨ Allow the use of the `{wheel}` placeholder in CIBW_TEST_COMMAND (#1533)
|
||||
- 📚 Docs & examples updates (#1532, #1416)
|
||||
- ⚠️ Removed support for running cibuildwheel in Python 3.7. Python 3.7 is EOL. However, cibuildwheel continues to build Python 3.7 wheels for the moment. (#1175)
|
||||
|
||||
<!-- END bin/update_readme_changelog.py -->
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ runs:
|
||||
- uses: actions/setup-python@v4
|
||||
id: python
|
||||
with:
|
||||
python-version: "3.7 - 3.11"
|
||||
python-version: "3.8 - 3.11"
|
||||
update-environment: false
|
||||
|
||||
# Redirecting stderr to stdout to fix interleaving issue in Actions.
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
pr:
|
||||
paths:
|
||||
exclude:
|
||||
- docs/*
|
||||
- .pre-commit-config.yaml
|
||||
|
||||
jobs:
|
||||
- job: linux_38
|
||||
timeoutInMinutes: 120
|
||||
|
||||
+3
-2
@@ -60,7 +60,7 @@ def bump_version() -> None:
|
||||
print(e)
|
||||
print("Failed to get previous version tag information.")
|
||||
|
||||
git_changes_result = subprocess.run(["git diff-index --quiet HEAD --"], shell=True)
|
||||
git_changes_result = subprocess.run(["git diff-index --quiet HEAD --"], shell=True, check=False)
|
||||
repo_has_uncommitted_changes = git_changes_result.returncode != 0
|
||||
|
||||
if repo_has_uncommitted_changes:
|
||||
@@ -142,7 +142,8 @@ def bump_version() -> None:
|
||||
"pre-commit",
|
||||
"run",
|
||||
"--files=docs/changelog.md",
|
||||
]
|
||||
],
|
||||
check=False,
|
||||
)
|
||||
|
||||
# run pre-commit to check that no errors occurred on the second run
|
||||
|
||||
@@ -15,8 +15,8 @@ the results without the `--online` setting.
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from collections.abc import Iterable, Iterator
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
|
||||
import click
|
||||
import yaml
|
||||
@@ -97,7 +97,7 @@ class MaybeRemote:
|
||||
with open(filename, "w") as f:
|
||||
yaml.safe_dump(self.contents, f, default_flow_style=False)
|
||||
|
||||
def on_each(self, repos: list[str]) -> Iterator[tuple[str, str, str | None]]:
|
||||
def on_each(self, repos: Iterable[str]) -> Iterator[tuple[str, str, str | None]]:
|
||||
for repo in repos:
|
||||
print(f"[bold]{repo}:")
|
||||
for filename in sorted(self.contents, reverse=True):
|
||||
|
||||
@@ -12,13 +12,13 @@ from subprocess import run
|
||||
import click
|
||||
|
||||
|
||||
def shell(cmd, **kwargs):
|
||||
return run([cmd], shell=True, **kwargs)
|
||||
def shell(cmd, *, check: bool, **kwargs):
|
||||
return run([cmd], shell=True, check=check, **kwargs)
|
||||
|
||||
|
||||
def git_repo_has_changes():
|
||||
unstaged_changes = shell("git diff-index --quiet HEAD --").returncode != 0
|
||||
staged_changes = shell("git diff-index --quiet --cached HEAD --").returncode != 0
|
||||
unstaged_changes = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
|
||||
staged_changes = shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
|
||||
return unstaged_changes or staged_changes
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ def main():
|
||||
print("Done.")
|
||||
finally:
|
||||
# remove any local changes
|
||||
shell("git checkout -- .")
|
||||
shell("git checkout -- .", check=True)
|
||||
shell(f"git checkout {previous_branch}", check=True)
|
||||
shell(f"git branch -D --force {branch_name}", check=True)
|
||||
|
||||
|
||||
Regular → Executable
+5
-4
@@ -16,6 +16,7 @@ import functools
|
||||
import textwrap
|
||||
import urllib.request
|
||||
import xml.dom.minidom
|
||||
from collections.abc import Iterable, Mapping, Sequence
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
@@ -42,7 +43,7 @@ ICONS = (
|
||||
class Project:
|
||||
NAME: int = 0
|
||||
|
||||
def __init__(self, config: dict[str, Any], github: Github | None = None):
|
||||
def __init__(self, config: Mapping[str, Any], github: Github | None = None):
|
||||
try:
|
||||
self.name: str = config["name"]
|
||||
self.gh: str = config["gh"]
|
||||
@@ -149,7 +150,7 @@ def path_for_icon(icon_name: str, relative_to: Path | None = None) -> Path:
|
||||
|
||||
|
||||
def get_projects(
|
||||
config: list[dict[str, Any]],
|
||||
config: Iterable[Mapping[str, Any]],
|
||||
*,
|
||||
online: bool = True,
|
||||
auth: str | None = None,
|
||||
@@ -163,7 +164,7 @@ def get_projects(
|
||||
return sorted((Project(item, github) for item in config), reverse=online)
|
||||
|
||||
|
||||
def render_projects(projects: list[Project], *, dest_path: Path, include_info: bool = True):
|
||||
def render_projects(projects: Sequence[Project], *, dest_path: Path, include_info: bool = True):
|
||||
io = StringIO()
|
||||
print = functools.partial(builtins.print, file=io)
|
||||
|
||||
@@ -191,7 +192,7 @@ def render_projects(projects: list[Project], *, dest_path: Path, include_info: b
|
||||
def insert_projects_table(
|
||||
file: Path,
|
||||
*,
|
||||
projects: list[Project],
|
||||
projects: Sequence[Project],
|
||||
input_filename: str,
|
||||
include_info: bool = True,
|
||||
):
|
||||
|
||||
@@ -16,13 +16,13 @@ from urllib.parse import quote
|
||||
import click
|
||||
|
||||
|
||||
def shell(cmd, **kwargs):
|
||||
return run([cmd], shell=True, **kwargs)
|
||||
def shell(cmd, *, check: bool, **kwargs):
|
||||
return run([cmd], shell=True, check=check, **kwargs)
|
||||
|
||||
|
||||
def git_repo_has_changes():
|
||||
unstaged_changes = shell("git diff-index --quiet HEAD --").returncode != 0
|
||||
staged_changes = shell("git diff-index --quiet --cached HEAD --").returncode != 0
|
||||
unstaged_changes = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
|
||||
staged_changes = shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
|
||||
return unstaged_changes or staged_changes
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ def run_example_ci_configs(config_files=None):
|
||||
finally:
|
||||
# remove any local changes
|
||||
shutil.rmtree(example_project, ignore_errors=True)
|
||||
shell("git checkout -- .")
|
||||
shell("git checkout -- .", check=True)
|
||||
shell(f"git checkout {previous_branch}", check=True)
|
||||
shell(f"git branch -D --force {branch_name}", check=True)
|
||||
|
||||
|
||||
+5
-1
@@ -24,4 +24,8 @@ if __name__ == "__main__":
|
||||
check=True,
|
||||
)
|
||||
|
||||
sys.exit(subprocess.run([sys.executable, "-m", "cibuildwheel"], cwd=project_dir).returncode)
|
||||
sys.exit(
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "cibuildwheel"], cwd=project_dir, check=False
|
||||
).returncode
|
||||
)
|
||||
|
||||
@@ -59,6 +59,12 @@ images = [
|
||||
Image("musllinux_1_1", "aarch64", "quay.io/pypa/musllinux_1_1_aarch64", None),
|
||||
Image("musllinux_1_1", "ppc64le", "quay.io/pypa/musllinux_1_1_ppc64le", None),
|
||||
Image("musllinux_1_1", "s390x", "quay.io/pypa/musllinux_1_1_s390x", None),
|
||||
# musllinux_1_2 images
|
||||
Image("musllinux_1_2", "x86_64", "quay.io/pypa/musllinux_1_2_x86_64", None),
|
||||
Image("musllinux_1_2", "i686", "quay.io/pypa/musllinux_1_2_i686", None),
|
||||
Image("musllinux_1_2", "aarch64", "quay.io/pypa/musllinux_1_2_aarch64", None),
|
||||
Image("musllinux_1_2", "ppc64le", "quay.io/pypa/musllinux_1_2_ppc64le", None),
|
||||
Image("musllinux_1_2", "s390x", "quay.io/pypa/musllinux_1_2_s390x", None),
|
||||
]
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
Regular → Executable
+1
-1
@@ -19,7 +19,7 @@ except ImportError:
|
||||
|
||||
|
||||
def main():
|
||||
subprocess.run(["mkdocs", "build"])
|
||||
subprocess.run(["mkdocs", "build"], check=True)
|
||||
|
||||
hti = Html2Image(custom_flags=["--force-device-scale-factor=2"])
|
||||
|
||||
|
||||
+10
-16
@@ -5,26 +5,20 @@ from __future__ import annotations
|
||||
import copy
|
||||
import difflib
|
||||
import logging
|
||||
import sys
|
||||
from collections.abc import Mapping, MutableMapping
|
||||
from pathlib import Path
|
||||
from typing import Any, Union
|
||||
from typing import Any, Final, Literal, TypedDict, Union
|
||||
|
||||
import click
|
||||
import requests
|
||||
import rich
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
|
||||
from packaging.specifiers import Specifier
|
||||
from packaging.version import Version
|
||||
from rich.logging import RichHandler
|
||||
from rich.syntax import Syntax
|
||||
|
||||
from cibuildwheel._compat import tomllib
|
||||
from cibuildwheel.extra import dump_python_configurations
|
||||
from cibuildwheel.typing import Final, Literal, TypedDict
|
||||
|
||||
log = logging.getLogger("cibw")
|
||||
|
||||
@@ -93,7 +87,7 @@ class WindowsVersions:
|
||||
unsorted_versions = spec.filter(self.version_dict)
|
||||
versions = sorted(unsorted_versions, reverse=True)
|
||||
|
||||
log.debug(f"Windows {self.arch} {spec} has {', '.join(str(v) for v in versions)}")
|
||||
log.debug("Windows %s %s has %s", self.arch, spec, ", ".join(str(v) for v in versions))
|
||||
|
||||
if not versions:
|
||||
return None
|
||||
@@ -124,7 +118,7 @@ class PyPyVersions:
|
||||
]
|
||||
self.arch = arch_str
|
||||
|
||||
def get_arch_file(self, release: dict[str, Any]) -> str:
|
||||
def get_arch_file(self, release: Mapping[str, Any]) -> str:
|
||||
urls: list[str] = [
|
||||
rf["download_url"]
|
||||
for rf in release["files"]
|
||||
@@ -134,7 +128,7 @@ class PyPyVersions:
|
||||
|
||||
def update_version_windows(self, spec: Specifier) -> ConfigWinCP:
|
||||
releases = [r for r in self.releases if spec.contains(r["python_version"])]
|
||||
releases = sorted(releases, key=lambda r: r["pypy_version"]) # type: ignore[no-any-return]
|
||||
releases = sorted(releases, key=lambda r: r["pypy_version"])
|
||||
releases = [r for r in releases if self.get_arch_file(r)]
|
||||
|
||||
if not releases:
|
||||
@@ -161,7 +155,7 @@ class PyPyVersions:
|
||||
raise RuntimeError(msg)
|
||||
|
||||
releases = [r for r in self.releases if spec.contains(r["python_version"])]
|
||||
releases = sorted(releases, key=lambda r: r["pypy_version"]) # type: ignore[no-any-return]
|
||||
releases = sorted(releases, key=lambda r: r["pypy_version"])
|
||||
|
||||
if not releases:
|
||||
msg = f"PyPy macOS {self.arch} not found for {spec}!"
|
||||
@@ -250,11 +244,11 @@ class AllVersions:
|
||||
self.macos_pypy = PyPyVersions("64")
|
||||
self.macos_pypy_arm64 = PyPyVersions("ARM64")
|
||||
|
||||
def update_config(self, config: dict[str, str]) -> None:
|
||||
def update_config(self, config: MutableMapping[str, str]) -> None:
|
||||
identifier = config["identifier"]
|
||||
version = Version(config["version"])
|
||||
spec = Specifier(f"=={version.major}.{version.minor}.*")
|
||||
log.info(f"Reading in '{identifier}' -> {spec} @ {version}")
|
||||
log.info("Reading in %r -> %s @ %s", str(identifier), spec, version)
|
||||
orig_config = copy.copy(config)
|
||||
config_update: AnyConfig | None = None
|
||||
|
||||
@@ -282,7 +276,7 @@ class AllVersions:
|
||||
config.update(**config_update)
|
||||
|
||||
if config != orig_config:
|
||||
log.info(f" Updated {orig_config} to {config}")
|
||||
log.info(" Updated %s to %s", orig_config, config)
|
||||
|
||||
|
||||
@click.command()
|
||||
|
||||
@@ -5,23 +5,17 @@ from __future__ import annotations
|
||||
import difflib
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
import click
|
||||
import rich
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
|
||||
from packaging.version import InvalidVersion, Version
|
||||
from rich.logging import RichHandler
|
||||
from rich.syntax import Syntax
|
||||
|
||||
from cibuildwheel.typing import Final
|
||||
from cibuildwheel._compat import tomllib
|
||||
|
||||
log = logging.getLogger("cibw")
|
||||
|
||||
@@ -54,14 +48,18 @@ def git_ls_remote_versions(url) -> list[VersionTuple]:
|
||||
try:
|
||||
version = Version(version_string)
|
||||
if version.is_devrelease:
|
||||
log.info(f"Ignoring development release '{version}'")
|
||||
log.info("Ignoring development release %r", str(version))
|
||||
continue
|
||||
if version.is_prerelease:
|
||||
log.info(f"Ignoring pre-release '{version}'")
|
||||
log.info("Ignoring pre-release %r", str(version))
|
||||
continue
|
||||
# Do not upgrade past 20.22.0 to keep python 3.6 compat
|
||||
if version >= Version("20.22.0"):
|
||||
log.info("Ignoring %r which is not compatible with python 3.6", str(version))
|
||||
continue
|
||||
versions.append(VersionTuple(version, version_string))
|
||||
except InvalidVersion:
|
||||
log.warning(f"Ignoring ref '{ref}'")
|
||||
log.warning("Ignoring ref %r", ref)
|
||||
versions.sort(reverse=True)
|
||||
return versions
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from __future__ import annotations
|
||||
|
||||
__version__ = "2.12.1"
|
||||
__version__ = "2.16.1"
|
||||
|
||||
+101
-92
@@ -7,18 +7,21 @@ import sys
|
||||
import tarfile
|
||||
import textwrap
|
||||
import typing
|
||||
from collections.abc import Iterable, Sequence, Set
|
||||
from pathlib import Path
|
||||
from tempfile import mkdtemp
|
||||
from typing import Protocol
|
||||
|
||||
import cibuildwheel
|
||||
import cibuildwheel.linux
|
||||
import cibuildwheel.macos
|
||||
import cibuildwheel.util
|
||||
import cibuildwheel.windows
|
||||
from cibuildwheel._compat.typing import assert_never
|
||||
from cibuildwheel.architecture import Architecture, allowed_architectures_check
|
||||
from cibuildwheel.logger import log
|
||||
from cibuildwheel.options import CommandLineArguments, Options, compute_options
|
||||
from cibuildwheel.typing import PLATFORMS, PlatformName, assert_never
|
||||
from cibuildwheel.typing import PLATFORMS, GenericPythonConfiguration, PlatformName
|
||||
from cibuildwheel.util import (
|
||||
CIBW_CACHE_PATH,
|
||||
BuildSelector,
|
||||
@@ -167,70 +170,102 @@ def main() -> None:
|
||||
log.warning(f"Can't delete temporary folder '{temp_dir}'")
|
||||
|
||||
|
||||
def build_in_directory(args: CommandLineArguments) -> None:
|
||||
def _compute_platform_only(only: str) -> PlatformName:
|
||||
if "linux_" in only:
|
||||
return "linux"
|
||||
if "macosx_" in only:
|
||||
return "macos"
|
||||
if "win_" in only or "win32" in only:
|
||||
return "windows"
|
||||
print(
|
||||
f"Invalid --only='{only}', must be a build selector with a known platform",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
def _compute_platform_ci() -> PlatformName:
|
||||
if detect_ci_provider() is None:
|
||||
print(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
cibuildwheel: Unable to detect platform. cibuildwheel should run on your CI server;
|
||||
Travis CI, AppVeyor, Azure Pipelines, GitHub Actions, CircleCI, Gitlab, and Cirrus CI
|
||||
are supported. You can run on your development machine or other CI providers
|
||||
using the --platform argument. Check --help output for more information.
|
||||
"""
|
||||
),
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
if sys.platform.startswith("linux"):
|
||||
return "linux"
|
||||
elif sys.platform == "darwin":
|
||||
return "macos"
|
||||
elif sys.platform == "win32":
|
||||
return "windows"
|
||||
else:
|
||||
print(
|
||||
'cibuildwheel: Unable to detect platform from "sys.platform" in a CI environment. You can run '
|
||||
"cibuildwheel using the --platform argument. Check --help output for more information.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
def _compute_platform(args: CommandLineArguments) -> PlatformName:
|
||||
platform_option_value = args.platform or os.environ.get("CIBW_PLATFORM", "auto")
|
||||
platform: PlatformName
|
||||
|
||||
if args.only and args.platform is not None:
|
||||
print(
|
||||
"--platform cannot be specified with --only, it is computed from --only",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
if args.only and args.archs is not None:
|
||||
print(
|
||||
"--arch cannot be specified with --only, it is computed from --only",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
|
||||
if platform_option_value not in PLATFORMS | {"auto"}:
|
||||
print(f"cibuildwheel: Unsupported platform: {platform_option_value}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
if args.only:
|
||||
if "linux_" in args.only:
|
||||
platform = "linux"
|
||||
elif "macosx_" in args.only:
|
||||
platform = "macos"
|
||||
elif "win_" in args.only or "win32" in args.only:
|
||||
platform = "windows"
|
||||
else:
|
||||
print(
|
||||
f"Invalid --only='{args.only}', must be a build selector with a known platform",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
if args.platform is not None:
|
||||
print(
|
||||
"--platform cannot be specified with --only, it is computed from --only",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
if args.archs is not None:
|
||||
print(
|
||||
"--arch cannot be specified with --only, it is computed from --only",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
return _compute_platform_only(args.only)
|
||||
elif platform_option_value != "auto":
|
||||
if platform_option_value not in PLATFORMS:
|
||||
print(f"cibuildwheel: Unsupported platform: {platform_option_value}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
return typing.cast(PlatformName, platform_option_value)
|
||||
|
||||
platform = typing.cast(PlatformName, platform_option_value)
|
||||
else:
|
||||
ci_provider = detect_ci_provider()
|
||||
if ci_provider is None:
|
||||
print(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
cibuildwheel: Unable to detect platform. cibuildwheel should run on your CI server;
|
||||
Travis CI, AppVeyor, Azure Pipelines, GitHub Actions, CircleCI, Gitlab, and Cirrus CI
|
||||
are supported. You can run on your development machine or other CI providers
|
||||
using the --platform argument. Check --help output for more information.
|
||||
"""
|
||||
),
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
if sys.platform.startswith("linux"):
|
||||
platform = "linux"
|
||||
elif sys.platform == "darwin":
|
||||
platform = "macos"
|
||||
elif sys.platform == "win32":
|
||||
platform = "windows"
|
||||
else:
|
||||
print(
|
||||
'cibuildwheel: Unable to detect platform from "sys.platform" in a CI environment. You can run '
|
||||
"cibuildwheel using the --platform argument. Check --help output for more information.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(2)
|
||||
return _compute_platform_ci()
|
||||
|
||||
|
||||
class PlatformModule(Protocol):
|
||||
# note that as per PEP544, the self argument is ignored when the protocol
|
||||
# is applied to a module
|
||||
def get_python_configurations(
|
||||
self, build_selector: BuildSelector, architectures: Set[Architecture]
|
||||
) -> Sequence[GenericPythonConfiguration]:
|
||||
...
|
||||
|
||||
def build(self, options: Options, tmp_path: Path) -> None:
|
||||
...
|
||||
|
||||
|
||||
# pylint: disable-next=inconsistent-return-statements
|
||||
def get_platform_module(platform: PlatformName) -> PlatformModule:
|
||||
if platform == "linux":
|
||||
return cibuildwheel.linux
|
||||
if platform == "windows":
|
||||
return cibuildwheel.windows
|
||||
if platform == "macos":
|
||||
return cibuildwheel.macos
|
||||
assert_never(platform)
|
||||
|
||||
|
||||
def build_in_directory(args: CommandLineArguments) -> None:
|
||||
platform: PlatformName = _compute_platform(args)
|
||||
options = compute_options(platform=platform, command_line_arguments=args, env=os.environ)
|
||||
|
||||
package_dir = options.globals.package_dir
|
||||
@@ -242,8 +277,9 @@ def build_in_directory(args: CommandLineArguments) -> None:
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
platform_module = get_platform_module(platform)
|
||||
identifiers = get_build_identifiers(
|
||||
platform=platform,
|
||||
platform_module=platform_module,
|
||||
build_selector=options.globals.build_selector,
|
||||
architectures=options.globals.architectures,
|
||||
)
|
||||
@@ -289,14 +325,7 @@ def build_in_directory(args: CommandLineArguments) -> None:
|
||||
with cibuildwheel.util.print_new_wheels(
|
||||
"\n{n} wheels produced in {m:.0f} minutes:", output_dir
|
||||
):
|
||||
if platform == "linux":
|
||||
cibuildwheel.linux.build(options, tmp_path)
|
||||
elif platform == "windows":
|
||||
cibuildwheel.windows.build(options, tmp_path)
|
||||
elif platform == "macos":
|
||||
cibuildwheel.macos.build(options, tmp_path)
|
||||
else:
|
||||
assert_never(platform)
|
||||
platform_module.build(options, tmp_path)
|
||||
finally:
|
||||
# avoid https://github.com/python/cpython/issues/86962 by performing
|
||||
# cleanup manually
|
||||
@@ -305,7 +334,7 @@ def build_in_directory(args: CommandLineArguments) -> None:
|
||||
log.warning(f"Can't delete temporary folder '{tmp_path}'")
|
||||
|
||||
|
||||
def print_preamble(platform: str, options: Options, identifiers: list[str]) -> None:
|
||||
def print_preamble(platform: str, options: Options, identifiers: Sequence[str]) -> None:
|
||||
print(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
@@ -339,33 +368,13 @@ def print_preamble(platform: str, options: Options, identifiers: list[str]) -> N
|
||||
|
||||
|
||||
def get_build_identifiers(
|
||||
platform: PlatformName, build_selector: BuildSelector, architectures: set[Architecture]
|
||||
platform_module: PlatformModule, build_selector: BuildSelector, architectures: Set[Architecture]
|
||||
) -> list[str]:
|
||||
python_configurations: (
|
||||
list[cibuildwheel.linux.PythonConfiguration]
|
||||
| list[cibuildwheel.windows.PythonConfiguration]
|
||||
| list[cibuildwheel.macos.PythonConfiguration]
|
||||
)
|
||||
|
||||
if platform == "linux":
|
||||
python_configurations = cibuildwheel.linux.get_python_configurations(
|
||||
build_selector, architectures
|
||||
)
|
||||
elif platform == "windows":
|
||||
python_configurations = cibuildwheel.windows.get_python_configurations(
|
||||
build_selector, architectures
|
||||
)
|
||||
elif platform == "macos":
|
||||
python_configurations = cibuildwheel.macos.get_python_configurations(
|
||||
build_selector, architectures
|
||||
)
|
||||
else:
|
||||
assert_never(platform)
|
||||
|
||||
python_configurations = platform_module.get_python_configurations(build_selector, architectures)
|
||||
return [config.identifier for config in python_configurations]
|
||||
|
||||
|
||||
def detect_warnings(*, options: Options, identifiers: list[str]) -> list[str]:
|
||||
def detect_warnings(*, options: Options, identifiers: Iterable[str]) -> list[str]:
|
||||
warnings = []
|
||||
|
||||
# warn about deprecated {python} and {pip}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from __future__ import annotations
|
||||
@@ -0,0 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from tomllib import load
|
||||
else:
|
||||
from tomli import load
|
||||
|
||||
__all__ = ("load",)
|
||||
@@ -0,0 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3, 11):
|
||||
from typing_extensions import NotRequired, assert_never
|
||||
else:
|
||||
from typing import NotRequired, assert_never
|
||||
|
||||
__all__ = (
|
||||
"assert_never",
|
||||
"NotRequired",
|
||||
)
|
||||
@@ -4,11 +4,18 @@ import functools
|
||||
import platform as platform_module
|
||||
import re
|
||||
import sys
|
||||
from collections.abc import Set
|
||||
from enum import Enum
|
||||
from typing import Final, Literal
|
||||
|
||||
from .typing import Final, Literal, PlatformName, assert_never
|
||||
from ._compat.typing import assert_never
|
||||
from .typing import PlatformName
|
||||
|
||||
PRETTY_NAMES: Final = {"linux": "Linux", "macos": "macOS", "windows": "Windows"}
|
||||
PRETTY_NAMES: Final[dict[PlatformName, str]] = {
|
||||
"linux": "Linux",
|
||||
"macos": "macOS",
|
||||
"windows": "Windows",
|
||||
}
|
||||
|
||||
ARCH_SYNONYMS: Final[list[dict[PlatformName, str | None]]] = [
|
||||
{"linux": "x86_64", "macos": "x86_64", "windows": "AMD64"},
|
||||
@@ -132,7 +139,7 @@ class Architecture(Enum):
|
||||
|
||||
def allowed_architectures_check(
|
||||
platform: PlatformName,
|
||||
architectures: set[Architecture],
|
||||
architectures: Set[Architecture],
|
||||
) -> None:
|
||||
allowed_architectures = Architecture.all_archs(platform)
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from collections.abc import Iterable, Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, Dict, List, Sequence
|
||||
from typing import Callable, Dict, List # noqa: TID251
|
||||
|
||||
import bashlex
|
||||
|
||||
@@ -10,7 +11,7 @@ import bashlex
|
||||
EnvironmentExecutor = Callable[[List[str], Dict[str, str]], str]
|
||||
|
||||
|
||||
def local_environment_executor(command: list[str], env: dict[str, str]) -> str:
|
||||
def local_environment_executor(command: Sequence[str], env: Mapping[str, str]) -> str:
|
||||
return subprocess.run(command, env=env, text=True, stdout=subprocess.PIPE, check=True).stdout
|
||||
|
||||
|
||||
@@ -22,7 +23,7 @@ class NodeExecutionContext:
|
||||
|
||||
|
||||
def evaluate(
|
||||
value: str, environment: dict[str, str], executor: EnvironmentExecutor | None = None
|
||||
value: str, environment: Mapping[str, str], executor: EnvironmentExecutor | None = None
|
||||
) -> str:
|
||||
if not value:
|
||||
# empty string evaluates to empty string
|
||||
@@ -40,7 +41,9 @@ def evaluate(
|
||||
return evaluate_node(
|
||||
value_word_node,
|
||||
context=NodeExecutionContext(
|
||||
environment=environment, input=value, executor=executor or local_environment_executor
|
||||
environment=dict(environment),
|
||||
input=value,
|
||||
executor=executor or local_environment_executor,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -105,7 +108,7 @@ def evaluate_nodes_as_compound_command(
|
||||
|
||||
|
||||
def evaluate_nodes_as_simple_command(
|
||||
nodes: list[bashlex.ast.node], context: NodeExecutionContext
|
||||
nodes: Iterable[bashlex.ast.node], context: NodeExecutionContext
|
||||
) -> str:
|
||||
command = [evaluate_node(part, context=context) for part in nodes]
|
||||
return context.executor(command, context.environment)
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from typing import Any, Mapping, Sequence
|
||||
from collections.abc import Mapping, Sequence
|
||||
from typing import Any, Protocol
|
||||
|
||||
import bashlex
|
||||
import bashlex.errors
|
||||
|
||||
from cibuildwheel.typing import Protocol
|
||||
|
||||
from . import bashlex_eval
|
||||
|
||||
|
||||
@@ -54,7 +53,7 @@ class EnvironmentAssignment(Protocol):
|
||||
def evaluated_value(
|
||||
self,
|
||||
*,
|
||||
environment: dict[str, str],
|
||||
environment: Mapping[str, str],
|
||||
executor: bashlex_eval.EnvironmentExecutor | None = None,
|
||||
) -> str:
|
||||
"""Returns the value of this assignment, as evaluated in the environment"""
|
||||
@@ -91,7 +90,7 @@ class EnvironmentAssignmentBash:
|
||||
|
||||
def evaluated_value(
|
||||
self,
|
||||
environment: dict[str, str],
|
||||
environment: Mapping[str, str],
|
||||
executor: bashlex_eval.EnvironmentExecutor | None = None,
|
||||
) -> str:
|
||||
return bashlex_eval.evaluate(self.value, environment=environment, executor=executor)
|
||||
|
||||
@@ -4,9 +4,9 @@ These are utilities for the `/bin` scripts, not for the `cibuildwheel` program.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping, Sequence
|
||||
from io import StringIO
|
||||
|
||||
from .typing import Protocol
|
||||
from typing import Protocol
|
||||
|
||||
__all__ = ("Printable", "dump_python_configurations")
|
||||
|
||||
@@ -16,7 +16,9 @@ class Printable(Protocol):
|
||||
...
|
||||
|
||||
|
||||
def dump_python_configurations(inp: dict[str, dict[str, list[dict[str, Printable]]]]) -> str:
|
||||
def dump_python_configurations(
|
||||
inp: Mapping[str, Mapping[str, Sequence[Mapping[str, Printable]]]]
|
||||
) -> str:
|
||||
output = StringIO()
|
||||
for header, values in inp.items():
|
||||
output.write(f"[{header}]\n")
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from threading import RLock
|
||||
from typing import Any, Callable, Generic, TypeVar, overload
|
||||
|
||||
__all__ = ["cached_property"]
|
||||
|
||||
_NOT_FOUND = object()
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class cached_property(Generic[_T]):
|
||||
def __init__(self, func: Callable[[Any], _T]):
|
||||
self.func = func
|
||||
self.attrname: str | None = None
|
||||
self.__doc__ = func.__doc__
|
||||
self.lock = RLock()
|
||||
|
||||
def __set_name__(self, owner: type[Any], name: str) -> None:
|
||||
if self.attrname is None:
|
||||
self.attrname = name
|
||||
elif name != self.attrname:
|
||||
msg = f"Cannot assign the same cached_property to two different names ({self.attrname!r} and {name!r})."
|
||||
raise TypeError(msg)
|
||||
|
||||
@overload
|
||||
def __get__(self, instance: None, owner: type[Any] | None = ...) -> cached_property[_T]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __get__(self, instance: object, owner: type[Any] | None = ...) -> _T:
|
||||
...
|
||||
|
||||
def __get__(self, instance: object | None, owner: type[Any] | None = None) -> Any:
|
||||
if instance is None:
|
||||
return self
|
||||
if self.attrname is None:
|
||||
msg = "Cannot use cached_property instance without calling __set_name__ on it."
|
||||
raise TypeError(msg)
|
||||
try:
|
||||
cache = instance.__dict__
|
||||
except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
|
||||
msg = (
|
||||
f"No '__dict__' attribute on {type(instance).__name__!r} "
|
||||
f"instance to cache {self.attrname!r} property."
|
||||
)
|
||||
raise TypeError(msg) from None
|
||||
val = cache.get(self.attrname, _NOT_FOUND)
|
||||
if val is _NOT_FOUND:
|
||||
with self.lock:
|
||||
# check if another thread filled cache while we awaited lock
|
||||
val = cache.get(self.attrname, _NOT_FOUND)
|
||||
if val is _NOT_FOUND:
|
||||
val = self.func(instance)
|
||||
try:
|
||||
cache[self.attrname] = val
|
||||
except TypeError:
|
||||
msg = (
|
||||
f"The '__dict__' attribute on {type(instance).__name__!r} instance "
|
||||
f"does not support item assignment for caching {self.attrname!r} property."
|
||||
)
|
||||
raise TypeError(msg) from None
|
||||
return val
|
||||
+25
-19
@@ -3,17 +3,20 @@ from __future__ import annotations
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
from collections.abc import Iterable, Iterator, Sequence, Set
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path, PurePath, PurePosixPath
|
||||
from typing import Iterator, Tuple
|
||||
from typing import OrderedDict, Tuple
|
||||
|
||||
from ._compat.typing import assert_never
|
||||
from .architecture import Architecture
|
||||
from .logger import log
|
||||
from .oci_container import OCIContainer
|
||||
from .options import Options
|
||||
from .typing import OrderedDict, PathOrStr, assert_never
|
||||
from .typing import PathOrStr
|
||||
from .util import (
|
||||
AlreadyBuiltWheelError,
|
||||
BuildFrontendConfig,
|
||||
BuildSelector,
|
||||
NonPlatformWheelError,
|
||||
find_compatible_wheel,
|
||||
@@ -46,7 +49,7 @@ class BuildStep:
|
||||
|
||||
def get_python_configurations(
|
||||
build_selector: BuildSelector,
|
||||
architectures: set[Architecture],
|
||||
architectures: Set[Architecture],
|
||||
) -> list[PythonConfiguration]:
|
||||
full_python_configs = read_python_configs("linux")
|
||||
|
||||
@@ -111,7 +114,7 @@ def get_build_steps(
|
||||
|
||||
|
||||
def check_all_python_exist(
|
||||
*, platform_configs: list[PythonConfiguration], container: OCIContainer
|
||||
*, platform_configs: Iterable[PythonConfiguration], container: OCIContainer
|
||||
) -> None:
|
||||
exist = True
|
||||
messages = []
|
||||
@@ -136,7 +139,7 @@ def check_all_python_exist(
|
||||
def build_in_container(
|
||||
*,
|
||||
options: Options,
|
||||
platform_configs: list[PythonConfiguration],
|
||||
platform_configs: Sequence[PythonConfiguration],
|
||||
container: OCIContainer,
|
||||
container_project_path: PurePath,
|
||||
container_package_dir: PurePath,
|
||||
@@ -174,6 +177,7 @@ def build_in_container(
|
||||
for config in platform_configs:
|
||||
log.build_start(config.identifier)
|
||||
build_options = options.build_options(config.identifier)
|
||||
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||
|
||||
dependency_constraint_flags: list[PathOrStr] = []
|
||||
|
||||
@@ -181,7 +185,7 @@ def build_in_container(
|
||||
constraints_file = build_options.dependency_constraints.get_for_python_version(
|
||||
config.version
|
||||
)
|
||||
container_constraints_file = PurePath("/constraints.txt")
|
||||
container_constraints_file = PurePosixPath("/constraints.txt")
|
||||
|
||||
container.copy_into(constraints_file, container_constraints_file)
|
||||
dependency_constraint_flags = ["-c", container_constraints_file]
|
||||
@@ -239,13 +243,11 @@ def build_in_container(
|
||||
container.call(["rm", "-rf", built_wheel_dir])
|
||||
container.call(["mkdir", "-p", built_wheel_dir])
|
||||
|
||||
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||
extra_flags = split_config_settings(
|
||||
build_options.config_settings, build_options.build_frontend
|
||||
)
|
||||
extra_flags = split_config_settings(build_options.config_settings, build_frontend.name)
|
||||
extra_flags += build_frontend.args
|
||||
|
||||
if build_options.build_frontend == "pip":
|
||||
extra_flags += verbosity_flags
|
||||
if build_frontend.name == "pip":
|
||||
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||
container.call(
|
||||
[
|
||||
"python",
|
||||
@@ -259,9 +261,10 @@ def build_in_container(
|
||||
],
|
||||
env=env,
|
||||
)
|
||||
elif build_options.build_frontend == "build":
|
||||
verbosity_setting = " ".join(verbosity_flags)
|
||||
extra_flags += (f"--config-setting={verbosity_setting}",)
|
||||
elif build_frontend.name == "build":
|
||||
if not 0 <= build_options.build_verbosity < 2:
|
||||
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
||||
log.warning(msg)
|
||||
container.call(
|
||||
[
|
||||
"python",
|
||||
@@ -275,7 +278,7 @@ def build_in_container(
|
||||
env=env,
|
||||
)
|
||||
else:
|
||||
assert_never(build_options.build_frontend)
|
||||
assert_never(build_frontend)
|
||||
|
||||
built_wheel = container.glob(built_wheel_dir, "*.whl")[0]
|
||||
|
||||
@@ -347,6 +350,7 @@ def build_in_container(
|
||||
build_options.test_command,
|
||||
project=container_project_path,
|
||||
package=container_package_dir,
|
||||
wheel=wheel_to_test,
|
||||
)
|
||||
test_cwd = testing_temp_dir / "test_cwd"
|
||||
container.call(["mkdir", "-p", test_cwd])
|
||||
@@ -377,7 +381,9 @@ def build(options: Options, tmp_path: Path) -> None: # noqa: ARG001
|
||||
try:
|
||||
# check the container engine is installed
|
||||
subprocess.run(
|
||||
[options.globals.container_engine, "--version"], check=True, stdout=subprocess.DEVNULL
|
||||
[options.globals.container_engine.name, "--version"],
|
||||
check=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
print(
|
||||
@@ -417,7 +423,7 @@ def build(options: Options, tmp_path: Path) -> None: # noqa: ARG001
|
||||
|
||||
with OCIContainer(
|
||||
image=build_step.container_image,
|
||||
simulate_32_bit=build_step.platform_tag.endswith("i686"),
|
||||
enforce_32_bit=build_step.platform_tag.endswith("i686"),
|
||||
cwd=container_project_path,
|
||||
engine=options.globals.container_engine,
|
||||
) as container:
|
||||
@@ -437,7 +443,7 @@ def build(options: Options, tmp_path: Path) -> None: # noqa: ARG001
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _matches_prepared_command(error_cmd: list[str], command_template: str) -> bool:
|
||||
def _matches_prepared_command(error_cmd: Sequence[str], command_template: str) -> bool:
|
||||
if len(error_cmd) < 3 or error_cmd[0:2] != ["sh", "-c"]:
|
||||
return False
|
||||
command_prefix = command_template.split("{", maxsplit=1)[0].strip()
|
||||
|
||||
@@ -5,19 +5,19 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from typing import IO, AnyStr
|
||||
from typing import IO, AnyStr, Final, Tuple
|
||||
|
||||
from cibuildwheel.typing import Final
|
||||
from cibuildwheel.util import CIProvider, detect_ci_provider
|
||||
from .util import CIProvider, detect_ci_provider
|
||||
|
||||
DEFAULT_FOLD_PATTERN: Final = ("{name}", "")
|
||||
FOLD_PATTERNS: Final = {
|
||||
FoldPattern = Tuple[str, str]
|
||||
DEFAULT_FOLD_PATTERN: Final[FoldPattern] = ("{name}", "")
|
||||
FOLD_PATTERNS: Final[dict[str, FoldPattern]] = {
|
||||
"azure": ("##[group]{name}", "##[endgroup]"),
|
||||
"travis": ("travis_fold:start:{identifier}\n{name}", "travis_fold:end:{identifier}"),
|
||||
"github": ("::group::{name}", "::endgroup::{name}"),
|
||||
}
|
||||
|
||||
PLATFORM_IDENTIFIER_DESCRIPTIONS: Final = {
|
||||
PLATFORM_IDENTIFIER_DESCRIPTIONS: Final[dict[str, str]] = {
|
||||
"manylinux_x86_64": "manylinux x86_64",
|
||||
"manylinux_i686": "manylinux i686",
|
||||
"manylinux_aarch64": "manylinux aarch64",
|
||||
|
||||
+22
-15
@@ -8,21 +8,25 @@ import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import typing
|
||||
from collections.abc import Sequence, Set
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Sequence, Tuple, cast
|
||||
from typing import Literal, Tuple
|
||||
|
||||
from filelock import FileLock
|
||||
|
||||
from ._compat.typing import assert_never
|
||||
from .architecture import Architecture
|
||||
from .environment import ParsedEnvironment
|
||||
from .logger import log
|
||||
from .options import Options
|
||||
from .typing import Literal, PathOrStr, assert_never
|
||||
from .typing import PathOrStr
|
||||
from .util import (
|
||||
CIBW_CACHE_PATH,
|
||||
AlreadyBuiltWheelError,
|
||||
BuildFrontend,
|
||||
BuildFrontendConfig,
|
||||
BuildFrontendName,
|
||||
BuildSelector,
|
||||
NonPlatformWheelError,
|
||||
call,
|
||||
@@ -53,7 +57,7 @@ def get_macos_version() -> tuple[int, int]:
|
||||
"""
|
||||
version_str, _, _ = platform.mac_ver()
|
||||
version = tuple(map(int, version_str.split(".")[:2]))
|
||||
return cast(Tuple[int, int], version)
|
||||
return typing.cast(Tuple[int, int], version)
|
||||
|
||||
|
||||
def get_macos_sdks() -> list[str]:
|
||||
@@ -69,7 +73,7 @@ class PythonConfiguration:
|
||||
|
||||
|
||||
def get_python_configurations(
|
||||
build_selector: BuildSelector, architectures: set[Architecture]
|
||||
build_selector: BuildSelector, architectures: Set[Architecture]
|
||||
) -> list[PythonConfiguration]:
|
||||
full_python_configs = read_python_configs("macos")
|
||||
|
||||
@@ -161,7 +165,7 @@ def setup_python(
|
||||
python_configuration: PythonConfiguration,
|
||||
dependency_constraint_flags: Sequence[PathOrStr],
|
||||
environment: ParsedEnvironment,
|
||||
build_frontend: BuildFrontend,
|
||||
build_frontend: BuildFrontendName,
|
||||
) -> dict[str, str]:
|
||||
tmp.mkdir()
|
||||
implementation_id = python_configuration.identifier.split("-")[0]
|
||||
@@ -330,6 +334,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
|
||||
for config in python_configurations:
|
||||
build_options = options.build_options(config.identifier)
|
||||
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||
log.build_start(config.identifier)
|
||||
|
||||
identifier_tmp_dir = tmp_path / config.identifier
|
||||
@@ -352,7 +357,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
config,
|
||||
dependency_constraint_flags,
|
||||
build_options.environment,
|
||||
build_options.build_frontend,
|
||||
build_frontend.name,
|
||||
)
|
||||
|
||||
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
||||
@@ -373,13 +378,13 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
log.step("Building wheel...")
|
||||
built_wheel_dir.mkdir()
|
||||
|
||||
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||
extra_flags = split_config_settings(
|
||||
build_options.config_settings, build_options.build_frontend
|
||||
build_options.config_settings, build_frontend.name
|
||||
)
|
||||
extra_flags += build_frontend.args
|
||||
|
||||
if build_options.build_frontend == "pip":
|
||||
extra_flags += verbosity_flags
|
||||
if build_frontend.name == "pip":
|
||||
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
||||
# see https://github.com/pypa/cibuildwheel/pull/369
|
||||
call(
|
||||
@@ -393,9 +398,10 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
*extra_flags,
|
||||
env=env,
|
||||
)
|
||||
elif build_options.build_frontend == "build":
|
||||
verbosity_setting = " ".join(verbosity_flags)
|
||||
extra_flags += (f"--config-setting={verbosity_setting}",)
|
||||
elif build_frontend.name == "build":
|
||||
if not 0 <= build_options.build_verbosity < 2:
|
||||
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
||||
log.warning(msg)
|
||||
build_env = env.copy()
|
||||
if build_options.dependency_constraints:
|
||||
constraint_path = (
|
||||
@@ -416,7 +422,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
env=build_env,
|
||||
)
|
||||
else:
|
||||
assert_never(build_options.build_frontend)
|
||||
assert_never(build_frontend)
|
||||
|
||||
built_wheel = next(built_wheel_dir.glob("*.whl"))
|
||||
|
||||
@@ -596,6 +602,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
build_options.test_command,
|
||||
project=Path(".").resolve(),
|
||||
package=build_options.package_dir.resolve(),
|
||||
wheel=repaired_wheel,
|
||||
)
|
||||
|
||||
test_cwd = identifier_tmp_dir / "test_cwd"
|
||||
|
||||
@@ -8,16 +8,48 @@ import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import typing
|
||||
import uuid
|
||||
from collections.abc import Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path, PurePath, PurePosixPath
|
||||
from types import TracebackType
|
||||
from typing import IO, Dict, Sequence, cast
|
||||
from typing import IO, Dict, Literal
|
||||
|
||||
from cibuildwheel.util import CIProvider, detect_ci_provider
|
||||
from .typing import PathOrStr, PopenBytes
|
||||
from .util import CIProvider, call, detect_ci_provider, parse_key_value_string
|
||||
|
||||
from .typing import Literal, PathOrStr, PopenBytes
|
||||
ContainerEngineName = Literal["docker", "podman"]
|
||||
|
||||
ContainerEngine = Literal["docker", "podman"]
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class OCIContainerEngineConfig:
|
||||
name: ContainerEngineName
|
||||
create_args: Sequence[str] = ()
|
||||
|
||||
@staticmethod
|
||||
def from_config_string(config_string: str) -> OCIContainerEngineConfig:
|
||||
config_dict = parse_key_value_string(
|
||||
config_string, ["name"], ["create_args", "create-args"]
|
||||
)
|
||||
name = " ".join(config_dict["name"])
|
||||
if name not in {"docker", "podman"}:
|
||||
msg = f"unknown container engine {name}"
|
||||
raise ValueError(msg)
|
||||
|
||||
name = typing.cast(ContainerEngineName, name)
|
||||
# some flexibility in the option name to cope with TOML conventions
|
||||
create_args = config_dict.get("create_args") or config_dict.get("create-args") or []
|
||||
return OCIContainerEngineConfig(name=name, create_args=create_args)
|
||||
|
||||
def options_summary(self) -> str | dict[str, str]:
|
||||
if not self.create_args:
|
||||
return self.name
|
||||
else:
|
||||
return {"name": self.name, "create_args": repr(self.create_args)}
|
||||
|
||||
|
||||
DEFAULT_ENGINE = OCIContainerEngineConfig("docker")
|
||||
|
||||
|
||||
class OCIContainer:
|
||||
@@ -53,16 +85,16 @@ class OCIContainer:
|
||||
self,
|
||||
*,
|
||||
image: str,
|
||||
simulate_32_bit: bool = False,
|
||||
enforce_32_bit: bool = False,
|
||||
cwd: PathOrStr | None = None,
|
||||
engine: ContainerEngine = "docker",
|
||||
engine: OCIContainerEngineConfig = DEFAULT_ENGINE,
|
||||
):
|
||||
if not image:
|
||||
msg = "Must have a non-empty image to run."
|
||||
raise ValueError(msg)
|
||||
|
||||
self.image = image
|
||||
self.simulate_32_bit = simulate_32_bit
|
||||
self.enforce_32_bit = enforce_32_bit
|
||||
self.cwd = cwd
|
||||
self.name: str | None = None
|
||||
self.engine = engine
|
||||
@@ -78,17 +110,29 @@ class OCIContainer:
|
||||
if detect_ci_provider() == CIProvider.travis_ci and platform.machine() == "ppc64le":
|
||||
network_args = ["--network=host"]
|
||||
|
||||
shell_args = ["linux32", "/bin/bash"] if self.simulate_32_bit else ["/bin/bash"]
|
||||
simulate_32_bit = False
|
||||
if self.enforce_32_bit:
|
||||
# If the architecture running the image is already the right one
|
||||
# or the image entrypoint takes care of enforcing this, then we don't need to
|
||||
# simulate this
|
||||
container_machine = call(
|
||||
self.engine.name, "run", "--rm", self.image, "uname", "-m", capture_stdout=True
|
||||
).strip()
|
||||
simulate_32_bit = container_machine != "i686"
|
||||
|
||||
shell_args = ["linux32", "/bin/bash"] if simulate_32_bit else ["/bin/bash"]
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
self.engine,
|
||||
self.engine.name,
|
||||
"create",
|
||||
"--env=CIBUILDWHEEL",
|
||||
"--env=SOURCE_DATE_EPOCH",
|
||||
f"--name={self.name}",
|
||||
"--interactive",
|
||||
"--volume=/:/host", # ignored on CircleCI
|
||||
*network_args,
|
||||
*self.engine.create_args,
|
||||
self.image,
|
||||
*shell_args,
|
||||
],
|
||||
@@ -97,7 +141,7 @@ class OCIContainer:
|
||||
|
||||
self.process = subprocess.Popen(
|
||||
[
|
||||
self.engine,
|
||||
self.engine.name,
|
||||
"start",
|
||||
"--attach",
|
||||
"--interactive",
|
||||
@@ -135,7 +179,7 @@ class OCIContainer:
|
||||
self.bash_stdin.close()
|
||||
self.bash_stdout.close()
|
||||
|
||||
if self.engine == "podman":
|
||||
if self.engine.name == "podman":
|
||||
# This works around what seems to be a race condition in the podman
|
||||
# backend. The full reason is not understood. See PR #966 for a
|
||||
# discussion on possible causes and attempts to remove this line.
|
||||
@@ -145,7 +189,7 @@ class OCIContainer:
|
||||
assert isinstance(self.name, str)
|
||||
|
||||
subprocess.run(
|
||||
[self.engine, "rm", "--force", "-v", self.name],
|
||||
[self.engine.name, "rm", "--force", "-v", self.name],
|
||||
stdout=subprocess.DEVNULL,
|
||||
check=False,
|
||||
)
|
||||
@@ -160,15 +204,16 @@ class OCIContainer:
|
||||
if from_path.is_dir():
|
||||
self.call(["mkdir", "-p", to_path])
|
||||
subprocess.run(
|
||||
f"tar cf - . | {self.engine} exec -i {self.name} tar --no-same-owner -xC {shell_quote(to_path)} -f -",
|
||||
f"tar cf - . | {self.engine.name} exec -i {self.name} tar --no-same-owner -xC {shell_quote(to_path)} -f -",
|
||||
shell=True,
|
||||
check=True,
|
||||
cwd=from_path,
|
||||
)
|
||||
else:
|
||||
exec_process: subprocess.Popen[bytes]
|
||||
with subprocess.Popen(
|
||||
[
|
||||
self.engine,
|
||||
self.engine.name,
|
||||
"exec",
|
||||
"-i",
|
||||
str(self.name),
|
||||
@@ -178,10 +223,10 @@ class OCIContainer:
|
||||
],
|
||||
stdin=subprocess.PIPE,
|
||||
) as exec_process:
|
||||
exec_process.stdin = cast(IO[bytes], exec_process.stdin)
|
||||
|
||||
assert exec_process.stdin
|
||||
with open(from_path, "rb") as from_file:
|
||||
shutil.copyfileobj(from_file, exec_process.stdin)
|
||||
# Bug in mypy, https://github.com/python/mypy/issues/15031
|
||||
shutil.copyfileobj(from_file, exec_process.stdin) # type: ignore[misc]
|
||||
|
||||
exec_process.stdin.close()
|
||||
exec_process.wait()
|
||||
@@ -195,10 +240,10 @@ class OCIContainer:
|
||||
# note: we assume from_path is a dir
|
||||
to_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if self.engine == "podman":
|
||||
if self.engine.name == "podman":
|
||||
subprocess.run(
|
||||
[
|
||||
self.engine,
|
||||
self.engine.name,
|
||||
"cp",
|
||||
f"{self.name}:{from_path}/.",
|
||||
str(to_path),
|
||||
@@ -206,10 +251,10 @@ class OCIContainer:
|
||||
check=True,
|
||||
cwd=to_path,
|
||||
)
|
||||
elif self.engine == "docker":
|
||||
elif self.engine.name == "docker":
|
||||
# There is a bug in docker that prevents a simple 'cp' invocation
|
||||
# from working https://github.com/moby/moby/issues/38995
|
||||
command = f"{self.engine} exec -i {self.name} tar -cC {shell_quote(from_path)} -f - . | tar -xf -"
|
||||
command = f"{self.engine.name} exec -i {self.name} tar -cC {shell_quote(from_path)} -f - . | tar -xf -"
|
||||
subprocess.run(
|
||||
command,
|
||||
shell=True,
|
||||
@@ -217,7 +262,7 @@ class OCIContainer:
|
||||
cwd=to_path,
|
||||
)
|
||||
else:
|
||||
raise KeyError(self.engine)
|
||||
raise KeyError(self.engine.name)
|
||||
|
||||
def glob(self, path: PurePosixPath, pattern: str) -> list[PurePosixPath]:
|
||||
glob_pattern = path.joinpath(pattern)
|
||||
@@ -238,7 +283,7 @@ class OCIContainer:
|
||||
def call(
|
||||
self,
|
||||
args: Sequence[PathOrStr],
|
||||
env: dict[str, str] | None = None,
|
||||
env: Mapping[str, str] | None = None,
|
||||
capture_output: bool = False,
|
||||
cwd: PathOrStr | None = None,
|
||||
) -> str:
|
||||
@@ -328,17 +373,17 @@ class OCIContainer:
|
||||
capture_output=True,
|
||||
)
|
||||
)
|
||||
return cast(Dict[str, str], env)
|
||||
return typing.cast(Dict[str, str], env)
|
||||
|
||||
def environment_executor(self, command: list[str], environment: dict[str, str]) -> str:
|
||||
def environment_executor(self, command: Sequence[str], environment: dict[str, str]) -> str:
|
||||
# used as an EnvironmentExecutor to evaluate commands and capture output
|
||||
return self.call(command, env=environment, capture_output=True)
|
||||
|
||||
def debug_info(self) -> str:
|
||||
if self.engine == "podman":
|
||||
command = f"{self.engine} info --debug"
|
||||
if self.engine.name == "podman":
|
||||
command = f"{self.engine.name} info --debug"
|
||||
else:
|
||||
command = f"{self.engine} info"
|
||||
command = f"{self.engine.name} info"
|
||||
completed = subprocess.run(
|
||||
command,
|
||||
shell=True,
|
||||
|
||||
+40
-29
@@ -10,26 +10,24 @@ import shlex
|
||||
import sys
|
||||
import textwrap
|
||||
import traceback
|
||||
from collections.abc import Callable, Generator, Iterable, Iterator, Mapping, Set
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Dict, Generator, Iterator, List, Mapping, Union, cast
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
from typing import Any, Dict, List, Literal, TypedDict, Union
|
||||
|
||||
from packaging.specifiers import SpecifierSet
|
||||
|
||||
from ._compat import tomllib
|
||||
from ._compat.typing import NotRequired
|
||||
from .architecture import Architecture
|
||||
from .environment import EnvironmentParseError, ParsedEnvironment, parse_environment
|
||||
from .logger import log
|
||||
from .oci_container import ContainerEngine
|
||||
from .oci_container import OCIContainerEngineConfig
|
||||
from .projectfiles import get_requires_python_str
|
||||
from .typing import PLATFORMS, Literal, NotRequired, PlatformName, TypedDict
|
||||
from .typing import PLATFORMS, PlatformName
|
||||
from .util import (
|
||||
MANYLINUX_ARCHS,
|
||||
MUSLLINUX_ARCHS,
|
||||
BuildFrontend,
|
||||
BuildFrontendConfig,
|
||||
BuildSelector,
|
||||
DependencyConstraints,
|
||||
TestSelector,
|
||||
@@ -76,7 +74,7 @@ class GlobalOptions:
|
||||
build_selector: BuildSelector
|
||||
test_selector: TestSelector
|
||||
architectures: set[Architecture]
|
||||
container_engine: ContainerEngine
|
||||
container_engine: OCIContainerEngineConfig
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
@@ -94,7 +92,7 @@ class BuildOptions:
|
||||
test_requires: list[str]
|
||||
test_extras: str
|
||||
build_verbosity: int
|
||||
build_frontend: BuildFrontend
|
||||
build_frontend: BuildFrontendConfig | None
|
||||
config_settings: str
|
||||
|
||||
@property
|
||||
@@ -137,8 +135,14 @@ DISALLOWED_OPTIONS = {
|
||||
|
||||
|
||||
class TableFmt(TypedDict):
|
||||
# a format string, used with '.format', with `k` and `v` parameters
|
||||
# e.g. "{k}={v}"
|
||||
item: str
|
||||
# the string that is inserted between items
|
||||
# e.g. " "
|
||||
sep: str
|
||||
# a quoting function that, if supplied, is called to quote each value
|
||||
# e.g. shlex.quote
|
||||
quote: NotRequired[Callable[[str], str]]
|
||||
|
||||
|
||||
@@ -193,7 +197,7 @@ class OptionsReader:
|
||||
*,
|
||||
platform: PlatformName,
|
||||
env: Mapping[str, str],
|
||||
disallow: dict[str, set[str]] | None = None,
|
||||
disallow: Mapping[str, Set[str]] | None = None,
|
||||
) -> None:
|
||||
self.platform = platform
|
||||
self.env = env
|
||||
@@ -446,6 +450,7 @@ class Options:
|
||||
build_config = args.only
|
||||
skip_config = ""
|
||||
architectures = Architecture.all_archs(self.platform)
|
||||
prerelease_pythons = True
|
||||
|
||||
build_selector = BuildSelector(
|
||||
build_config=build_config,
|
||||
@@ -455,15 +460,17 @@ class Options:
|
||||
)
|
||||
test_selector = TestSelector(skip_config=test_skip)
|
||||
|
||||
container_engine_str = self.reader.get("container-engine")
|
||||
container_engine_str = self.reader.get(
|
||||
"container-engine", table={"item": "{k}:{v}", "sep": "; ", "quote": shlex.quote}
|
||||
)
|
||||
|
||||
if container_engine_str not in ["docker", "podman"]:
|
||||
msg = f"cibuildwheel: Unrecognised container_engine {container_engine_str!r}, only 'docker' and 'podman' are supported"
|
||||
try:
|
||||
container_engine = OCIContainerEngineConfig.from_config_string(container_engine_str)
|
||||
except ValueError as e:
|
||||
msg = f"cibuildwheel: Failed to parse container config. {e}"
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
container_engine = cast(ContainerEngine, container_engine_str)
|
||||
|
||||
return GlobalOptions(
|
||||
package_dir=package_dir,
|
||||
output_dir=output_dir,
|
||||
@@ -481,7 +488,6 @@ class Options:
|
||||
with self.reader.identifier(identifier):
|
||||
before_all = self.reader.get("before-all", sep=" && ")
|
||||
|
||||
build_frontend_str = self.reader.get("build-frontend", env_plat=False)
|
||||
environment_config = self.reader.get(
|
||||
"environment", table={"item": '{k}="{v}"', "sep": " "}
|
||||
)
|
||||
@@ -499,15 +505,20 @@ class Options:
|
||||
test_extras = self.reader.get("test-extras", sep=",")
|
||||
build_verbosity_str = self.reader.get("build-verbosity")
|
||||
|
||||
build_frontend: BuildFrontend
|
||||
if build_frontend_str == "build":
|
||||
build_frontend = "build"
|
||||
elif build_frontend_str == "pip":
|
||||
build_frontend = "pip"
|
||||
build_frontend_str = self.reader.get(
|
||||
"build-frontend",
|
||||
env_plat=False,
|
||||
table={"item": "{k}:{v}", "sep": "; ", "quote": shlex.quote},
|
||||
)
|
||||
build_frontend: BuildFrontendConfig | None
|
||||
if not build_frontend_str or build_frontend_str == "default":
|
||||
build_frontend = None
|
||||
else:
|
||||
msg = f"cibuildwheel: Unrecognised build frontend {build_frontend_str!r}, only 'pip' and 'build' are supported"
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
try:
|
||||
build_frontend = BuildFrontendConfig.from_config_string(build_frontend_str)
|
||||
except ValueError as e:
|
||||
print(f"cibuildwheel: {e}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
try:
|
||||
environment = parse_environment(environment_config)
|
||||
@@ -597,7 +608,7 @@ class Options:
|
||||
config_settings=config_settings,
|
||||
)
|
||||
|
||||
def check_for_invalid_configuration(self, identifiers: list[str]) -> None:
|
||||
def check_for_invalid_configuration(self, identifiers: Iterable[str]) -> None:
|
||||
if self.platform in {"macos", "windows"}:
|
||||
before_all_values = {self.build_options(i).before_all for i in identifiers}
|
||||
|
||||
@@ -629,7 +640,7 @@ class Options:
|
||||
read_config_file=False,
|
||||
)
|
||||
|
||||
def summary(self, identifiers: list[str]) -> str:
|
||||
def summary(self, identifiers: Iterable[str]) -> str:
|
||||
lines = []
|
||||
global_option_names = sorted(f.name for f in dataclasses.fields(self.globals))
|
||||
|
||||
@@ -667,7 +678,7 @@ class Options:
|
||||
option_name: str,
|
||||
option_value: Any,
|
||||
default_value: Any,
|
||||
overrides: dict[str, Any] | None = None,
|
||||
overrides: Mapping[str, Any] | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Return a summary of the option value, including any overrides, with
|
||||
|
||||
@@ -3,26 +3,46 @@ from __future__ import annotations
|
||||
import ast
|
||||
import configparser
|
||||
import contextlib
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
from ._compat import tomllib
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
Constant = ast.Str
|
||||
|
||||
def get_constant(x: ast.Str) -> str:
|
||||
return x.s
|
||||
def get_parent(node: ast.AST | None, depth: int = 1) -> ast.AST | None:
|
||||
for _ in range(depth):
|
||||
node = getattr(node, "parent", None)
|
||||
return node
|
||||
|
||||
else:
|
||||
Constant = ast.Constant
|
||||
|
||||
def get_constant(x: ast.Constant) -> Any:
|
||||
return x.value
|
||||
def is_main(parent: ast.AST | None) -> bool:
|
||||
if parent is None:
|
||||
return False
|
||||
|
||||
# This would be much nicer with 3.10's pattern matching!
|
||||
if not isinstance(parent, ast.If):
|
||||
return False
|
||||
if not isinstance(parent.test, ast.Compare):
|
||||
return False
|
||||
|
||||
try:
|
||||
(op,) = parent.test.ops
|
||||
(comp,) = parent.test.comparators
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
if not isinstance(op, ast.Eq):
|
||||
return False
|
||||
|
||||
values = {comp, parent.test.left}
|
||||
|
||||
mains = {x for x in values if isinstance(x, ast.Constant) and x.value == "__main__"}
|
||||
if len(mains) != 1:
|
||||
return False
|
||||
consts = {x for x in values if isinstance(x, ast.Name) and x.id == "__name__"}
|
||||
if len(consts) != 1:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class Analyzer(ast.NodeVisitor):
|
||||
@@ -36,15 +56,24 @@ class Analyzer(ast.NodeVisitor):
|
||||
super().visit(node)
|
||||
|
||||
def visit_keyword(self, node: ast.keyword) -> None:
|
||||
# Must not be nested except for if __name__ == "__main__"
|
||||
|
||||
self.generic_visit(node)
|
||||
# Must not be nested in an if or other structure
|
||||
# This will be Module -> Expr -> Call -> keyword
|
||||
parent = get_parent(node, 4)
|
||||
unnested = parent is None
|
||||
|
||||
# This will be Module -> If -> Expr -> Call -> keyword
|
||||
name_main_unnested = (
|
||||
parent is not None and get_parent(parent) is None and is_main(get_parent(node, 3))
|
||||
)
|
||||
|
||||
if (
|
||||
node.arg == "python_requires"
|
||||
and not hasattr(node.parent.parent.parent, "parent") # type: ignore[attr-defined]
|
||||
and isinstance(node.value, Constant)
|
||||
and isinstance(node.value, ast.Constant)
|
||||
and (unnested or name_main_unnested)
|
||||
):
|
||||
self.requires_python = get_constant(node.value)
|
||||
self.requires_python = node.value.value
|
||||
|
||||
|
||||
def setup_py_python_requires(content: str) -> str | None:
|
||||
|
||||
@@ -6,69 +6,82 @@ python_configurations = [
|
||||
{ identifier = "cp39-manylinux_x86_64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-manylinux_x86_64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-manylinux_x86_64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-manylinux_x86_64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "cp36-manylinux_i686", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-manylinux_i686", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-manylinux_i686", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-manylinux_i686", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-manylinux_i686", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-manylinux_i686", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-manylinux_i686", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "pp37-manylinux_x86_64", version = "3.7", path_str = "/opt/python/pp37-pypy37_pp73" },
|
||||
{ identifier = "pp38-manylinux_x86_64", version = "3.8", path_str = "/opt/python/pp38-pypy38_pp73" },
|
||||
{ identifier = "pp39-manylinux_x86_64", version = "3.9", path_str = "/opt/python/pp39-pypy39_pp73" },
|
||||
{ identifier = "pp310-manylinux_x86_64", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
|
||||
{ identifier = "cp36-manylinux_aarch64", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-manylinux_aarch64", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-manylinux_aarch64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-manylinux_aarch64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-manylinux_aarch64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-manylinux_aarch64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-manylinux_aarch64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "cp36-manylinux_ppc64le", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-manylinux_ppc64le", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-manylinux_ppc64le", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-manylinux_ppc64le", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-manylinux_ppc64le", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-manylinux_ppc64le", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-manylinux_ppc64le", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "cp36-manylinux_s390x", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-manylinux_s390x", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-manylinux_s390x", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-manylinux_s390x", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-manylinux_s390x", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-manylinux_s390x", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-manylinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "pp37-manylinux_aarch64", version = "3.7", path_str = "/opt/python/pp37-pypy37_pp73" },
|
||||
{ identifier = "pp38-manylinux_aarch64", version = "3.8", path_str = "/opt/python/pp38-pypy38_pp73" },
|
||||
{ identifier = "pp39-manylinux_aarch64", version = "3.9", path_str = "/opt/python/pp39-pypy39_pp73" },
|
||||
{ identifier = "pp310-manylinux_aarch64", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
|
||||
{ identifier = "pp37-manylinux_i686", version = "3.7", path_str = "/opt/python/pp37-pypy37_pp73" },
|
||||
{ identifier = "pp38-manylinux_i686", version = "3.8", path_str = "/opt/python/pp38-pypy38_pp73" },
|
||||
{ identifier = "pp39-manylinux_i686", version = "3.9", path_str = "/opt/python/pp39-pypy39_pp73" },
|
||||
{ identifier = "pp310-manylinux_i686", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
|
||||
{ identifier = "cp36-musllinux_x86_64", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-musllinux_x86_64", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-musllinux_x86_64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-musllinux_x86_64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-musllinux_x86_64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-musllinux_x86_64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-musllinux_x86_64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "cp36-musllinux_i686", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-musllinux_i686", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-musllinux_i686", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-musllinux_i686", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-musllinux_i686", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-musllinux_i686", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-musllinux_i686", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "cp36-musllinux_aarch64", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-musllinux_aarch64", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-musllinux_aarch64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-musllinux_aarch64", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-musllinux_aarch64", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-musllinux_aarch64", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-musllinux_aarch64", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "cp36-musllinux_ppc64le", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-musllinux_ppc64le", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-musllinux_ppc64le", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-musllinux_ppc64le", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-musllinux_ppc64le", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-musllinux_ppc64le", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-musllinux_ppc64le", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
{ identifier = "cp36-musllinux_s390x", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||
{ identifier = "cp37-musllinux_s390x", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||
{ identifier = "cp38-musllinux_s390x", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||
{ identifier = "cp39-musllinux_s390x", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||
{ identifier = "cp310-musllinux_s390x", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||
{ identifier = "cp311-musllinux_s390x", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||
{ identifier = "cp312-musllinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||
]
|
||||
|
||||
[macos]
|
||||
@@ -81,17 +94,22 @@ python_configurations = [
|
||||
{ identifier = "cp39-macosx_x86_64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
|
||||
{ identifier = "cp39-macosx_arm64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
|
||||
{ identifier = "cp39-macosx_universal2", version = "3.9", url = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-macos11.pkg" },
|
||||
{ identifier = "cp310-macosx_x86_64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.10/python-3.10.10-macos11.pkg" },
|
||||
{ identifier = "cp310-macosx_arm64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.10/python-3.10.10-macos11.pkg" },
|
||||
{ identifier = "cp310-macosx_universal2", version = "3.10", url = "https://www.python.org/ftp/python/3.10.10/python-3.10.10-macos11.pkg" },
|
||||
{ identifier = "cp311-macosx_x86_64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg" },
|
||||
{ identifier = "cp311-macosx_arm64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg" },
|
||||
{ identifier = "cp311-macosx_universal2", version = "3.11", url = "https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg" },
|
||||
{ identifier = "cp310-macosx_x86_64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.11/python-3.10.11-macos11.pkg" },
|
||||
{ identifier = "cp310-macosx_arm64", version = "3.10", url = "https://www.python.org/ftp/python/3.10.11/python-3.10.11-macos11.pkg" },
|
||||
{ identifier = "cp310-macosx_universal2", version = "3.10", url = "https://www.python.org/ftp/python/3.10.11/python-3.10.11-macos11.pkg" },
|
||||
{ identifier = "cp311-macosx_x86_64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.5/python-3.11.5-macos11.pkg" },
|
||||
{ identifier = "cp311-macosx_arm64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.5/python-3.11.5-macos11.pkg" },
|
||||
{ identifier = "cp311-macosx_universal2", version = "3.11", url = "https://www.python.org/ftp/python/3.11.5/python-3.11.5-macos11.pkg" },
|
||||
{ identifier = "cp312-macosx_x86_64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.0/python-3.12.0rc3-macos11.pkg" },
|
||||
{ identifier = "cp312-macosx_arm64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.0/python-3.12.0rc3-macos11.pkg" },
|
||||
{ identifier = "cp312-macosx_universal2", version = "3.12", url = "https://www.python.org/ftp/python/3.12.0/python-3.12.0rc3-macos11.pkg" },
|
||||
{ identifier = "pp37-macosx_x86_64", version = "3.7", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.9-osx64.tar.bz2" },
|
||||
{ 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.11-macos_x86_64.tar.bz2" },
|
||||
{ identifier = "pp39-macosx_arm64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-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.12-macos_x86_64.tar.bz2" },
|
||||
{ identifier = "pp39-macosx_arm64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.12-macos_arm64.tar.bz2" },
|
||||
{ identifier = "pp310-macosx_x86_64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.12-macos_x86_64.tar.bz2" },
|
||||
{ identifier = "pp310-macosx_arm64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.12-macos_arm64.tar.bz2" },
|
||||
]
|
||||
|
||||
[windows]
|
||||
@@ -104,14 +122,18 @@ python_configurations = [
|
||||
{ identifier = "cp38-win_amd64", version = "3.8.10", arch = "64" },
|
||||
{ identifier = "cp39-win32", version = "3.9.13", arch = "32" },
|
||||
{ identifier = "cp39-win_amd64", version = "3.9.13", arch = "64" },
|
||||
{ identifier = "cp310-win32", version = "3.10.10", arch = "32" },
|
||||
{ identifier = "cp310-win_amd64", version = "3.10.10", arch = "64" },
|
||||
{ identifier = "cp311-win32", version = "3.11.2", arch = "32" },
|
||||
{ identifier = "cp311-win_amd64", version = "3.11.2", arch = "64" },
|
||||
{ identifier = "cp310-win32", version = "3.10.11", arch = "32" },
|
||||
{ identifier = "cp310-win_amd64", version = "3.10.11", arch = "64" },
|
||||
{ identifier = "cp311-win32", version = "3.11.5", arch = "32" },
|
||||
{ identifier = "cp311-win_amd64", version = "3.11.5", arch = "64" },
|
||||
{ identifier = "cp312-win32", version = "3.12.0-rc3", arch = "32" },
|
||||
{ identifier = "cp312-win_amd64", version = "3.12.0-rc3", arch = "64" },
|
||||
{ identifier = "cp39-win_arm64", version = "3.9.10", arch = "ARM64" },
|
||||
{ identifier = "cp310-win_arm64", version = "3.10.10", arch = "ARM64" },
|
||||
{ identifier = "cp311-win_arm64", version = "3.11.2", arch = "ARM64" },
|
||||
{ identifier = "cp310-win_arm64", version = "3.10.11", arch = "ARM64" },
|
||||
{ identifier = "cp311-win_arm64", version = "3.11.5", arch = "ARM64" },
|
||||
{ identifier = "cp312-win_arm64", version = "3.12.0-rc3", arch = "ARM64" },
|
||||
{ identifier = "pp37-win_amd64", version = "3.7", arch = "64", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.9-win64.zip" },
|
||||
{ identifier = "pp38-win_amd64", version = "3.8", arch = "64", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-win64.zip" },
|
||||
{ identifier = "pp39-win_amd64", version = "3.9", arch = "64", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.11-win64.zip" },
|
||||
{ identifier = "pp39-win_amd64", version = "3.9", arch = "64", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.12-win64.zip" },
|
||||
{ identifier = "pp310-win_amd64", version = "3.10", arch = "64", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.12-win64.zip" },
|
||||
]
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
#
|
||||
delocate==0.10.4
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
distlib==0.3.6
|
||||
distlib==0.3.7
|
||||
# via virtualenv
|
||||
filelock==3.9.0
|
||||
filelock==3.12.4
|
||||
# via virtualenv
|
||||
packaging==23.0
|
||||
packaging==23.1
|
||||
# via delocate
|
||||
platformdirs==3.1.0
|
||||
platformdirs==3.10.0
|
||||
# via virtualenv
|
||||
typing-extensions==4.5.0
|
||||
typing-extensions==4.8.0
|
||||
# via delocate
|
||||
virtualenv==20.20.0
|
||||
virtualenv==20.24.5
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
wheel==0.38.4
|
||||
wheel==0.41.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==23.0.1
|
||||
pip==23.2.1
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
setuptools==67.5.0
|
||||
setuptools==68.2.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
#
|
||||
delocate==0.10.4
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
distlib==0.3.6
|
||||
distlib==0.3.7
|
||||
# via virtualenv
|
||||
filelock==3.9.0
|
||||
filelock==3.12.4
|
||||
# via virtualenv
|
||||
packaging==23.0
|
||||
packaging==23.1
|
||||
# via delocate
|
||||
platformdirs==3.1.0
|
||||
platformdirs==3.10.0
|
||||
# via virtualenv
|
||||
typing-extensions==4.5.0
|
||||
typing-extensions==4.8.0
|
||||
# via delocate
|
||||
virtualenv==20.20.0
|
||||
virtualenv==20.24.5
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
wheel==0.38.4
|
||||
wheel==0.41.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==23.0.1
|
||||
pip==23.2.1
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
setuptools==67.5.0
|
||||
setuptools==68.2.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# nox -s update_constraints-3.12
|
||||
#
|
||||
delocate==0.10.4
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
distlib==0.3.7
|
||||
# via virtualenv
|
||||
filelock==3.12.4
|
||||
# via virtualenv
|
||||
packaging==23.1
|
||||
# via delocate
|
||||
platformdirs==3.10.0
|
||||
# via virtualenv
|
||||
typing-extensions==4.8.0
|
||||
# via delocate
|
||||
virtualenv==20.24.5
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
wheel==0.41.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==23.2.1
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
setuptools==68.2.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
@@ -6,30 +6,30 @@
|
||||
#
|
||||
delocate==0.10.4
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
distlib==0.3.6
|
||||
distlib==0.3.7
|
||||
# via virtualenv
|
||||
filelock==3.9.0
|
||||
filelock==3.12.2
|
||||
# via virtualenv
|
||||
importlib-metadata==6.0.0
|
||||
importlib-metadata==6.7.0
|
||||
# via virtualenv
|
||||
packaging==23.0
|
||||
packaging==23.1
|
||||
# via delocate
|
||||
platformdirs==3.1.0
|
||||
platformdirs==3.10.0
|
||||
# via virtualenv
|
||||
typing-extensions==4.5.0
|
||||
typing-extensions==4.7.1
|
||||
# via
|
||||
# delocate
|
||||
# importlib-metadata
|
||||
# platformdirs
|
||||
virtualenv==20.20.0
|
||||
virtualenv==20.24.5
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
wheel==0.38.4
|
||||
wheel==0.41.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
zipp==3.15.0
|
||||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==23.0.1
|
||||
pip==23.2.1
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
setuptools==67.5.0
|
||||
setuptools==68.0.0
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
#
|
||||
delocate==0.10.4
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
distlib==0.3.6
|
||||
distlib==0.3.7
|
||||
# via virtualenv
|
||||
filelock==3.9.0
|
||||
filelock==3.12.4
|
||||
# via virtualenv
|
||||
packaging==23.0
|
||||
packaging==23.1
|
||||
# via delocate
|
||||
platformdirs==3.1.0
|
||||
platformdirs==3.10.0
|
||||
# via virtualenv
|
||||
typing-extensions==4.5.0
|
||||
typing-extensions==4.8.0
|
||||
# via delocate
|
||||
virtualenv==20.20.0
|
||||
virtualenv==20.24.5
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
wheel==0.38.4
|
||||
wheel==0.41.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==23.0.1
|
||||
pip==23.2.1
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
setuptools==67.5.0
|
||||
setuptools==68.2.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
#
|
||||
delocate==0.10.4
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
distlib==0.3.6
|
||||
distlib==0.3.7
|
||||
# via virtualenv
|
||||
filelock==3.9.0
|
||||
filelock==3.12.4
|
||||
# via virtualenv
|
||||
packaging==23.0
|
||||
packaging==23.1
|
||||
# via delocate
|
||||
platformdirs==3.1.0
|
||||
platformdirs==3.10.0
|
||||
# via virtualenv
|
||||
typing-extensions==4.5.0
|
||||
typing-extensions==4.8.0
|
||||
# via delocate
|
||||
virtualenv==20.20.0
|
||||
virtualenv==20.24.5
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
wheel==0.38.4
|
||||
wheel==0.41.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==23.0.1
|
||||
pip==23.2.1
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
setuptools==67.5.0
|
||||
setuptools==68.2.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with Python 3.11
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# nox -s update_constraints-3.11
|
||||
# nox -s update_constraints-3.12
|
||||
#
|
||||
delocate==0.10.4
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
distlib==0.3.6
|
||||
distlib==0.3.7
|
||||
# via virtualenv
|
||||
filelock==3.9.0
|
||||
filelock==3.12.4
|
||||
# via virtualenv
|
||||
packaging==23.0
|
||||
packaging==23.1
|
||||
# via delocate
|
||||
platformdirs==3.1.0
|
||||
platformdirs==3.10.0
|
||||
# via virtualenv
|
||||
typing-extensions==4.5.0
|
||||
typing-extensions==4.8.0
|
||||
# via delocate
|
||||
virtualenv==20.20.0
|
||||
virtualenv==20.24.5
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
wheel==0.38.4
|
||||
wheel==0.41.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==23.0.1
|
||||
pip==23.2.1
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
setuptools==67.5.0
|
||||
setuptools==68.2.2
|
||||
# via -r cibuildwheel/resources/constraints.in
|
||||
|
||||
@@ -4,7 +4,7 @@ skip = ""
|
||||
test-skip = ""
|
||||
|
||||
archs = ["auto"]
|
||||
build-frontend = "pip"
|
||||
build-frontend = "default"
|
||||
config-settings = {}
|
||||
dependency-versions = "pinned"
|
||||
environment = {}
|
||||
|
||||
@@ -1,49 +1,54 @@
|
||||
[x86_64]
|
||||
manylinux1 = quay.io/pypa/manylinux1_x86_64:2023-02-26-4ed41b6
|
||||
manylinux1 = quay.io/pypa/manylinux1_x86_64:2023-09-12-f07b683
|
||||
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-12-26-0d38463
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2023-03-05-271004f
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2023-03-05-271004f
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2023-09-24-36b93e4
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2023-09-24-36b93e4
|
||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2023-09-24-36b93e4
|
||||
|
||||
[i686]
|
||||
manylinux1 = quay.io/pypa/manylinux1_i686:2023-02-26-4ed41b6
|
||||
manylinux1 = quay.io/pypa/manylinux1_i686:2023-09-12-f07b683
|
||||
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_i686:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_i686:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2023-03-05-271004f
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2023-09-24-36b93e4
|
||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2023-09-24-36b93e4
|
||||
|
||||
[pypy_x86_64]
|
||||
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-12-26-0d38463
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2023-03-05-271004f
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2023-09-24-36b93e4
|
||||
|
||||
[pypy_i686]
|
||||
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_i686:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_i686:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463
|
||||
|
||||
[aarch64]
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2023-03-05-271004f
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2023-03-05-271004f
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2023-09-24-36b93e4
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2023-09-24-36b93e4
|
||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2023-09-24-36b93e4
|
||||
|
||||
[ppc64le]
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-12-26-0d38463
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2023-03-05-271004f
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2023-03-05-271004f
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2023-09-24-36b93e4
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2023-09-24-36b93e4
|
||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2023-09-24-36b93e4
|
||||
|
||||
[s390x]
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-12-26-0d38463
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2023-03-05-271004f
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2023-03-05-271004f
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2023-09-24-36b93e4
|
||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2023-09-24-36b93e4
|
||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2023-09-24-36b93e4
|
||||
|
||||
[pypy_aarch64]
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2023-03-05-271004f
|
||||
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2023-09-24-36b93e4
|
||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2023-03-05-271004f
|
||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2023-09-24-36b93e4
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
version = "20.20.0"
|
||||
url = "https://github.com/pypa/get-virtualenv/blob/20.20.0/public/virtualenv.pyz?raw=true"
|
||||
version = "20.21.1"
|
||||
url = "https://github.com/pypa/get-virtualenv/blob/20.21.1/public/virtualenv.pyz?raw=true"
|
||||
|
||||
+9
-21
@@ -2,37 +2,19 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final, Literal, OrderedDict, Protocol, TypedDict
|
||||
else:
|
||||
from typing import Final, Literal, OrderedDict, Protocol, TypedDict
|
||||
|
||||
if sys.version_info < (3, 11):
|
||||
from typing_extensions import NotRequired, assert_never
|
||||
else:
|
||||
from typing import NotRequired, assert_never
|
||||
import typing
|
||||
from typing import Final, Literal, Protocol, Union
|
||||
|
||||
__all__ = (
|
||||
"Final",
|
||||
"Literal",
|
||||
"PLATFORMS",
|
||||
"PathOrStr",
|
||||
"PlatformName",
|
||||
"Protocol",
|
||||
"PLATFORMS",
|
||||
"PopenBytes",
|
||||
"Protocol",
|
||||
"TypedDict",
|
||||
"OrderedDict",
|
||||
"assert_never",
|
||||
"NotRequired",
|
||||
)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
if typing.TYPE_CHECKING:
|
||||
PopenBytes = subprocess.Popen[bytes]
|
||||
PathOrStr = Union[str, os.PathLike[str]]
|
||||
else:
|
||||
@@ -42,3 +24,9 @@ else:
|
||||
|
||||
PlatformName = Literal["linux", "macos", "windows"]
|
||||
PLATFORMS: Final[set[PlatformName]] = {"linux", "macos", "windows"}
|
||||
|
||||
|
||||
class GenericPythonConfiguration(Protocol):
|
||||
@property
|
||||
def identifier(self) -> str:
|
||||
...
|
||||
|
||||
+91
-34
@@ -11,32 +11,19 @@ import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
import time
|
||||
import typing
|
||||
import urllib.request
|
||||
from collections import defaultdict
|
||||
from collections.abc import Generator, Iterable, Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from functools import lru_cache
|
||||
from functools import cached_property, lru_cache
|
||||
from pathlib import Path, PurePath
|
||||
from time import sleep
|
||||
from typing import (
|
||||
Any,
|
||||
ClassVar,
|
||||
Generator,
|
||||
Iterable,
|
||||
Sequence,
|
||||
TextIO,
|
||||
TypeVar,
|
||||
cast,
|
||||
overload,
|
||||
)
|
||||
from typing import Any, ClassVar, Final, Literal, TextIO, TypeVar
|
||||
|
||||
import bracex
|
||||
import certifi
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
|
||||
from filelock import FileLock
|
||||
from packaging.requirements import InvalidRequirement, Requirement
|
||||
from packaging.specifiers import SpecifierSet
|
||||
@@ -44,7 +31,8 @@ from packaging.utils import parse_wheel_filename
|
||||
from packaging.version import Version
|
||||
from platformdirs import user_cache_path
|
||||
|
||||
from cibuildwheel.typing import Final, Literal, PathOrStr, PlatformName
|
||||
from ._compat import tomllib
|
||||
from .typing import PathOrStr, PlatformName
|
||||
|
||||
__all__ = [
|
||||
"resources_dir",
|
||||
@@ -69,7 +57,6 @@ install_certifi_script: Final[Path] = resources_dir / "install_certifi.py"
|
||||
|
||||
test_fail_cwd_file: Final[Path] = resources_dir / "testing_temp_dir_file.py"
|
||||
|
||||
BuildFrontend = Literal["pip", "build"]
|
||||
|
||||
MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
|
||||
"x86_64",
|
||||
@@ -98,20 +85,20 @@ CIBW_CACHE_PATH: Final[Path] = Path(
|
||||
IS_WIN: Final[bool] = sys.platform.startswith("win")
|
||||
|
||||
|
||||
@overload
|
||||
@typing.overload
|
||||
def call(
|
||||
*args: PathOrStr,
|
||||
env: dict[str, str] | None = None,
|
||||
env: Mapping[str, str] | None = None,
|
||||
cwd: PathOrStr | None = None,
|
||||
capture_stdout: Literal[False] = ...,
|
||||
) -> None:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
@typing.overload
|
||||
def call(
|
||||
*args: PathOrStr,
|
||||
env: dict[str, str] | None = None,
|
||||
env: Mapping[str, str] | None = None,
|
||||
cwd: PathOrStr | None = None,
|
||||
capture_stdout: Literal[True],
|
||||
) -> str:
|
||||
@@ -120,7 +107,7 @@ def call(
|
||||
|
||||
def call(
|
||||
*args: PathOrStr,
|
||||
env: dict[str, str] | None = None,
|
||||
env: Mapping[str, str] | None = None,
|
||||
cwd: PathOrStr | None = None,
|
||||
capture_stdout: bool = False,
|
||||
) -> str | None:
|
||||
@@ -140,10 +127,12 @@ def call(
|
||||
result = subprocess.run(args_, check=True, shell=IS_WIN, env=env, cwd=cwd, **kwargs)
|
||||
if not capture_stdout:
|
||||
return None
|
||||
return cast(str, result.stdout)
|
||||
return typing.cast(str, result.stdout)
|
||||
|
||||
|
||||
def shell(*commands: str, env: dict[str, str] | None = None, cwd: PathOrStr | None = None) -> None:
|
||||
def shell(
|
||||
*commands: str, env: Mapping[str, str] | None = None, cwd: PathOrStr | None = None
|
||||
) -> None:
|
||||
command = " ".join(commands)
|
||||
print(f"+ {command}")
|
||||
subprocess.run(command, env=env, cwd=cwd, shell=True, check=True)
|
||||
@@ -377,6 +366,34 @@ class DependencyConstraints:
|
||||
return self.base_file_path.name
|
||||
|
||||
|
||||
BuildFrontendName = Literal["pip", "build"]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BuildFrontendConfig:
|
||||
name: BuildFrontendName
|
||||
args: Sequence[str] = ()
|
||||
|
||||
@staticmethod
|
||||
def from_config_string(config_string: str) -> BuildFrontendConfig:
|
||||
config_dict = parse_key_value_string(config_string, ["name"], ["args"])
|
||||
name = " ".join(config_dict["name"])
|
||||
if name not in {"pip", "build"}:
|
||||
msg = f"Unrecognised build frontend {name}, only 'pip' and 'build' are supported"
|
||||
raise ValueError(msg)
|
||||
|
||||
name = typing.cast(BuildFrontendName, name)
|
||||
|
||||
args = config_dict.get("args") or []
|
||||
return BuildFrontendConfig(name=name, args=args)
|
||||
|
||||
def options_summary(self) -> str | dict[str, str]:
|
||||
if not self.args:
|
||||
return self.name
|
||||
else:
|
||||
return {"name": self.name, "args": repr(self.args)}
|
||||
|
||||
|
||||
class NonPlatformWheelError(Exception):
|
||||
def __init__(self) -> None:
|
||||
message = textwrap.dedent(
|
||||
@@ -498,7 +515,7 @@ def print_new_wheels(msg: str, output_dir: Path) -> Generator[None, None, None]:
|
||||
)
|
||||
|
||||
|
||||
def get_pip_version(env: dict[str, str]) -> str:
|
||||
def get_pip_version(env: Mapping[str, str]) -> str:
|
||||
versions_output_text = call(
|
||||
"python", "-m", "pip", "freeze", "--all", capture_stdout=True, env=env
|
||||
)
|
||||
@@ -658,12 +675,6 @@ def find_compatible_wheel(wheels: Sequence[T], identifier: str) -> T | None:
|
||||
return None
|
||||
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from functools import cached_property
|
||||
else:
|
||||
from .functools_cached_property_38 import cached_property
|
||||
|
||||
|
||||
# Can be replaced by contextlib.chdir in Python 3.11
|
||||
@contextlib.contextmanager
|
||||
def chdir(new_path: Path | str) -> Generator[None, None, None]:
|
||||
@@ -703,3 +714,49 @@ def fix_ansi_codes_for_github_actions(text: str) -> str:
|
||||
ansi_codes.append(code)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def parse_key_value_string(
|
||||
key_value_string: str,
|
||||
positional_arg_names: Sequence[str] | None = None,
|
||||
kw_arg_names: Sequence[str] | None = None,
|
||||
) -> dict[str, list[str]]:
|
||||
"""
|
||||
Parses a string like "docker; create_args: --some-option=value another-option"
|
||||
"""
|
||||
if positional_arg_names is None:
|
||||
positional_arg_names = []
|
||||
if kw_arg_names is None:
|
||||
kw_arg_names = []
|
||||
|
||||
all_field_names = [*positional_arg_names, *kw_arg_names]
|
||||
|
||||
shlexer = shlex.shlex(key_value_string, posix=True, punctuation_chars=";:")
|
||||
shlexer.commenters = ""
|
||||
parts = list(shlexer)
|
||||
# parts now looks like
|
||||
# ['docker', ';', 'create_args',':', '--some-option=value', 'another-option']
|
||||
|
||||
# split by semicolon
|
||||
fields = [list(group) for k, group in itertools.groupby(parts, lambda x: x == ";") if not k]
|
||||
|
||||
result: dict[str, list[str]] = defaultdict(list)
|
||||
for field_i, field in enumerate(fields):
|
||||
if len(field) > 1 and field[1] == ":":
|
||||
field_name = field[0]
|
||||
values = field[2:]
|
||||
if field_name not in all_field_names:
|
||||
msg = f"Failed to parse {key_value_string!r}. Unknown field name {field_name!r}"
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
try:
|
||||
field_name = positional_arg_names[field_i]
|
||||
except IndexError:
|
||||
msg = f"Failed to parse {key_value_string!r}. Too many positional arguments - expected a maximum of {len(positional_arg_names)}"
|
||||
raise ValueError(msg) from None
|
||||
|
||||
values = field
|
||||
|
||||
result[field_name] += values
|
||||
|
||||
return result
|
||||
|
||||
+25
-16
@@ -6,24 +6,27 @@ import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
from collections.abc import MutableMapping, Sequence, Set
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Sequence
|
||||
from zipfile import ZipFile
|
||||
|
||||
from filelock import FileLock
|
||||
from packaging.version import Version
|
||||
|
||||
from ._compat.typing import assert_never
|
||||
from .architecture import Architecture
|
||||
from .environment import ParsedEnvironment
|
||||
from .logger import log
|
||||
from .options import Options
|
||||
from .typing import PathOrStr, assert_never
|
||||
from .typing import PathOrStr
|
||||
from .util import (
|
||||
CIBW_CACHE_PATH,
|
||||
AlreadyBuiltWheelError,
|
||||
BuildFrontend,
|
||||
BuildFrontendConfig,
|
||||
BuildFrontendName,
|
||||
BuildSelector,
|
||||
NonPlatformWheelError,
|
||||
call,
|
||||
@@ -71,7 +74,7 @@ class PythonConfiguration:
|
||||
|
||||
def get_python_configurations(
|
||||
build_selector: BuildSelector,
|
||||
architectures: set[Architecture],
|
||||
architectures: Set[Architecture],
|
||||
) -> list[PythonConfiguration]:
|
||||
full_python_configs = read_python_configs("windows")
|
||||
|
||||
@@ -135,7 +138,7 @@ def setup_setuptools_cross_compile(
|
||||
tmp: Path,
|
||||
python_configuration: PythonConfiguration,
|
||||
python_libs_base: Path,
|
||||
env: dict[str, str],
|
||||
env: MutableMapping[str, str],
|
||||
) -> None:
|
||||
distutils_cfg = tmp / "extra-setup.cfg"
|
||||
env["DIST_EXTRA_CONFIG"] = str(distutils_cfg)
|
||||
@@ -183,7 +186,7 @@ def setup_rust_cross_compile(
|
||||
tmp: Path, # noqa: ARG001
|
||||
python_configuration: PythonConfiguration,
|
||||
python_libs_base: Path, # noqa: ARG001
|
||||
env: dict[str, str],
|
||||
env: MutableMapping[str, str],
|
||||
) -> None:
|
||||
# Assume that MSVC will be used, because we already know that we are
|
||||
# cross-compiling. MinGW users can set CARGO_BUILD_TARGET themselves
|
||||
@@ -213,7 +216,7 @@ def setup_python(
|
||||
python_configuration: PythonConfiguration,
|
||||
dependency_constraint_flags: Sequence[PathOrStr],
|
||||
environment: ParsedEnvironment,
|
||||
build_frontend: BuildFrontend,
|
||||
build_frontend: BuildFrontendName,
|
||||
) -> dict[str, str]:
|
||||
tmp.mkdir()
|
||||
implementation_id = python_configuration.identifier.split("-")[0]
|
||||
@@ -366,6 +369,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
|
||||
for config in python_configurations:
|
||||
build_options = options.build_options(config.identifier)
|
||||
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||
log.build_start(config.identifier)
|
||||
|
||||
identifier_tmp_dir = tmp_path / config.identifier
|
||||
@@ -386,7 +390,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
config,
|
||||
dependency_constraint_flags,
|
||||
build_options.environment,
|
||||
build_options.build_frontend,
|
||||
build_frontend.name,
|
||||
)
|
||||
|
||||
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
||||
@@ -410,13 +414,13 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
log.step("Building wheel...")
|
||||
built_wheel_dir.mkdir()
|
||||
|
||||
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||
extra_flags = split_config_settings(
|
||||
build_options.config_settings, build_options.build_frontend
|
||||
build_options.config_settings, build_frontend.name
|
||||
)
|
||||
extra_flags += build_frontend.args
|
||||
|
||||
if build_options.build_frontend == "pip":
|
||||
extra_flags += verbosity_flags
|
||||
if build_frontend.name == "pip":
|
||||
extra_flags += get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
||||
# see https://github.com/pypa/cibuildwheel/pull/369
|
||||
call(
|
||||
@@ -430,9 +434,10 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
*extra_flags,
|
||||
env=env,
|
||||
)
|
||||
elif build_options.build_frontend == "build":
|
||||
verbosity_setting = " ".join(verbosity_flags)
|
||||
extra_flags += (f"--config-setting={verbosity_setting}",)
|
||||
elif build_frontend.name == "build":
|
||||
if not 0 <= build_options.build_verbosity < 2:
|
||||
msg = f"build_verbosity {build_options.build_verbosity} is not supported for build frontend. Ignoring."
|
||||
log.warning(msg)
|
||||
build_env = env.copy()
|
||||
if build_options.dependency_constraints:
|
||||
constraints_path = (
|
||||
@@ -463,7 +468,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
env=build_env,
|
||||
)
|
||||
else:
|
||||
assert_never(build_options.build_frontend)
|
||||
assert_never(build_frontend)
|
||||
|
||||
built_wheel = next(built_wheel_dir.glob("*.whl"))
|
||||
|
||||
@@ -550,6 +555,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
build_options.test_command,
|
||||
project=Path(".").resolve(),
|
||||
package=options.globals.package_dir.resolve(),
|
||||
wheel=repaired_wheel,
|
||||
)
|
||||
test_cwd = identifier_tmp_dir / "test_cwd"
|
||||
test_cwd.mkdir()
|
||||
@@ -559,6 +565,9 @@ def build(options: Options, tmp_path: Path) -> None:
|
||||
|
||||
# we're all done here; move it to output (remove if already exists)
|
||||
if compatible_wheel is None:
|
||||
with suppress(FileNotFoundError):
|
||||
(build_options.output_dir / repaired_wheel.name).unlink()
|
||||
|
||||
shutil.move(str(repaired_wheel), build_options.output_dir)
|
||||
built_wheels.append(build_options.output_dir / repaired_wheel.name)
|
||||
|
||||
|
||||
@@ -4,6 +4,79 @@ title: Changelog
|
||||
|
||||
# Changelog
|
||||
|
||||
### v2.16.1
|
||||
|
||||
_26 September 2023_
|
||||
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0rc3 (#1625)
|
||||
- 🛠 Only calls `linux32` in containers when necessary (#1599)
|
||||
|
||||
### v2.16.0
|
||||
|
||||
_18 September 2023_
|
||||
|
||||
- ✨ Add the ability to pass additional flags to a build frontend through the [CIBW_BUILD_FRONTEND](https://cibuildwheel.readthedocs.io/en/stable/options/#build-frontend) option (#1588).
|
||||
- ✨ The environment variable SOURCE_DATE_EPOCH is now automatically passed through to container Linux builds (useful for [reproducible builds](https://reproducible-builds.org/docs/source-date-epoch/)!) (#1589)
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0rc2 (#1604)
|
||||
- 🐛 Fix `requires_python` auto-detection from setup.py when the call to `setup()` is within an `if __name__ == "__main__" block (#1613)
|
||||
- 🐛 Fix a bug that prevented building Linux wheels in Docker on a Windows host (#1573)
|
||||
- 🐛 `--only` can now select prerelease-pythons (#1564)
|
||||
- 📚 Docs & examples updates (#1582, #1593, #1598, #1615)
|
||||
|
||||
### v2.15.0
|
||||
|
||||
_8 August 2023_
|
||||
|
||||
- 🌟 CPython 3.12 wheels are now built by default - without the CIBW_PRERELEASE_PYTHONS flag. It's time to build and upload these wheels to PyPI! This release includes CPython 3.12.0rc1, which is guaranteed to be ABI compatible with the final release. (#1565)
|
||||
- ✨ Adds musllinux_1_2 support - this allows packagers to build for musl-based Linux distributions on a more recent Alpine image, and a newer musl libc. (#1561)
|
||||
|
||||
### v2.14.1
|
||||
|
||||
_15 July 2023_
|
||||
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0b4 (#1550)
|
||||
|
||||
### v2.14.0
|
||||
|
||||
_10 July 2023_
|
||||
|
||||
- ✨ Adds support for building PyPy 3.10 wheels. (#1525)
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0b3.
|
||||
- ✨ Allow the use of the `{wheel}` placeholder in CIBW_TEST_COMMAND (#1533)
|
||||
- 📚 Docs & examples updates (#1532, #1416)
|
||||
- ⚠️ Removed support for running cibuildwheel in Python 3.7. Python 3.7 is EOL. However, cibuildwheel continues to build Python 3.7 wheels for the moment. (#1175)
|
||||
|
||||
### v2.13.1
|
||||
|
||||
_10 June 2023_
|
||||
|
||||
- 🛠 Updates the prerelease CPython 3.12 version to 3.12.0b2. (#1516)
|
||||
- 🛠 Adds a moving `v<major>.<minor>` tag for use in GitHub Actions workflow files. If you use this, you'll get the latest patch release within a minor version. Additionally, Dependabot won't send you PRs for patch releases. (#1517)
|
||||
|
||||
### v2.13.0
|
||||
|
||||
_28 May 2023_
|
||||
|
||||
- ✨ Adds CPython 3.12 support, under the prerelease flag [CIBW_PRERELEASE_PYTHONS](https://cibuildwheel.readthedocs.io/en/stable/options/#prerelease-pythons). This version of cibuildwheel uses 3.12.0b1.
|
||||
|
||||
While CPython is in beta, the ABI can change, so your wheels might not be compatible with the final release. For this reason, we don't recommend distributing wheels until RC1, at which point 3.12 will be available in cibuildwheel without the flag. (#1507)
|
||||
|
||||
- ✨ Adds the ability to pass arguments to the container engine when the container is created, using the [CIBW_CONTAINER_ENGINE](https://cibuildwheel.readthedocs.io/en/stable/options/#container-engine) option. (#1499)
|
||||
|
||||
### v2.12.3
|
||||
|
||||
_19 April 2023_
|
||||
|
||||
- 🐛 Fix an import error when running on Python 3.7. (#1479)
|
||||
|
||||
### v2.12.2
|
||||
|
||||
_18 April 2023_
|
||||
|
||||
- 🐛 Fix a bug that caused an extra empty config-setting to be passed to the backend when CIBW_BUILD_FRONTEND is set to `build`. (#1474)
|
||||
- 🐛 Fix a crash that occurred when overwriting an existing wheel on Windows. (#1464)
|
||||
- 🛠 Pinned version updates, including CPython 3.10.11, 3.11.3, pip 23.1 and wheel 0.40.0.
|
||||
|
||||
### v2.12.1
|
||||
|
||||
_11 March 2023_
|
||||
|
||||
+10
-7
@@ -413,8 +413,9 @@
|
||||
|
||||
- name: Tornado
|
||||
gh: tornadoweb/tornado
|
||||
ci: [travisci]
|
||||
os: [apple, linux]
|
||||
ci: [github]
|
||||
os: [linux, apple, windows]
|
||||
notes: Tornado is a Python web framework and asynchronous networking library. Uses stable ABI for a small C extension.
|
||||
|
||||
- name: pytorch-fairseq
|
||||
gh: pytorch/fairseq
|
||||
@@ -431,11 +432,6 @@
|
||||
ci: [github]
|
||||
os: [apple, linux, windows]
|
||||
|
||||
- name: pydantic
|
||||
gh: samuelcolvin/pydantic
|
||||
ci: [github]
|
||||
os: [apple, linux, windows]
|
||||
|
||||
- name: vaex
|
||||
gh: vaexio/vaex
|
||||
ci: [github]
|
||||
@@ -628,3 +624,10 @@
|
||||
os: [windows, apple, linux]
|
||||
pypi: picologging
|
||||
notes: A high-performance logging library for Python.
|
||||
|
||||
- name: aalink
|
||||
gh: artfwo/aalink
|
||||
ci: [github]
|
||||
os: [windows, apple, linux]
|
||||
pypi: aalink
|
||||
notes: Async Python interface for Ableton Link.
|
||||
|
||||
@@ -48,7 +48,7 @@ well as several useful actions. Alongside your existing job(s) that runs cibuild
|
||||
name: Make SDist
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Optional, use if you use setuptools_scm
|
||||
submodules: true # Optional, use if you have submodules
|
||||
@@ -61,13 +61,16 @@ well as several useful actions. Alongside your existing job(s) that runs cibuild
|
||||
path: dist/*.tar.gz
|
||||
```
|
||||
|
||||
Then, you need to publish the artifacts that the previous jobs have built. This final job should run only on release or tag, depending on your preference. It gathers the artifacts from the sdist and wheel jobs and uploads them to PyPI.
|
||||
Then, you need to publish the artifacts that the previous jobs have built. This final job should run only on release or tag, depending on your preference. It gathers the artifacts from the sdist and wheel jobs and uploads them to PyPI. The release environment (`pypi` in the example below) will be created the first time this workflow runs.
|
||||
|
||||
This requires a [PyPI upload token](https://pypi.org/manage/account/token/), stored in your [GitHub repo's secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository) as `pypi_password`.
|
||||
This requires setting this GitHub workflow in your project's PyPI settings (for a [new project](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc)/[existing project](https://docs.pypi.org/trusted-publishers/adding-a-publisher)).
|
||||
|
||||
```yaml
|
||||
upload_all:
|
||||
needs: [build_wheels, make_sdist]
|
||||
environment: pypi
|
||||
permissions:
|
||||
id-token: write
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
steps:
|
||||
@@ -76,10 +79,7 @@ This requires a [PyPI upload token](https://pypi.org/manage/account/token/), sto
|
||||
name: artifact
|
||||
path: dist
|
||||
|
||||
- uses: pypa/gh-action-pypi-publish@v1.5.0
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_password }}
|
||||
- uses: pypa/gh-action-pypi-publish@release/v1
|
||||
```
|
||||
|
||||
You should use Dependabot to keep the publish action up to date. In the above
|
||||
|
||||
+37
-23
@@ -20,9 +20,13 @@ Linux wheels are built in [`manylinux`/`musllinux` containers](https://github.co
|
||||
|
||||
### Building macOS wheels for Apple Silicon {: #apple-silicon}
|
||||
|
||||
`cibuildwheel` supports cross-compiling `universal2` and `arm64` wheels on `x86_64` runners. With the introduction of Apple Silicon, you now have several choices for wheels for Python 3.8+:
|
||||
`cibuildwheel` supports cross-compiling `universal2` and `arm64` wheels on `x86_64` runners.
|
||||
|
||||
#### `x86_64`
|
||||
#### Overview of Mac architectures
|
||||
|
||||
With the introduction of Apple Silicon, you now have several choices for wheels for Python 3.8+:
|
||||
|
||||
##### `x86_64`
|
||||
|
||||
The traditional wheel for Apple, loads on Intel machines, and on
|
||||
Apple Silicon when running Python under Rosetta 2 emulation.
|
||||
@@ -30,51 +34,61 @@ Apple Silicon when running Python under Rosetta 2 emulation.
|
||||
Due to a change in naming, Pip 20.3+ (or an installer using packaging 20.5+)
|
||||
is required to install a binary wheel on macOS Big Sur.
|
||||
|
||||
#### `arm64`
|
||||
##### `arm64`
|
||||
|
||||
The native wheel for macOS on Apple Silicon.
|
||||
|
||||
Requires Pip 20.3+ (or packaging 20.5+) to install.
|
||||
|
||||
#### `universal2`
|
||||
##### `universal2`
|
||||
|
||||
This wheel contains both architectures, causing it to be up to twice the
|
||||
size (data files do not get doubled, only compiled code). It requires
|
||||
Pip 20.3 (Packaging 20.6+) to load on Intel, and Pip 21.0.1 (Packaging 20.9+)
|
||||
to load on Apple Silicon.
|
||||
|
||||
!!! note
|
||||
The dual-architecture `universal2` has a few benefits, but a key benefit
|
||||
to a universal wheel is that a user can bundle these wheels into an
|
||||
application and ship a single binary.
|
||||
The dual-architecture `universal2` has a few benefits, but a key benefit
|
||||
to a universal wheel is that a user can bundle these wheels into an
|
||||
application and ship a single binary.
|
||||
|
||||
However, if you have a large library, then you might prefer to ship
|
||||
the two single-arch wheels instead - `x86_64` and `arm64`. In rare cases,
|
||||
you might want to build all three, but in that case, pip will not download
|
||||
the universal wheels, because it prefers the most specific wheel
|
||||
available.
|
||||
However, if you have a large library, then you might prefer to ship
|
||||
the two single-arch wheels instead - `x86_64` and `arm64`. In rare cases,
|
||||
you might want to build all three, but in that case, pip will not download
|
||||
the universal wheels, because it prefers the most specific wheel
|
||||
available.
|
||||
|
||||
#### What to provide?
|
||||
|
||||
Generally speaking, because Pip 20.3 is required for the `universal2` wheel,
|
||||
most packages should provide both `x86_64` and one of `universal2`/`arm64`
|
||||
wheels for now. When Pip 20.3+ is common on macOS, then it might be possible
|
||||
to ship only the `universal2` wheel.
|
||||
wheels. When Pip 20.3+ is common on macOS, then it might be possible to ship
|
||||
only the `universal2` wheel.
|
||||
|
||||
**Apple Silicon wheels are not built by default on Intel runners**, but can be enabled by adding extra archs to the [`CIBW_ARCHS_MACOS` option](options.md#archs) - e.g. `x86_64 arm64`. Cross-compilation is provided by the Xcode toolchain.
|
||||
Opinions vary on which of arch-specific or `universal2` wheels are best - some packagers prefer `universal2` because it's one wheel for all Mac users, so simpler, and easier to build into apps for downstream users. However, because they contain code for both architectures, their file size is larger, meaning they consume more disk space and bandwidth, and are harder to build for some projects.
|
||||
|
||||
See [GitHub issue 1333](https://github.com/pypa/cibuildwheel/issues/1333) for more discussion.
|
||||
|
||||
#### How to cross-compile
|
||||
|
||||
With the exception of Cirrus CI, macOS CI runners are still Intel-based, and Apple Silicon wheels are not built by default on Intel runners. However, cross-compilation can be enabled by adding extra archs to the [`CIBW_ARCHS_MACOS` option](options.md#archs) - e.g. `x86_64 arm64`. Cross-compilation is provided by the Xcode toolchain.
|
||||
|
||||
!!! important
|
||||
When cross-compiling on Intel, it is not possible to test `arm64` and the `arm64` part of a `universal2` wheel.
|
||||
|
||||
`cibuildwheel` will raise a warning to notify you of this - these warnings be be silenced by skipping testing on these platforms: `CIBW_TEST_SKIP: *_arm64 *_universal2:arm64`.
|
||||
|
||||
Hopefully, cross-compilation is a temporary situation. Once we have widely
|
||||
available Apple Silicon CI runners, we can build and test `arm64` and
|
||||
`universal2` wheels natively. That's why `universal2`/`arm64` wheels require opt-in by setting `CIBW_ARCHS_MACOS`.
|
||||
|
||||
!!! note
|
||||
Your runner needs Xcode Command Line Tools 12.2 or later to build `universal2` or `arm64`.
|
||||
|
||||
Only CPython 3.8 and newer support `universal2` and `arm64` wheels.
|
||||
|
||||
!!! note
|
||||
If your project uses **Poetry** as a build backend, cross-compiling on macOS [does not currently work](https://github.com/python-poetry/poetry/issues/7107). In some cases arm64 wheels can be built but their tags will be incorrect, with the platform tag showing `x86_64` instead of `arm64`.
|
||||
|
||||
As a workaround, the tag can be fixed before running delocate to repair the wheel. The [`wheel tags`](https://wheel.readthedocs.io/en/stable/reference/wheel_tags.html) command is ideal for this. See [this workflow](https://gist.github.com/anderssonjohan/49f07e33fc5cb2420515a8ac76dc0c95#file-build-pendulum-wheels-yml-L39-L53) for an example usage of `wheel tags`.
|
||||
|
||||
Hopefully, cross-compilation is a temporary situation. Once we have widely available Apple Silicon CI runners, we can build `arm64` wheels natively. Until then, cross-compiling `arm64` or `universal2` wheels requires opt-in by setting `CIBW_ARCHS_MACOS` on Intel runners.
|
||||
|
||||
Here's an example GitHub Actions workflow with a job that builds for Apple Silicon:
|
||||
|
||||
> .github/workflows/build_macos.yml
|
||||
@@ -145,7 +159,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@v2.12.1
|
||||
uses: pypa/cibuildwheel@v2.16.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.
|
||||
@@ -167,7 +181,7 @@ The second option, and the only one that supports other CI systems, is using a `
|
||||
|
||||
```bash
|
||||
# requirements-cibw.txt
|
||||
cibuildwheel==2.12.1
|
||||
cibuildwheel==2.16.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:
|
||||
@@ -311,7 +325,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==2.12.1 --output-dir wheelhouse
|
||||
pipx run cibuildwheel==2.16.1 --output-dir wheelhouse
|
||||
pipx run twine upload wheelhouse/*.whl
|
||||
```
|
||||
|
||||
|
||||
+70
-25
@@ -92,8 +92,8 @@ Options have the same names as the environment variable overrides, but are
|
||||
placed in `[tool.cibuildwheel]` and are lower case, with dashes, following
|
||||
common [TOML][] practice. Anything placed in subsections `linux`, `windows`,
|
||||
or `macos` will only affect those platforms. Lists can be used instead of
|
||||
strings for items that are natually a list. Multiline strings also work just
|
||||
like in in the environment variables. Environment variables will take
|
||||
strings for items that are naturally a list. Multiline strings also work just
|
||||
like in the environment variables. Environment variables will take
|
||||
precedence if defined.
|
||||
|
||||
The example above using environment variables could have been written like this:
|
||||
@@ -218,17 +218,19 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat
|
||||
|
||||
<div class="build-id-table-marker"></div>
|
||||
|
||||
| | macOS | Windows | Linux Intel | Linux Other |
|
||||
|--------------|------------------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Python 3.6 | cp36-macosx_x86_64 | cp36-win_amd64<br/>cp36-win32 | cp36-manylinux_x86_64<br/>cp36-manylinux_i686<br/>cp36-musllinux_x86_64<br/>cp36-musllinux_i686 | cp36-manylinux_aarch64<br/>cp36-manylinux_ppc64le<br/>cp36-manylinux_s390x<br/>cp36-musllinux_aarch64<br/>cp36-musllinux_ppc64le<br/>cp36-musllinux_s390x |
|
||||
| Python 3.7 | cp37-macosx_x86_64 | cp37-win_amd64<br/>cp37-win32 | cp37-manylinux_x86_64<br/>cp37-manylinux_i686<br/>cp37-musllinux_x86_64<br/>cp37-musllinux_i686 | cp37-manylinux_aarch64<br/>cp37-manylinux_ppc64le<br/>cp37-manylinux_s390x<br/>cp37-musllinux_aarch64<br/>cp37-musllinux_ppc64le<br/>cp37-musllinux_s390x |
|
||||
| Python 3.8 | cp38-macosx_x86_64<br/>cp38-macosx_universal2<br/>cp38-macosx_arm64 | cp38-win_amd64<br/>cp38-win32 | cp38-manylinux_x86_64<br/>cp38-manylinux_i686<br/>cp38-musllinux_x86_64<br/>cp38-musllinux_i686 | cp38-manylinux_aarch64<br/>cp38-manylinux_ppc64le<br/>cp38-manylinux_s390x<br/>cp38-musllinux_aarch64<br/>cp38-musllinux_ppc64le<br/>cp38-musllinux_s390x |
|
||||
| Python 3.9 | cp39-macosx_x86_64<br/>cp39-macosx_universal2<br/>cp39-macosx_arm64 | cp39-win_amd64<br/>cp39-win32<br/>cp39-win_arm64 | cp39-manylinux_x86_64<br/>cp39-manylinux_i686<br/>cp39-musllinux_x86_64<br/>cp39-musllinux_i686 | cp39-manylinux_aarch64<br/>cp39-manylinux_ppc64le<br/>cp39-manylinux_s390x<br/>cp39-musllinux_aarch64<br/>cp39-musllinux_ppc64le<br/>cp39-musllinux_s390x |
|
||||
| Python 3.10 | cp310-macosx_x86_64<br/>cp310-macosx_universal2<br/>cp310-macosx_arm64 | cp310-win_amd64<br/>cp310-win32<br/>cp310-win_arm64 | cp310-manylinux_x86_64<br/>cp310-manylinux_i686<br/>cp310-musllinux_x86_64<br/>cp310-musllinux_i686 | cp310-manylinux_aarch64<br/>cp310-manylinux_ppc64le<br/>cp310-manylinux_s390x<br/>cp310-musllinux_aarch64<br/>cp310-musllinux_ppc64le<br/>cp310-musllinux_s390x |
|
||||
| Python 3.11 | cp311-macosx_x86_64<br/>cp311-macosx_universal2<br/>cp311-macosx_arm64 | cp311-win_amd64<br/>cp311-win32<br/>cp311-win_arm64 | cp311-manylinux_x86_64<br/>cp311-manylinux_i686<br/>cp311-musllinux_x86_64<br/>cp311-musllinux_i686 | cp311-manylinux_aarch64<br/>cp311-manylinux_ppc64le<br/>cp311-manylinux_s390x<br/>cp311-musllinux_aarch64<br/>cp311-musllinux_ppc64le<br/>cp311-musllinux_s390x |
|
||||
| PyPy3.7 v7.3 | pp37-macosx_x86_64 | pp37-win_amd64 | pp37-manylinux_x86_64<br/>pp37-manylinux_i686 | pp37-manylinux_aarch64 |
|
||||
| PyPy3.8 v7.3 | pp38-macosx_x86_64<br/>pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64<br/>pp38-manylinux_i686 | pp38-manylinux_aarch64 |
|
||||
| PyPy3.9 v7.3 | pp39-macosx_x86_64<br/>pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64<br/>pp39-manylinux_i686 | pp39-manylinux_aarch64 |
|
||||
| | macOS | Windows | Linux Intel | Linux Other |
|
||||
|---------------|------------------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Python 3.6 | cp36-macosx_x86_64 | cp36-win_amd64<br/>cp36-win32 | cp36-manylinux_x86_64<br/>cp36-manylinux_i686<br/>cp36-musllinux_x86_64<br/>cp36-musllinux_i686 | cp36-manylinux_aarch64<br/>cp36-manylinux_ppc64le<br/>cp36-manylinux_s390x<br/>cp36-musllinux_aarch64<br/>cp36-musllinux_ppc64le<br/>cp36-musllinux_s390x |
|
||||
| Python 3.7 | cp37-macosx_x86_64 | cp37-win_amd64<br/>cp37-win32 | cp37-manylinux_x86_64<br/>cp37-manylinux_i686<br/>cp37-musllinux_x86_64<br/>cp37-musllinux_i686 | cp37-manylinux_aarch64<br/>cp37-manylinux_ppc64le<br/>cp37-manylinux_s390x<br/>cp37-musllinux_aarch64<br/>cp37-musllinux_ppc64le<br/>cp37-musllinux_s390x |
|
||||
| Python 3.8 | cp38-macosx_x86_64<br/>cp38-macosx_universal2<br/>cp38-macosx_arm64 | cp38-win_amd64<br/>cp38-win32 | cp38-manylinux_x86_64<br/>cp38-manylinux_i686<br/>cp38-musllinux_x86_64<br/>cp38-musllinux_i686 | cp38-manylinux_aarch64<br/>cp38-manylinux_ppc64le<br/>cp38-manylinux_s390x<br/>cp38-musllinux_aarch64<br/>cp38-musllinux_ppc64le<br/>cp38-musllinux_s390x |
|
||||
| Python 3.9 | cp39-macosx_x86_64<br/>cp39-macosx_universal2<br/>cp39-macosx_arm64 | cp39-win_amd64<br/>cp39-win32<br/>cp39-win_arm64 | cp39-manylinux_x86_64<br/>cp39-manylinux_i686<br/>cp39-musllinux_x86_64<br/>cp39-musllinux_i686 | cp39-manylinux_aarch64<br/>cp39-manylinux_ppc64le<br/>cp39-manylinux_s390x<br/>cp39-musllinux_aarch64<br/>cp39-musllinux_ppc64le<br/>cp39-musllinux_s390x |
|
||||
| Python 3.10 | cp310-macosx_x86_64<br/>cp310-macosx_universal2<br/>cp310-macosx_arm64 | cp310-win_amd64<br/>cp310-win32<br/>cp310-win_arm64 | cp310-manylinux_x86_64<br/>cp310-manylinux_i686<br/>cp310-musllinux_x86_64<br/>cp310-musllinux_i686 | cp310-manylinux_aarch64<br/>cp310-manylinux_ppc64le<br/>cp310-manylinux_s390x<br/>cp310-musllinux_aarch64<br/>cp310-musllinux_ppc64le<br/>cp310-musllinux_s390x |
|
||||
| Python 3.11 | cp311-macosx_x86_64<br/>cp311-macosx_universal2<br/>cp311-macosx_arm64 | cp311-win_amd64<br/>cp311-win32<br/>cp311-win_arm64 | cp311-manylinux_x86_64<br/>cp311-manylinux_i686<br/>cp311-musllinux_x86_64<br/>cp311-musllinux_i686 | cp311-manylinux_aarch64<br/>cp311-manylinux_ppc64le<br/>cp311-manylinux_s390x<br/>cp311-musllinux_aarch64<br/>cp311-musllinux_ppc64le<br/>cp311-musllinux_s390x |
|
||||
| Python 3.12 | cp312-macosx_x86_64<br/>cp312-macosx_universal2<br/>cp312-macosx_arm64 | cp312-win_amd64<br/>cp312-win32<br/>cp312-win_arm64 | cp312-manylinux_x86_64<br/>cp312-manylinux_i686<br/>cp312-musllinux_x86_64<br/>cp312-musllinux_i686 | cp312-manylinux_aarch64<br/>cp312-manylinux_ppc64le<br/>cp312-manylinux_s390x<br/>cp312-musllinux_aarch64<br/>cp312-musllinux_ppc64le<br/>cp312-musllinux_s390x |
|
||||
| PyPy3.7 v7.3 | pp37-macosx_x86_64 | pp37-win_amd64 | pp37-manylinux_x86_64<br/>pp37-manylinux_i686 | pp37-manylinux_aarch64 |
|
||||
| PyPy3.8 v7.3 | pp38-macosx_x86_64<br/>pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64<br/>pp38-manylinux_i686 | pp38-manylinux_aarch64 |
|
||||
| PyPy3.9 v7.3 | pp39-macosx_x86_64<br/>pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64<br/>pp39-manylinux_i686 | pp39-manylinux_aarch64 |
|
||||
| PyPy3.10 v7.3 | pp310-macosx_x86_64<br/>pp310-macosx_arm64 | pp310-win_amd64 | pp310-manylinux_x86_64<br/>pp310-manylinux_i686 | pp310-manylinux_aarch64 |
|
||||
|
||||
The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to cibuildwheel.
|
||||
The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details).
|
||||
@@ -237,7 +239,7 @@ For CPython, the minimally supported macOS version is 10.9; for PyPy 3.7, macOS
|
||||
|
||||
Windows arm64 platform support is experimental.
|
||||
|
||||
See the [cibuildwheel 1 documentation](https://cibuildwheel.readthedocs.io/en/1.x/) for past end of life versions of Python, and PyPy2.7.
|
||||
See the [cibuildwheel 1 documentation](https://cibuildwheel.readthedocs.io/en/1.x/) for past end-of-life versions of Python, and PyPy2.7.
|
||||
|
||||
#### Examples
|
||||
|
||||
@@ -314,7 +316,7 @@ See the [cibuildwheel 1 documentation](https://cibuildwheel.readthedocs.io/en/1.
|
||||
|
||||
It is generally recommended to set `CIBW_BUILD` as an environment variable, though `skip`
|
||||
tends to be useful in a config file; you can statically declare that you don't
|
||||
support pypy, for example.
|
||||
support PyPy, for example.
|
||||
|
||||
<style>
|
||||
.build-id-table-marker + table {
|
||||
@@ -502,9 +504,19 @@ This option can also be set using the [command-line option](#command-line) `--pr
|
||||
### `CIBW_BUILD_FRONTEND` {: #build-frontend}
|
||||
> Set the tool to use to build, either "pip" (default for now) or "build"
|
||||
|
||||
Choose which build backend to use. Can either be "pip", which will run
|
||||
Options:
|
||||
|
||||
- `pip[;args: ...]`
|
||||
- `build[;args: ...]`
|
||||
|
||||
Default: `pip`
|
||||
|
||||
Choose which build frontend to use. Can either be "pip", which will run
|
||||
`python -m pip wheel`, or "build", which will run `python -m build --wheel`.
|
||||
|
||||
You can specify extra arguments to pass to `pip wheel` or `build` using the
|
||||
optional `args` option.
|
||||
|
||||
!!! tip
|
||||
Until v2.0.0, [pip] was the only way to build wheels, and is still the
|
||||
default. However, we expect that at some point in the future, cibuildwheel
|
||||
@@ -524,6 +536,9 @@ Choose which build backend to use. Can either be "pip", which will run
|
||||
|
||||
# Ensure pip is used even if the default changes in the future
|
||||
CIBW_BUILD_FRONTEND: "pip"
|
||||
|
||||
# supply an extra argument to 'pip wheel'
|
||||
CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation"
|
||||
```
|
||||
|
||||
!!! tab examples "pyproject.toml"
|
||||
@@ -535,6 +550,9 @@ Choose which build backend to use. Can either be "pip", which will run
|
||||
|
||||
# Ensure pip is used even if the default changes in the future
|
||||
build-frontend = "pip"
|
||||
|
||||
# supply an extra argument to 'pip wheel'
|
||||
build-frontend = { name = "pip", args = ["--no-build-isolation"] }
|
||||
```
|
||||
|
||||
### `CIBW_CONFIG_SETTINGS` {: #config-settings}
|
||||
@@ -549,7 +567,7 @@ a table of items, including arrays.
|
||||
single values.
|
||||
|
||||
Platform-specific environment variables also available:<br/>
|
||||
`CIBW_BEFORE_ALL_MACOS` | `CIBW_BEFORE_ALL_WINDOWS` | `CIBW_BEFORE_ALL_LINUX`
|
||||
`CIBW_CONFIG_SETTINGS_MACOS` | `CIBW_CONFIG_SETTINGS_WINDOWS` | `CIBW_CONFIG_SETTINGS_LINUX`
|
||||
|
||||
|
||||
#### Examples
|
||||
@@ -658,10 +676,13 @@ Platform-specific environment variables are also available:<br/>
|
||||
### `CIBW_ENVIRONMENT_PASS_LINUX` {: #environment-pass}
|
||||
> Set environment variables on the host to pass-through to the container during the build.
|
||||
|
||||
A list of environment variables to pass into the linux container during the build. It has no affect on the other platforms, which can already access all environment variables directly.
|
||||
A list of environment variables to pass into the linux container during the build. It has no effect on the other platforms, which can already access all environment variables directly.
|
||||
|
||||
To specify more than one environment variable, separate the variable names by spaces.
|
||||
|
||||
!!! note
|
||||
cibuildwheel automatically passes the environment variable [`SOURCE_DATE_EPOCH`](https://reproducible-builds.org/docs/source-date-epoch/) if defined.
|
||||
|
||||
#### Examples
|
||||
|
||||
!!! tab examples "Environment passthrough"
|
||||
@@ -979,7 +1000,7 @@ Set an alternative Docker image to be used for building [manylinux / musllinux](
|
||||
For `CIBW_MANYLINUX_*_IMAGE`, the value of this option can either be set to `manylinux1`, `manylinux2010`, `manylinux2014`, `manylinux_2_24` or `manylinux_2_28` 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 PyPy, the `manylinux1` image is not available. For architectures other
|
||||
than x86 (x86\_64 and i686) `manylinux2014`, `manylinux_2_24` or `manylinux_2_28` must be used, because the first version of the manylinux specification that supports additional architectures is `manylinux2014`. `manylinux_2_28` is not supported for `i686` architecture.
|
||||
|
||||
For `CIBW_MUSLLINUX_*_IMAGE`, the value of this option can either be set to `musllinux_1_1` to use a pinned version of the [official musllinux images](https://github.com/pypa/musllinux). Alternatively, set these options to any other valid Docker image name.
|
||||
For `CIBW_MUSLLINUX_*_IMAGE`, the value of this option can either be set to `musllinux_1_1` or `musllinux_1_2` to use a pinned version of the [official musllinux images](https://github.com/pypa/musllinux). Alternatively, set these options to any other valid Docker image name.
|
||||
|
||||
If this option is blank, it will fall though to the next available definition (environment variable -> pyproject.toml -> default).
|
||||
|
||||
@@ -1048,9 +1069,12 @@ Auditwheel detects the version of the manylinux / musllinux standard in the imag
|
||||
|
||||
|
||||
### `CIBW_CONTAINER_ENGINE` {: #container-engine}
|
||||
> Specify which container engine to use when building Linux wheels
|
||||
> Specify the container engine to use when building Linux wheels
|
||||
|
||||
Options: `docker` `podman`
|
||||
Options:
|
||||
|
||||
- `docker[;create_args: ...]`
|
||||
- `podman[;create_args: ...]`
|
||||
|
||||
Default: `docker`
|
||||
|
||||
@@ -1059,6 +1083,12 @@ Set the container engine to use. Docker is the default, or you can switch to
|
||||
running and `docker` available on PATH. To use Podman, it needs to be
|
||||
installed and `podman` available on PATH.
|
||||
|
||||
Arguments can be supplied to the container engine. Currently, the only option
|
||||
that's customisable is 'create_args'. Parameters to create_args are
|
||||
space-separated strings, which are passed to the container engine on the
|
||||
command line when it's creating the container. If you want to include spaces
|
||||
inside a parameter, use shell-style quoting.
|
||||
|
||||
!!! tip
|
||||
|
||||
While most users will stick with Docker, Podman is available in different
|
||||
@@ -1073,14 +1103,22 @@ installed and `podman` available on PATH.
|
||||
!!! tab examples "Environment variables"
|
||||
|
||||
```yaml
|
||||
# use podman instead of docker
|
||||
CIBW_CONTAINER_ENGINE: podman
|
||||
|
||||
# pass command line options to 'docker create'
|
||||
CIBW_CONTAINER_ENGINE: "docker; create_args: --gpus all"
|
||||
```
|
||||
|
||||
!!! tab examples "pyproject.toml"
|
||||
|
||||
```toml
|
||||
[tool.cibuildwheel]
|
||||
# use podman instead of docker
|
||||
container-engine = "podman"
|
||||
|
||||
# pass command line options to 'docker create'
|
||||
container-engine = { name = "docker", create-args = ["--gpus", "all"]}
|
||||
```
|
||||
|
||||
|
||||
@@ -1214,6 +1252,13 @@ Platform-specific environment variables are also available:<br/>
|
||||
|
||||
In configuration files, you can use an array, and the items will be joined with `&&`.
|
||||
|
||||
!!! note
|
||||
|
||||
It isn't recommended to `cd` to your project directory before running tests,
|
||||
because Python might resolve `import yourpackage` relative to the working dir,
|
||||
and we want to test the wheel you just built. However, if you're sure that's not
|
||||
an issue for you and your workflow requires it, on Windows you should do `cd /d`,
|
||||
because the CWD and project dir might be on different drives.
|
||||
|
||||
### `CIBW_BEFORE_TEST` {: #before-test}
|
||||
> Execute a shell command before testing each wheel
|
||||
@@ -1319,11 +1364,11 @@ Platform-specific environment variables are also available:<br/>
|
||||
> Install your wheel for testing using `extras_require`
|
||||
|
||||
List of
|
||||
[extras_require](https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies)
|
||||
[extras_require](https://setuptools.pypa.io/en/latest/userguide/dependency_management.html#declaring-required-dependency)
|
||||
options that should be included when installing the wheel prior to running the
|
||||
tests. This can be used to avoid having to redefine test dependencies in
|
||||
`CIBW_TEST_REQUIRES` if they are already defined in `setup.py` or
|
||||
`setup.cfg`.
|
||||
`CIBW_TEST_REQUIRES` if they are already defined in `pyproject.toml`,
|
||||
`setup.cfg` or `setup.py`.
|
||||
|
||||
Platform-specific environment variables are also available:<br/>
|
||||
`CIBW_TEST_EXTRAS_MACOS` | `CIBW_TEST_EXTRAS_WINDOWS` | `CIBW_TEST_EXTRAS_LINUX`
|
||||
@@ -1386,7 +1431,7 @@ This option is not supported in the overrides section in `pyproject.toml`.
|
||||
### `CIBW_BUILD_VERBOSITY` {: #build-verbosity}
|
||||
> Increase/decrease the output of pip wheel
|
||||
|
||||
An number from 1 to 3 to increase the level of verbosity (corresponding to invoking pip with `-v`, `-vv`, and `-vvv`), between -1 and -3 (`-q`, `-qq`, and `-qqq`), or just 0 (default verbosity). These flags are useful while debugging a build when the output of the actual build invoked by `pip wheel` is required.
|
||||
A number from 1 to 3 to increase the level of verbosity (corresponding to invoking pip with `-v`, `-vv`, and `-vvv`), between -1 and -3 (`-q`, `-qq`, and `-qqq`), or just 0 (default verbosity). These flags are useful while debugging a build when the output of the actual build invoked by `pip wheel` is required. Has no effect on the `build` backend, which produces verbose output by default.
|
||||
|
||||
Platform-specific environment variables are also available:<br/>
|
||||
`CIBW_BUILD_VERBOSITY_MACOS` | `CIBW_BUILD_VERBOSITY_WINDOWS` | `CIBW_BUILD_VERBOSITY_LINUX`
|
||||
|
||||
+4
-4
@@ -181,10 +181,10 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
|
||||
os: [ubuntu-20.04, windows-2019, macos-11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build wheels
|
||||
run: pipx run cibuildwheel==2.12.1
|
||||
run: pipx run cibuildwheel==2.16.1
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -213,13 +213,13 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
|
||||
os: [ubuntu-20.04, windows-2019, macos-11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Used to host cibuildwheel
|
||||
- uses: actions/setup-python@v3
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: python -m pip install cibuildwheel==2.12.1
|
||||
run: python -m pip install cibuildwheel==2.16.1
|
||||
|
||||
- name: Build wheels
|
||||
run: python -m cibuildwheel --output-dir wheelhouse
|
||||
|
||||
+59
-59
@@ -9,215 +9,215 @@ title: Working examples
|
||||
| Name | CI | OS | Notes |
|
||||
|-----------------------------------|----|----|:------|
|
||||
| [scikit-learn][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The machine learning library. A complex but clean config using many of cibuildwheel's features to build a large project with Cython and C++ extensions. |
|
||||
| [NumPy][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The fundamental package for scientific computing with Python. |
|
||||
| [pytorch-fairseq][] | ![github icon][] | ![apple icon][] ![linux icon][] | Facebook AI Research Sequence-to-Sequence Toolkit written in Python. |
|
||||
| [Tornado][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. |
|
||||
| [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. |
|
||||
| [Matplotlib][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The venerable Matplotlib, a Python library with C++ portions |
|
||||
| [NCNN][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | ncnn is a high-performance neural network inference framework optimized for the mobile platform |
|
||||
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
|
||||
| [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. |
|
||||
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | The compiled version of MyPy using MyPyC. |
|
||||
| [pydantic][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Data validation using Python type hints |
|
||||
| [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. |
|
||||
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
|
||||
| [duckdb][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | DuckDB is an in-process SQL OLAP Database Management System |
|
||||
| [MemRay][] | ![github icon][] | ![linux icon][] | Memray is a memory profiler for Python |
|
||||
| [uvloop][] | ![github icon][] | ![apple icon][] ![linux icon][] | Ultra fast asyncio event loop. |
|
||||
| [psutil][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Cross-platform lib for process and system monitoring in Python |
|
||||
| [duckdb][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | DuckDB is an in-process SQL OLAP Database Management System |
|
||||
| [Triton][] | ![github icon][] | ![linux icon][] | Self hosted runners |
|
||||
| [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 🚀 |
|
||||
| [Google Benchmark][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A microbenchmark support library |
|
||||
| [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. |
|
||||
| [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. |
|
||||
| [Triton][] | ![github icon][] | ![linux icon][] | Self hosted runners |
|
||||
| [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. |
|
||||
| [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. |
|
||||
| [twisted-iocpsupport][] | ![github icon][] | ![windows icon][] | A submodule of Twisted that hooks into native C APIs using Cython. |
|
||||
| [PyOxidizer][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A modern Python application packaging and distribution tool |
|
||||
| [websockets][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Library for building WebSocket servers and clients. Mostly written in Python, with a small C 'speedups' extension module. |
|
||||
| [cvxpy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A Python-embedded modeling language for convex optimization problems. |
|
||||
| [websockets][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Library for building WebSocket servers and clients. Mostly written in Python, with a small C 'speedups' extension module. |
|
||||
| [River][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | 🌊 Online machine learning in Python |
|
||||
| [UltraJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Ultra fast JSON decoder and encoder written in C with Python bindings |
|
||||
| [OpenSpiel][] | ![github icon][] | ![apple icon][] ![linux icon][] | OpenSpiel is a collection of environments and algorithms for research in general reinforcement learning and search/planning in games. |
|
||||
| [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. |
|
||||
| [aiortc][] | ![github icon][] | ![apple icon][] ![linux icon][] | WebRTC and ORTC implementation for Python using asyncio. |
|
||||
| [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. |
|
||||
| [Confluent client for Kafka][] | ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | setup in `tools/wheels/build-wheels.bat` |
|
||||
| [Implicit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes GPU support for linux wheels |
|
||||
| [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
|
||||
| [vispy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Main repository for Vispy |
|
||||
| [tinyobjloader][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Tiny but powerful single file wavefront obj loader |
|
||||
| [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
|
||||
| [coverage.py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The coverage tool for Python |
|
||||
| [PyCryptodome][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A self-contained cryptographic library for Python |
|
||||
| [PyYAML][] | ![github icon][] | ![apple icon][] | Canonical source repository for PyYAML |
|
||||
| [numexpr][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast numerical array expression evaluator for Python, NumPy, PyTables, pandas, bcolz and more |
|
||||
| [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. |
|
||||
| [Wrapt][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python module for decorators, wrappers and monkey patching. |
|
||||
| [PyAV][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Pythonic bindings for FFmpeg's libraries. |
|
||||
| [Line Profiler][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Line-by-line profiling for Python |
|
||||
| [pikepdf][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python library for reading and writing PDF, powered by qpdf |
|
||||
| [SimpleJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | simplejson is a simple, fast, extensible JSON encoder/decoder for Python |
|
||||
| [envd][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | 🏕️ Reproducible development environment for AI/ML |
|
||||
| [numexpr][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast numerical array expression evaluator for Python, NumPy, PyTables, pandas, bcolz and more |
|
||||
| [PyAV][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Pythonic bindings for FFmpeg's libraries. |
|
||||
| [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. |
|
||||
| [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. |
|
||||
| [Wrapt][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python module for decorators, wrappers and monkey patching. |
|
||||
| [pikepdf][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python library for reading and writing PDF, powered by QPDF |
|
||||
| [envd][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | 🏕️ Reproducible development environment |
|
||||
| [OpenColorIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A color management framework for visual effects and animation. |
|
||||
| [SimpleJSON][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | simplejson is a simple, fast, extensible JSON encoder/decoder for Python |
|
||||
| [aioquic][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | QUIC and HTTP/3 implementation in Python |
|
||||
| [ruptures][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Extensive Cython + NumPy [pyproject.toml](https://github.com/deepcharles/ruptures/blob/master/pyproject.toml) example. |
|
||||
| [OpenTimelineIO][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Open Source API and interchange format for editorial timeline information. |
|
||||
| [PyTables][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A Python package to manage extremely large amounts of data |
|
||||
| [ruptures][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Extensive Cython + NumPy [pyproject.toml](https://github.com/deepcharles/ruptures/blob/master/pyproject.toml) example. |
|
||||
| [Psycopg 3][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A modern implementation of a PostgreSQL adapter for Python |
|
||||
| [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. |
|
||||
| [DeepForest][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | An Efficient, Scalable and Optimized Python Framework for Deep Forest (2021.2.1) |
|
||||
| [google neuroglancer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | WebGL-based viewer for volumetric data |
|
||||
| [AutoPy][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
|
||||
| [H3-py][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for H3, a hierarchical hexagonal geospatial indexing system |
|
||||
| [mosec][] | ![github icon][] | ![linux icon][] ![apple icon][] | A high-performance ML model serving framework, offers dynamic batching and CPU/GPU pipelines to fully exploit your compute machine |
|
||||
| [Rtree][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Rtree: spatial index for Python GIS ¶ |
|
||||
| [markupsafe][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Safely add untrusted strings to HTML/XML markup. |
|
||||
| [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. |
|
||||
| [Picologging][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A high-performance logging library for Python. |
|
||||
| [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 |
|
||||
| [time-machine][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Time mocking library using only the CPython C API. |
|
||||
| [KDEpy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Kernel Density Estimation in Python |
|
||||
| [python-rapidjson][] | ![travisci icon][] ![gitlab icon][] ![appveyor icon][] | ![windows icon][] ![linux icon][] | Python wrapper around rapidjson |
|
||||
| [python-snappy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for the snappy google library |
|
||||
| [KDEpy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Kernel Density Estimation in Python |
|
||||
| [time-machine][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Time mocking library using only the CPython C API. |
|
||||
| [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 |
|
||||
| [dd-trace-py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Uses custom alternate arch emulation on GitHub |
|
||||
| [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. |
|
||||
| [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. |
|
||||
| [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. |
|
||||
| [jq.py][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Python bindings for jq |
|
||||
| [mosec][] | ![github icon][] | ![linux icon][] ![apple icon][] | A high-performance serving framework for ML models, offers dynamic batching and multi-stage pipeline to fully exploit your compute machine |
|
||||
| [iminuit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Jupyter-friendly Python interface for C++ MINUIT2 |
|
||||
| [Tokenizer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast and customizable text tokenization library with BPE and SentencePiece support |
|
||||
| [PyGLM][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Fast OpenGL Mathematics (GLM) for Python |
|
||||
| [TgCrypto][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
|
||||
| [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. |
|
||||
| [iDynTree][] | ![github icon][] | ![linux icon][] | Uses manylinux_2_24 |
|
||||
| [boost-histogram][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Supports full range of wheels, including PyPy and alternate archs. |
|
||||
| [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. |
|
||||
| [Python-WebRTC][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | a Python extension that provides bindings to WebRTC M92 |
|
||||
| [pybase64][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast Base64 encoding/decoding in Python |
|
||||
| [Arbor][] | ![github icon][] | ![apple icon][] ![linux icon][] | Arbor is a multi-compartment neuron simulation library; compatible with next-generation accelerators; best-practices applied to research software; focused on community-driven development. Includes a [small script](https://github.com/arbor-sim/arbor/blob/master/scripts/patchwheel.py) patching `rpath` in bundled libraries. |
|
||||
| [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. |
|
||||
| [fathon][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | python package for DFA (Detrended Fluctuation Analysis) and related algorithms |
|
||||
| [power-grid-model][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python/C++ library for distribution power system analysis |
|
||||
| [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. |
|
||||
| [polaroid][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Full range of wheels for setuptools rust, with auto release and PyPI deploy. |
|
||||
| [power-grid-model][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python/C++ library for distribution power system analysis |
|
||||
| [pybind11 scikit_build_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | An example combining scikit-build and pybind11 |
|
||||
| [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 |
|
||||
| [clang-format][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Scikit-build wrapper around LLVM's CMake, all platforms, generic wheels. |
|
||||
| [pybind11 scikit_build_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | An example combining scikit-build and pybind11 |
|
||||
| [numpythia][] | ![github icon][] | ![apple icon][] ![linux icon][] | The interface between PYTHIA and NumPy |
|
||||
| [ninja][] | ![github icon][] ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Multitagged binary builds for all supported platforms, using cibw 2 config configuration. |
|
||||
| [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 |
|
||||
| [GSD][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Cython and NumPy project with 64-bit wheels. |
|
||||
| [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. |
|
||||
| [SiPM][] | ![github icon][] | ![apple icon][] ![linux icon][] | High performance library for SiPM detectors simulation using C++17, OpenMP and AVX2 intrinsics. |
|
||||
| [CorrectionLib][] | ![github icon][] | ![apple icon][] ![linux icon][] | Structured JSON powered correction library for HEP, designed for the CMS experiment at CERN. |
|
||||
| [pyinstrument_cext][] | ![travisci icon][] ![appveyor icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | A simple C extension, without external dependencies |
|
||||
| [xmlstarlet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python 3.6+ CFFI bindings with true MSVC build. |
|
||||
| [aalink][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Async Python interface for Ableton Link. |
|
||||
| [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 |
|
||||
|
||||
[scikit-learn]: https://github.com/scikit-learn/scikit-learn
|
||||
[NumPy]: https://github.com/numpy/numpy
|
||||
[pytorch-fairseq]: https://github.com/pytorch/fairseq
|
||||
[NumPy]: https://github.com/numpy/numpy
|
||||
[Tornado]: https://github.com/tornadoweb/tornado
|
||||
[Matplotlib]: https://github.com/matplotlib/matplotlib
|
||||
[NCNN]: https://github.com/Tencent/ncnn
|
||||
[Kivy]: https://github.com/kivy/kivy
|
||||
[Prophet]: https://github.com/facebook/prophet
|
||||
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
|
||||
[pydantic]: https://github.com/samuelcolvin/pydantic
|
||||
[Prophet]: https://github.com/facebook/prophet
|
||||
[Kivy]: https://github.com/kivy/kivy
|
||||
[duckdb]: https://github.com/duckdb/duckdb
|
||||
[MemRay]: https://github.com/bloomberg/memray
|
||||
[uvloop]: https://github.com/MagicStack/uvloop
|
||||
[psutil]: https://github.com/giampaolo/psutil
|
||||
[duckdb]: https://github.com/duckdb/duckdb
|
||||
[Triton]: https://github.com/openai/triton
|
||||
[vaex]: https://github.com/vaexio/vaex
|
||||
[Google Benchmark]: https://github.com/google/benchmark
|
||||
[Apache Beam]: https://github.com/apache/beam
|
||||
[asyncpg]: https://github.com/MagicStack/asyncpg
|
||||
[PyGame]: https://github.com/pygame/pygame
|
||||
[Triton]: https://github.com/openai/triton
|
||||
[asyncpg]: https://github.com/MagicStack/asyncpg
|
||||
[cmake]: https://github.com/scikit-build/cmake-python-distributions
|
||||
[scikit-image]: https://github.com/scikit-image/scikit-image
|
||||
[twisted-iocpsupport]: https://github.com/twisted/twisted-iocpsupport
|
||||
[PyOxidizer]: https://github.com/indygreg/PyOxidizer
|
||||
[websockets]: https://github.com/aaugustin/websockets
|
||||
[cvxpy]: https://github.com/cvxpy/cvxpy
|
||||
[websockets]: https://github.com/aaugustin/websockets
|
||||
[River]: https://github.com/online-ml/river
|
||||
[UltraJSON]: https://github.com/ultrajson/ultrajson
|
||||
[OpenSpiel]: https://github.com/deepmind/open_spiel
|
||||
[pyzmq]: https://github.com/zeromq/pyzmq
|
||||
[aiortc]: https://github.com/aiortc/aiortc
|
||||
[pyzmq]: https://github.com/zeromq/pyzmq
|
||||
[Confluent client for Kafka]: https://github.com/confluentinc/confluent-kafka-python
|
||||
[Implicit]: https://github.com/benfred/implicit
|
||||
[Dependency Injector]: https://github.com/ets-labs/python-dependency-injector
|
||||
[vispy]: https://github.com/vispy/vispy
|
||||
[tinyobjloader]: https://github.com/tinyobjloader/tinyobjloader
|
||||
[Dependency Injector]: https://github.com/ets-labs/python-dependency-injector
|
||||
[coverage.py]: https://github.com/nedbat/coveragepy
|
||||
[PyCryptodome]: https://github.com/Legrandin/pycryptodome
|
||||
[PyYAML]: https://github.com/yaml/pyyaml
|
||||
[numexpr]: https://github.com/pydata/numexpr
|
||||
[h5py]: https://github.com/h5py/h5py
|
||||
[Wrapt]: https://github.com/GrahamDumpleton/wrapt
|
||||
[PyAV]: https://github.com/PyAV-Org/PyAV
|
||||
[Line Profiler]: https://github.com/pyutils/line_profiler
|
||||
[numexpr]: https://github.com/pydata/numexpr
|
||||
[PyAV]: https://github.com/PyAV-Org/PyAV
|
||||
[h5py]: https://github.com/h5py/h5py
|
||||
[CTranslate2]: https://github.com/OpenNMT/CTranslate2
|
||||
[Wrapt]: https://github.com/GrahamDumpleton/wrapt
|
||||
[pikepdf]: https://github.com/pikepdf/pikepdf
|
||||
[SimpleJSON]: https://github.com/simplejson/simplejson
|
||||
[envd]: https://github.com/tensorchord/envd
|
||||
[OpenColorIO]: https://github.com/AcademySoftwareFoundation/OpenColorIO
|
||||
[SimpleJSON]: https://github.com/simplejson/simplejson
|
||||
[aioquic]: https://github.com/aiortc/aioquic
|
||||
[ruptures]: https://github.com/deepcharles/ruptures
|
||||
[OpenTimelineIO]: https://github.com/PixarAnimationStudios/OpenTimelineIO
|
||||
[PyTables]: https://github.com/PyTables/PyTables
|
||||
[ruptures]: https://github.com/deepcharles/ruptures
|
||||
[Psycopg 3]: https://github.com/psycopg/psycopg
|
||||
[Parselmouth]: https://github.com/YannickJadoul/Parselmouth
|
||||
[DeepForest]: https://github.com/LAMDA-NJU/Deep-Forest
|
||||
[google neuroglancer]: https://github.com/google/neuroglancer
|
||||
[AutoPy]: https://github.com/autopilot-rs/autopy
|
||||
[H3-py]: https://github.com/uber/h3-py
|
||||
[mosec]: https://github.com/mosecorg/mosec
|
||||
[Rtree]: https://github.com/Toblerity/rtree
|
||||
[markupsafe]: https://github.com/pallets/markupsafe
|
||||
[CTranslate2]: https://github.com/OpenNMT/CTranslate2
|
||||
[Picologging]: https://github.com/microsoft/picologging
|
||||
[markupsafe]: https://github.com/pallets/markupsafe
|
||||
[pybind11 cmake_example]: https://github.com/pybind/cmake_example
|
||||
[time-machine]: https://github.com/adamchainz/time-machine
|
||||
[KDEpy]: https://github.com/tommyod/KDEpy
|
||||
[python-rapidjson]: https://github.com/python-rapidjson/python-rapidjson
|
||||
[python-snappy]: https://github.com/andrix/python-snappy
|
||||
[KDEpy]: https://github.com/tommyod/KDEpy
|
||||
[time-machine]: https://github.com/adamchainz/time-machine
|
||||
[tgcalls]: https://github.com/MarshalX/tgcalls
|
||||
[pybind11 python_example]: https://github.com/pybind/python_example
|
||||
[dd-trace-py]: https://github.com/DataDog/dd-trace-py
|
||||
[pybind11 python_example]: https://github.com/pybind/python_example
|
||||
[sourmash]: https://github.com/dib-lab/sourmash
|
||||
[cyvcf2]: https://github.com/brentp/cyvcf2
|
||||
[matrixprofile]: https://github.com/matrix-profile-foundation/matrixprofile
|
||||
[abess]: https://github.com/abess-team/abess
|
||||
[jq.py]: https://github.com/mwilliamson/jq.py
|
||||
[mosec]: https://github.com/mosecorg/mosec
|
||||
[iminuit]: https://github.com/scikit-hep/iminuit
|
||||
[Tokenizer]: https://github.com/OpenNMT/Tokenizer
|
||||
[PyGLM]: https://github.com/Zuzu-Typ/PyGLM
|
||||
[TgCrypto]: https://github.com/pyrogram/tgcrypto
|
||||
[bx-python]: https://github.com/bxlab/bx-python
|
||||
[boost-histogram]: https://github.com/scikit-hep/boost-histogram
|
||||
[iDynTree]: https://github.com/robotology/idyntree
|
||||
[boost-histogram]: https://github.com/scikit-hep/boost-histogram
|
||||
[pillow-heif]: https://github.com/bigcat88/pillow_heif
|
||||
[Python-WebRTC]: https://github.com/MarshalX/python-webrtc
|
||||
[pybase64]: https://github.com/mayeut/pybase64
|
||||
[Arbor]: https://github.com/arbor-sim/arbor
|
||||
[pillow-heif]: https://github.com/bigcat88/pillow_heif
|
||||
[fathon]: https://github.com/stfbnc/fathon
|
||||
[power-grid-model]: https://github.com/alliander-opensource/power-grid-model
|
||||
[Imagecodecs (fork)]: https://github.com/czaki/imagecodecs_build
|
||||
[polaroid]: https://github.com/daggy1234/polaroid
|
||||
[power-grid-model]: https://github.com/alliander-opensource/power-grid-model
|
||||
[pybind11 scikit_build_example]: https://github.com/pybind/scikit_build_example
|
||||
[etebase-py]: https://github.com/etesync/etebase-py
|
||||
[cf-units]: https://github.com/SciTools/cf-units
|
||||
[clang-format]: https://github.com/ssciwr/clang-format-wheel
|
||||
[pybind11 scikit_build_example]: https://github.com/pybind/scikit_build_example
|
||||
[numpythia]: https://github.com/scikit-hep/numpythia
|
||||
[ninja]: https://github.com/scikit-build/ninja-python-distributions
|
||||
[numpythia]: https://github.com/scikit-hep/numpythia
|
||||
[pyjet]: https://github.com/scikit-hep/pyjet
|
||||
[GSD]: https://github.com/glotzerlab/gsd
|
||||
[ril]: https://github.com/Cryptex-github/ril-py
|
||||
[GSD]: https://github.com/glotzerlab/gsd
|
||||
[SiPM]: https://github.com/EdoPro98/SimSiPM
|
||||
[CorrectionLib]: https://github.com/cms-nanoAOD/correctionlib
|
||||
[pyinstrument_cext]: https://github.com/joerick/pyinstrument_cext
|
||||
[xmlstarlet]: https://github.com/dimitern/xmlstarlet
|
||||
[aalink]: https://github.com/artfwo/aalink
|
||||
[pybind11 cross build example]: https://github.com/wbarnha/pybind_cmake_example_crossbuild
|
||||
|
||||
[appveyor icon]: data/readme_icons/appveyor.svg
|
||||
|
||||
@@ -12,7 +12,7 @@ stack: python 3.7
|
||||
init:
|
||||
- cmd: set PATH=C:\Python37;C:\Python37\Scripts;%PATH%
|
||||
|
||||
install: python -m pip install cibuildwheel==2.12.1
|
||||
install: python -m pip install cibuildwheel==2.16.1
|
||||
|
||||
build_script: python -m cibuildwheel --output-dir wheelhouse
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ jobs:
|
||||
- bash: |
|
||||
set -o errexit
|
||||
python3 -m pip install --upgrade pip
|
||||
pip3 install cibuildwheel==2.12.1
|
||||
pip3 install cibuildwheel==2.16.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==2.12.1
|
||||
python3 -m pip install cibuildwheel==2.16.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==2.12.1
|
||||
pip install cibuildwheel==2.16.1
|
||||
displayName: Install dependencies
|
||||
- bash: cibuildwheel --output-dir wheelhouse .
|
||||
displayName: Build wheels
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
- run:
|
||||
name: Build the Linux wheels.
|
||||
command: |
|
||||
pip3 install --user cibuildwheel==2.12.1
|
||||
pip3 install --user cibuildwheel==2.16.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==2.12.1
|
||||
python3 -m pip install --user cibuildwheel==2.16.1
|
||||
python3 -m cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
- run:
|
||||
name: Build the OS X wheels.
|
||||
command: |
|
||||
pip3 install cibuildwheel==2.12.1
|
||||
pip3 install cibuildwheel==2.16.1
|
||||
cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
||||
install_cibuildwheel_script:
|
||||
- python -m pip install cibuildwheel==2.12.1
|
||||
- python -m pip install cibuildwheel==2.16.1
|
||||
run_cibuildwheel_script:
|
||||
- cibuildwheel
|
||||
wheels_artifacts:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
||||
install_cibuildwheel_script:
|
||||
- python -m pip install cibuildwheel==2.12.1
|
||||
- python -m pip install cibuildwheel==2.16.1
|
||||
run_cibuildwheel_script:
|
||||
- cibuildwheel
|
||||
wheels_artifacts:
|
||||
|
||||
@@ -7,10 +7,10 @@ jobs:
|
||||
name: Build wheels on macos-11
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.12.1
|
||||
uses: pypa/cibuildwheel@v2.16.1
|
||||
env:
|
||||
CIBW_ARCHS_MACOS: x86_64 arm64
|
||||
|
||||
|
||||
+21
-21
@@ -1,14 +1,14 @@
|
||||
name: Build and upload to PyPI
|
||||
|
||||
# Build on every branch push, tag push, and pull request change:
|
||||
on: [push, pull_request]
|
||||
# Alternatively, to publish when a (published) GitHub Release is created, use the following:
|
||||
# on:
|
||||
# push:
|
||||
# pull_request:
|
||||
# release:
|
||||
# types:
|
||||
# - published
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build_wheels:
|
||||
@@ -16,13 +16,13 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, windows-2019, macos-11]
|
||||
os: [ubuntu-22.04, windows-2022, macos-11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.12.1
|
||||
uses: pypa/cibuildwheel@v2.16.1
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
name: Build source distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build sdist
|
||||
run: pipx run build --sdist
|
||||
@@ -44,10 +44,12 @@ jobs:
|
||||
upload_pypi:
|
||||
needs: [build_wheels, build_sdist]
|
||||
runs-on: ubuntu-latest
|
||||
# upload to PyPI on every tag starting with 'v'
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||
# alternatively, to publish when a GitHub Release is created, use the following rule:
|
||||
# if: github.event_name == 'release' && github.event.action == 'published'
|
||||
environment: pypi
|
||||
permissions:
|
||||
id-token: write
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
# or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this)
|
||||
# if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
@@ -56,8 +58,6 @@ jobs:
|
||||
name: artifact
|
||||
path: dist
|
||||
|
||||
- uses: pypa/gh-action-pypi-publish@v1.5.0
|
||||
- uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_password }}
|
||||
# To test: repository_url: https://test.pypi.org/legacy/
|
||||
# To test: repository-url: https://test.pypi.org/legacy/
|
||||
|
||||
@@ -11,10 +11,10 @@ jobs:
|
||||
os: [ubuntu-20.04, windows-2019, macos-11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.12.1
|
||||
uses: pypa/cibuildwheel@v2.16.1
|
||||
# env:
|
||||
# CIBW_SOME_OPTION: value
|
||||
# ...
|
||||
|
||||
@@ -11,16 +11,16 @@ jobs:
|
||||
os: [ubuntu-20.04, windows-2019, macos-11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
if: runner.os == 'Linux'
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.12.1
|
||||
uses: pypa/cibuildwheel@v2.16.1
|
||||
env:
|
||||
# configure cibuildwheel to build native archs ('auto'), and some
|
||||
# emulated ones
|
||||
|
||||
@@ -12,7 +12,7 @@ linux:
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
script:
|
||||
- curl -sSL https://get.docker.com/ | sh
|
||||
- python -m pip install cibuildwheel==2.12.1
|
||||
- python -m pip install cibuildwheel==2.16.1
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
artifacts:
|
||||
paths:
|
||||
@@ -23,7 +23,7 @@ windows:
|
||||
before_script:
|
||||
- choco install python -y --version 3.8.6
|
||||
- choco install git.install -y
|
||||
- py -m pip install cibuildwheel==2.12.1
|
||||
- py -m pip install cibuildwheel==2.16.1
|
||||
script:
|
||||
- py -m cibuildwheel --output-dir wheelhouse --platform windows
|
||||
artifacts:
|
||||
|
||||
@@ -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==2.12.1
|
||||
- python -m pip install cibuildwheel==2.16.1
|
||||
# Assuming your CI runner's default architecture is x86_64...
|
||||
- cibuildwheel --output-dir wheelhouse --platform linux --archs aarch64
|
||||
artifacts:
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
|
||||
|
||||
install:
|
||||
- python3 -m pip install cibuildwheel==2.12.1
|
||||
- python3 -m pip install cibuildwheel==2.16.1
|
||||
|
||||
script:
|
||||
# build the wheels, put them into './dist'
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
|
||||
|
||||
install:
|
||||
- python3 -m pip install cibuildwheel==2.12.1
|
||||
- python3 -m pip install cibuildwheel==2.16.1
|
||||
|
||||
script:
|
||||
# build the wheels, put them into './wheelhouse'
|
||||
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
- stage: deploy
|
||||
name: Build and deploy Linux wheels
|
||||
services: docker
|
||||
install: python3 -m pip install cibuildwheel==2.12.1 twine
|
||||
install: python3 -m pip install cibuildwheel==2.16.1 twine
|
||||
script: python3 -m cibuildwheel --output-dir wheelhouse
|
||||
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
||||
# Deploy on windows
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
name: Build and deploy Windows wheels
|
||||
os: windows
|
||||
language: shell
|
||||
install: python3 -m pip install cibuildwheel==2.12.1 twine
|
||||
install: python3 -m pip install cibuildwheel==2.16.1 twine
|
||||
script: python3 -m cibuildwheel --output-dir wheelhouse
|
||||
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import nox
|
||||
|
||||
nox.options.sessions = ["lint", "pylint", "check_manifest", "tests"]
|
||||
|
||||
PYTHON_ALL_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||
PYTHON_ALL_VERSIONS = ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||
|
||||
DIR = Path(__file__).parent.resolve()
|
||||
|
||||
|
||||
+45
-30
@@ -7,24 +7,20 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
target-version = ['py37', 'py38', 'py39', 'py310']
|
||||
target-version = ['py38', 'py39', 'py310', 'py311']
|
||||
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
minversion = "6.0"
|
||||
addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"]
|
||||
junit_family = "xunit2"
|
||||
testpaths = [
|
||||
"test",
|
||||
"unit_test",
|
||||
]
|
||||
xfail_strict = true
|
||||
filterwarnings = ["error"]
|
||||
log_cli_level = "info"
|
||||
|
||||
|
||||
[tool.mypy]
|
||||
python_version = 3.7
|
||||
python_version = 3.8
|
||||
files = [
|
||||
"cibuildwheel/*.py",
|
||||
"test/**/*.py",
|
||||
@@ -83,10 +79,10 @@ ignore = [
|
||||
]
|
||||
|
||||
[tool.pylint]
|
||||
master.py-version = "3.7"
|
||||
master.jobs = "0"
|
||||
master.fail-on = ["E", "F"]
|
||||
master.fail-under = "9.8"
|
||||
py-version = "3.8"
|
||||
jobs = "0"
|
||||
fail-on = ["E", "F"]
|
||||
fail-under = "9.8"
|
||||
reports.output-format = "colorized"
|
||||
messages_control.enable = [
|
||||
"useless-suppression",
|
||||
@@ -120,30 +116,49 @@ messages_control.disable = [
|
||||
|
||||
[tool.ruff]
|
||||
select = [
|
||||
"E", "F", "W", # flake8
|
||||
"B", "B904", # flake8-bugbear
|
||||
"I", # isort
|
||||
"ARG", # flake8-unused-arguments
|
||||
"C4", # flake8-comprehensions
|
||||
"EM", # flake8-errmsg
|
||||
"ICN", # flake8-import-conventions
|
||||
"ISC", # flake8-implicit-str-concat
|
||||
"PGH", # pygrep-hooks
|
||||
"PIE", # flake8-pie
|
||||
"PLC", "PLE", "PLW", # pylint
|
||||
"PT", # flake8-pytest-style
|
||||
"RET", # flake8-return
|
||||
"RUF", # Ruff-specific
|
||||
"SIM", # flake8-simplify
|
||||
"UP", # pyupgrade
|
||||
"YTT", # flake8-2020
|
||||
"E", "F", "W", # flake8
|
||||
"B", # flake8-bugbear
|
||||
"I", # isort
|
||||
"ARG", # flake8-unused-arguments
|
||||
"C4", # flake8-comprehensions
|
||||
"EM", # flake8-errmsg
|
||||
"ICN", # flake8-import-conventions
|
||||
"ISC", # flake8-implicit-str-concat
|
||||
"G", # flake8-logging-format
|
||||
"PGH", # pygrep-hooks
|
||||
"PIE", # flake8-pie
|
||||
"PL", # pylint
|
||||
"PT", # flake8-pytest-style
|
||||
"RET", # flake8-return
|
||||
"RUF", # Ruff-specific
|
||||
"SIM", # flake8-simplify
|
||||
"TID251", # flake8-tidy-imports.banned-api
|
||||
"UP", # pyupgrade
|
||||
"YTT", # flake8-2020
|
||||
"EXE", # flake8-executable
|
||||
]
|
||||
extend-ignore = [
|
||||
"PLR2004", "E501",
|
||||
"PLR", # Design related pylint codes
|
||||
"E501", # Line too long
|
||||
"RET504", "RET505", "RET508", # else after control flow
|
||||
"PT004", # Rename suggested for returnless fixtures
|
||||
"PT007", # False positive (fixed upstream)
|
||||
]
|
||||
target-version = "py37"
|
||||
typing-modules = ["cibuildwheel.typing"]
|
||||
target-version = "py38"
|
||||
typing-modules = ["cibuildwheel._compat.typing"]
|
||||
flake8-unused-arguments.ignore-variadic-names = true
|
||||
|
||||
[tool.ruff.flake8-tidy-imports.banned-api]
|
||||
"typing.Mapping".msg = "Use collections.abc.Mapping instead."
|
||||
"typing.Callable".msg = "Use collections.abc.Callable instead."
|
||||
"typing.Iterator".msg = "Use collections.abc.Iterator instead."
|
||||
"typing.Sequence".msg = "Use collections.abc.Sequence instead."
|
||||
"typing.Set".msg = "Use collections.abc.Set instead."
|
||||
"typing.NotRequired".msg = "Use cibuildwheel._compat.typing.NotRequired instead."
|
||||
"typing.assert_never".msg = "Use cibuildwheel._compat.typing.assert_never instead."
|
||||
"tomllib".msg = "Use cibuildwheel._compat.tomllib instead."
|
||||
"tomli".msg = "Use cibuildwheel._compat.tomllib instead."
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
"unit_test/*" = ["PLC1901"]
|
||||
"cibuildwheel/_compat/**.py" = ["TID251"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = cibuildwheel
|
||||
version = 2.12.1
|
||||
version = 2.16.1
|
||||
description = Build Python wheels on CI with minimal configuration.
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
@@ -8,7 +8,7 @@ url = https://github.com/pypa/cibuildwheel
|
||||
author = Joe Rickerby
|
||||
author_email = joerick@mac.com
|
||||
license = BSD-2-Clause
|
||||
license_file = LICENSE
|
||||
license_files = LICENSE
|
||||
classifiers =
|
||||
Development Status :: 5 - Production/Stable
|
||||
Intended Audience :: Developers
|
||||
@@ -16,7 +16,6 @@ classifiers =
|
||||
Natural Language :: English
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3 :: Only
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
Programming Language :: Python :: 3.10
|
||||
@@ -39,7 +38,7 @@ install_requires =
|
||||
platformdirs
|
||||
tomli;python_version < '3.11'
|
||||
typing-extensions>=4.1.0;python_version < '3.11'
|
||||
python_requires = >=3.7
|
||||
python_requires = >=3.8
|
||||
include_package_data = True
|
||||
zip_safe = False
|
||||
|
||||
|
||||
@@ -27,20 +27,9 @@ extras = {
|
||||
"rich>=9.6",
|
||||
"packaging>=21.0",
|
||||
],
|
||||
"mypy": [
|
||||
"mypy>=0.901",
|
||||
"types-jinja2",
|
||||
"types-certifi",
|
||||
"types-toml",
|
||||
"types-jinja2",
|
||||
"types-pyyaml",
|
||||
"types-click",
|
||||
"types-requests",
|
||||
],
|
||||
}
|
||||
|
||||
extras["dev"] = [
|
||||
*extras["mypy"],
|
||||
*extras["test"],
|
||||
*extras["bin"],
|
||||
]
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from typing import Generator
|
||||
|
||||
import pytest
|
||||
|
||||
from cibuildwheel.util import detect_ci_provider
|
||||
|
||||
from .utils import platform
|
||||
|
||||
|
||||
def pytest_addoption(parser) -> None:
|
||||
parser.addoption(
|
||||
@@ -21,3 +29,25 @@ def pytest_addoption(parser) -> None:
|
||||
)
|
||||
def build_frontend_env(request) -> dict[str, str]:
|
||||
return request.param # type: ignore[no-any-return]
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def docker_cleanup() -> Generator[None, None, None]:
|
||||
def get_images() -> set[str]:
|
||||
if detect_ci_provider() is None or platform != "linux":
|
||||
return set()
|
||||
images = subprocess.run(
|
||||
["docker", "image", "ls", "--format", "{{json .ID}}"],
|
||||
text=True,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
).stdout
|
||||
return {json.loads(image.strip()) for image in images.splitlines() if image.strip()}
|
||||
|
||||
images_before = get_images()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
images_after = get_images()
|
||||
for image in images_after - images_before:
|
||||
subprocess.run(["docker", "rmi", image], check=False)
|
||||
|
||||
@@ -47,7 +47,7 @@ def test_abi3(tmp_path):
|
||||
expected_wheels = [
|
||||
w.replace("cp38-cp38", "cp38-abi3")
|
||||
for w in utils.expected_wheels("spam", "0.1.0")
|
||||
if "-pp" not in w and "-cp39" not in w and "-cp310" not in w and "-cp311" not in w
|
||||
if "-pp" not in w and "-cp39" not in w and "-cp31" not in w
|
||||
]
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
|
||||
from . import utils
|
||||
from .test_projects.c import new_c_project
|
||||
|
||||
|
||||
@pytest.mark.parametrize("frontend_name", ["pip", "build"])
|
||||
def test_build_frontend_args(tmp_path, capfd, frontend_name):
|
||||
project = new_c_project()
|
||||
project_dir = tmp_path / "project"
|
||||
project.generate(project_dir)
|
||||
|
||||
# the build will fail because the frontend is called with '-h' - it prints the help message
|
||||
with pytest.raises(subprocess.CalledProcessError):
|
||||
utils.cibuildwheel_run(
|
||||
project_dir,
|
||||
add_env={
|
||||
"CIBW_BUILD": "cp311-*",
|
||||
"CIBW_BUILD_FRONTEND": f"{frontend_name}; args: -h",
|
||||
},
|
||||
)
|
||||
|
||||
captured = capfd.readouterr()
|
||||
print(captured.out)
|
||||
|
||||
# check that the help message was printed
|
||||
if frontend_name == "pip":
|
||||
assert "Usage:" in captured.out
|
||||
assert "Wheel Options:" in captured.out
|
||||
else:
|
||||
assert "usage:" in captured.out
|
||||
assert "A simple, correct Python build frontend." in captured.out
|
||||
@@ -7,7 +7,7 @@ from . import test_projects, utils
|
||||
basic_project = test_projects.new_c_project()
|
||||
|
||||
|
||||
def test(tmp_path, capfd, request):
|
||||
def test_podman(tmp_path, capfd, request):
|
||||
if utils.platform != "linux":
|
||||
pytest.skip("the test is only relevant to the linux build")
|
||||
|
||||
@@ -38,3 +38,29 @@ def test(tmp_path, capfd, request):
|
||||
# check that stdout is bring passed-though from container correctly
|
||||
captured = capfd.readouterr()
|
||||
assert "test log statement from before-all" in captured.out
|
||||
|
||||
|
||||
def test_create_args(tmp_path, capfd):
|
||||
if utils.platform != "linux":
|
||||
pytest.skip("the test is only relevant to the linux build")
|
||||
|
||||
project_dir = tmp_path / "project"
|
||||
basic_project.generate(project_dir)
|
||||
|
||||
# build a manylinux wheel, using create_args to set an environment variable
|
||||
actual_wheels = utils.cibuildwheel_run(
|
||||
project_dir,
|
||||
add_env={
|
||||
"CIBW_BUILD": "cp310-manylinux_*",
|
||||
"CIBW_BEFORE_ALL": "echo TEST_CREATE_ARGS is set to $TEST_CREATE_ARGS",
|
||||
"CIBW_CONTAINER_ENGINE": "docker; create_args: --env=TEST_CREATE_ARGS=itworks",
|
||||
},
|
||||
)
|
||||
|
||||
expected_wheels = [
|
||||
w for w in utils.expected_wheels("spam", "0.1.0") if ("cp310-manylinux" in w)
|
||||
]
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
captured = capfd.readouterr()
|
||||
assert "TEST_CREATE_ARGS is set to itworks" in captured.out
|
||||
@@ -23,6 +23,7 @@ dockcross_only_project = test_projects.new_c_project(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("docker_cleanup")
|
||||
def test(tmp_path):
|
||||
if utils.platform != "linux":
|
||||
pytest.skip("the test is only relevant to the linux build")
|
||||
|
||||
@@ -118,7 +118,7 @@ def test_cpp17(tmp_path):
|
||||
|
||||
# Pypy's distutils sets the default compiler to 'msvc9compiler', which
|
||||
# is too old to support cpp17.
|
||||
add_env = {"CIBW_SKIP": "pp??-*"}
|
||||
add_env = {"CIBW_SKIP": "pp*"}
|
||||
|
||||
if utils.platform == "macos":
|
||||
add_env["MACOSX_DEPLOYMENT_TARGET"] = "10.13"
|
||||
|
||||
@@ -45,9 +45,7 @@ VERSION_REGEX = r"([\w-]+)==([^\s]+)"
|
||||
def get_versions_from_constraint_file(constraint_file):
|
||||
constraint_file_text = constraint_file.read_text(encoding="utf8")
|
||||
|
||||
return {
|
||||
package: version for package, version in re.findall(VERSION_REGEX, constraint_file_text)
|
||||
}
|
||||
return dict(re.findall(VERSION_REGEX, constraint_file_text))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("python_version", ["3.6", "3.8", "3.9"])
|
||||
@@ -122,10 +120,10 @@ def test_dependency_constraints_file(tmp_path, build_frontend_env):
|
||||
project_with_expected_version_checks.generate(project_dir)
|
||||
|
||||
tool_versions = {
|
||||
"pip": "20.0.2",
|
||||
"setuptools": "53.0.0",
|
||||
"wheel": "0.36.2",
|
||||
"virtualenv": "20.11.2",
|
||||
"pip": "23.1.2",
|
||||
"setuptools": "67.7.2",
|
||||
"wheel": "0.38.3",
|
||||
"virtualenv": "20.23.0",
|
||||
}
|
||||
|
||||
constraints_file = tmp_path / "constraints file.txt"
|
||||
@@ -157,11 +155,12 @@ def test_dependency_constraints_file(tmp_path, build_frontend_env):
|
||||
add_env={
|
||||
"CIBW_ENVIRONMENT": cibw_environment_option,
|
||||
"CIBW_DEPENDENCY_VERSIONS": str(constraints_file),
|
||||
"CIBW_SKIP": "cp36-*",
|
||||
**build_frontend_env,
|
||||
},
|
||||
)
|
||||
|
||||
# also check that we got the right wheels
|
||||
expected_wheels = utils.expected_wheels("spam", "0.1.0")
|
||||
expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0") if "-cp36" not in w]
|
||||
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
@@ -53,6 +53,7 @@ project_with_manylinux_symbols = test_projects.new_c_project(
|
||||
"manylinux_image",
|
||||
["manylinux1", "manylinux2010", "manylinux2014", "manylinux_2_24", "manylinux_2_28"],
|
||||
)
|
||||
@pytest.mark.usefixtures("docker_cleanup")
|
||||
def test(manylinux_image, tmp_path):
|
||||
if utils.platform != "linux":
|
||||
pytest.skip("the container image test is only relevant to the linux build")
|
||||
@@ -84,8 +85,11 @@ def test(manylinux_image, tmp_path):
|
||||
# We don't have a manylinux1 image for PyPy & CPython 3.10 and above
|
||||
add_env["CIBW_SKIP"] = "pp* cp31*"
|
||||
if manylinux_image in {"manylinux2010"}:
|
||||
# We don't have a manylinux2010 image for PyPy 3.9, CPython 3.11
|
||||
add_env["CIBW_SKIP"] = "pp39* cp311*"
|
||||
# We don't have a manylinux2010 image for PyPy 3.9+, CPython 3.11+
|
||||
add_env["CIBW_SKIP"] = "pp39* pp31* cp311* cp312*"
|
||||
if manylinux_image in {"manylinux_2_24"}:
|
||||
# We don't have a manylinux_2_24 image for PyPy 3.10+, CPython 3.12+
|
||||
add_env["CIBW_SKIP"] = "pp31* cp312*"
|
||||
if manylinux_image == "manylinux_2_28" and platform.machine() == "x86_64":
|
||||
# We don't have a manylinux_2_28 image for i686
|
||||
add_env["CIBW_ARCHS"] = "x86_64"
|
||||
@@ -108,8 +112,16 @@ def test(manylinux_image, tmp_path):
|
||||
expected_wheels = [w for w in expected_wheels if "-pp" not in w and "-cp31" not in w]
|
||||
|
||||
if manylinux_image in {"manylinux2010"}:
|
||||
# remove PyPy 3.9 & CPython 3.11
|
||||
expected_wheels = [w for w in expected_wheels if "-pp39" not in w and "-cp311" not in w]
|
||||
# remove PyPy 3.9+ & CPython 3.11
|
||||
expected_wheels = [
|
||||
w
|
||||
for w in expected_wheels
|
||||
if "-pp39" not in w and "-pp31" not in w and "-cp311" not in w and "-cp312" not in w
|
||||
]
|
||||
|
||||
if manylinux_image in {"manylinux_2_24"}:
|
||||
# remove PyPy 3.10+ & CPython 3.11 and above
|
||||
expected_wheels = [w for w in expected_wheels if "-pp31" not in w and "-cp312" not in w]
|
||||
|
||||
if manylinux_image == "manylinux_2_28" and platform.machine() == "x86_64":
|
||||
# We don't have a manylinux_2_28 image for i686
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
|
||||
from . import test_projects, utils
|
||||
|
||||
project_with_manylinux_symbols = test_projects.new_c_project(
|
||||
spam_c_top_level_add=textwrap.dedent(
|
||||
r"""
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__GLIBC_PREREQ)
|
||||
#error "Must not run on a glibc linux environment"
|
||||
#endif
|
||||
"""
|
||||
),
|
||||
spam_c_function_add=textwrap.dedent(
|
||||
r"""
|
||||
sts = 0;
|
||||
"""
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"musllinux_image",
|
||||
["musllinux_1_1", "musllinux_1_2"],
|
||||
)
|
||||
@pytest.mark.usefixtures("docker_cleanup")
|
||||
def test(musllinux_image, tmp_path):
|
||||
if utils.platform != "linux":
|
||||
pytest.skip("the container image test is only relevant to the linux build")
|
||||
|
||||
project_dir = tmp_path / "project"
|
||||
project_with_manylinux_symbols.generate(project_dir)
|
||||
|
||||
# build the wheels
|
||||
add_env = {
|
||||
"CIBW_BUILD": "*-musllinux*",
|
||||
"CIBW_MUSLLINUX_X86_64_IMAGE": musllinux_image,
|
||||
"CIBW_MUSLLINUX_I686_IMAGE": musllinux_image,
|
||||
"CIBW_MUSLLINUX_AARCH64_IMAGE": musllinux_image,
|
||||
"CIBW_MUSLLINUX_PPC64LE_IMAGE": musllinux_image,
|
||||
"CIBW_MUSLLINUX_S390X_IMAGE": musllinux_image,
|
||||
}
|
||||
|
||||
actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env)
|
||||
expected_wheels = utils.expected_wheels(
|
||||
"spam",
|
||||
"0.1.0",
|
||||
manylinux_versions=[],
|
||||
musllinux_versions=[musllinux_image],
|
||||
)
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
+2
-2
@@ -9,7 +9,7 @@ basic_project = test_projects.new_c_project(
|
||||
"""
|
||||
# Will fail if PEP 518 does work
|
||||
import requests
|
||||
assert requests.__version__ == "2.23.0", "Requests found but wrong version ({0})".format(requests.__version__)
|
||||
assert requests.__version__ == "2.27.0", "Requests found but wrong version ({0})".format(requests.__version__)
|
||||
|
||||
# Just making sure environment is still set
|
||||
import os
|
||||
@@ -27,7 +27,7 @@ requires = [
|
||||
"setuptools >= 42",
|
||||
"setuptools_scm[toml]>=4.1.2",
|
||||
"wheel",
|
||||
"requests==2.23.0"
|
||||
"requests==2.27.0"
|
||||
]
|
||||
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
@@ -12,9 +12,9 @@ basic_project = test_projects.new_c_project()
|
||||
|
||||
|
||||
def skip_if_no_msvc(arm64=False):
|
||||
programfiles = os.getenv("ProgramFiles(x86)", "") or os.getenv("ProgramFiles", "")
|
||||
programfiles = os.getenv("PROGRAMFILES(X86)", "") or os.getenv("PROGRAMFILES", "")
|
||||
if not programfiles:
|
||||
pytest.skip("Requires %ProgramFiles(x86)% variable to be set")
|
||||
pytest.skip("Requires %PROGRAMFILES(X86)% variable to be set")
|
||||
|
||||
vswhere = os.path.join(programfiles, "Microsoft Visual Studio", "Installer", "vswhere.exe")
|
||||
if not os.path.isfile(vswhere):
|
||||
|
||||
+29
-9
@@ -170,10 +170,16 @@ def expected_wheels(
|
||||
"cp39-cp39",
|
||||
"cp310-cp310",
|
||||
"cp311-cp311",
|
||||
"cp312-cp312",
|
||||
]
|
||||
|
||||
if machine_arch in ["x86_64", "AMD64", "x86", "aarch64"]:
|
||||
python_abi_tags += ["pp37-pypy37_pp73", "pp38-pypy38_pp73", "pp39-pypy39_pp73"]
|
||||
python_abi_tags += [
|
||||
"pp37-pypy37_pp73",
|
||||
"pp38-pypy38_pp73",
|
||||
"pp39-pypy39_pp73",
|
||||
"pp310-pypy310_pp73",
|
||||
]
|
||||
|
||||
if platform == "macos" and machine_arch == "arm64":
|
||||
# arm64 macs are only supported by cp38+
|
||||
@@ -182,8 +188,10 @@ def expected_wheels(
|
||||
"cp39-cp39",
|
||||
"cp310-cp310",
|
||||
"cp311-cp311",
|
||||
"cp312-cp312",
|
||||
"pp38-pypy38_pp73",
|
||||
"pp39-pypy39_pp73",
|
||||
"pp310-pypy310_pp73",
|
||||
]
|
||||
|
||||
wheels = []
|
||||
@@ -192,18 +200,19 @@ def expected_wheels(
|
||||
platform_tags = []
|
||||
|
||||
if platform == "linux":
|
||||
architectures = [machine_arch]
|
||||
architectures = [arch_name_for_linux(machine_arch)]
|
||||
|
||||
if machine_arch == "x86_64":
|
||||
architectures.append("i686")
|
||||
|
||||
platform_tags = [
|
||||
".".join(
|
||||
f"{manylinux_version}_{architecture}"
|
||||
for manylinux_version in manylinux_versions
|
||||
)
|
||||
for architecture in architectures
|
||||
]
|
||||
if len(manylinux_versions) > 0:
|
||||
platform_tags = [
|
||||
".".join(
|
||||
f"{manylinux_version}_{architecture}"
|
||||
for manylinux_version in manylinux_versions
|
||||
)
|
||||
for architecture in architectures
|
||||
]
|
||||
if len(musllinux_versions) > 0 and not python_abi_tag.startswith("pp"):
|
||||
platform_tags.extend(
|
||||
[
|
||||
@@ -255,3 +264,14 @@ def get_macos_version():
|
||||
"""
|
||||
version_str, _, _ = pm.mac_ver()
|
||||
return tuple(map(int, version_str.split(".")[:2]))
|
||||
|
||||
|
||||
def arch_name_for_linux(arch: str):
|
||||
"""
|
||||
Archs have different names on different platforms, but it's useful to be
|
||||
able to run linux tests on dev machines. This function translates between
|
||||
the different names.
|
||||
"""
|
||||
if arch == "arm64":
|
||||
return "aarch64"
|
||||
return arch
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
|
||||
from packaging.version import Version
|
||||
|
||||
from cibuildwheel._compat import tomllib
|
||||
from cibuildwheel.extra import Printable, dump_python_configurations
|
||||
from cibuildwheel.util import resources_dir
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ def test_build():
|
||||
assert build_selector("cp37-manylinux_x86_64")
|
||||
assert build_selector("cp310-manylinux_x86_64")
|
||||
assert build_selector("cp311-manylinux_x86_64")
|
||||
assert build_selector("cp312-manylinux_x86_64")
|
||||
assert build_selector("pp36-manylinux_x86_64")
|
||||
assert build_selector("pp37-manylinux_x86_64")
|
||||
assert build_selector("cp36-manylinux_i686")
|
||||
@@ -31,6 +32,7 @@ def test_build():
|
||||
assert build_selector("cp37-win_amd64")
|
||||
assert build_selector("cp310-win_amd64")
|
||||
assert build_selector("cp311-win_amd64")
|
||||
assert build_selector("cp312-win_amd64")
|
||||
assert not build_selector("pp36-win_amd64")
|
||||
assert not build_selector("pp37-win_amd64")
|
||||
|
||||
@@ -43,9 +45,9 @@ def test_build_filter_pre():
|
||||
)
|
||||
|
||||
assert build_selector("cp37-manylinux_x86_64")
|
||||
assert build_selector("cp311-manylinux_x86_64")
|
||||
assert build_selector("cp312-manylinux_x86_64")
|
||||
assert build_selector("cp37-win_amd64")
|
||||
assert build_selector("cp311-win_amd64")
|
||||
assert build_selector("cp312-win_amd64")
|
||||
|
||||
|
||||
def test_skip():
|
||||
|
||||
@@ -62,8 +62,9 @@ def test_linux_container_split(tmp_path: Path, monkeypatch):
|
||||
"cp36-manylinux_x86_64",
|
||||
"cp37-manylinux_x86_64",
|
||||
"cp311-manylinux_x86_64",
|
||||
"cp312-manylinux_x86_64",
|
||||
]
|
||||
assert before_alls(build_steps[0]) == ["", "", ""]
|
||||
assert before_alls(build_steps[0]) == ["", "", "", ""]
|
||||
|
||||
assert build_steps[1].container_image == "other_container_image"
|
||||
assert identifiers(build_steps[1]) == ["cp38-manylinux_x86_64", "cp310-manylinux_x86_64"]
|
||||
|
||||
@@ -6,12 +6,8 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
import tomllib
|
||||
else:
|
||||
import tomli as tomllib
|
||||
|
||||
from cibuildwheel.__main__ import main
|
||||
from cibuildwheel._compat import tomllib
|
||||
from cibuildwheel.environment import ParsedEnvironment
|
||||
from cibuildwheel.options import BuildOptions, _get_pinned_container_images
|
||||
from cibuildwheel.util import BuildSelector, resources_dir, split_config_settings
|
||||
@@ -369,7 +365,7 @@ def test_defaults(platform, intercepted_build_args):
|
||||
if isinstance(repair_wheel_default, list):
|
||||
repair_wheel_default = " && ".join(repair_wheel_default)
|
||||
assert build_options.repair_command == repair_wheel_default
|
||||
assert build_options.build_frontend == defaults["build-frontend"]
|
||||
assert build_options.build_frontend is None
|
||||
|
||||
if platform == "linux":
|
||||
assert build_options.manylinux_images
|
||||
|
||||
@@ -214,6 +214,7 @@ def test_only_argument(intercepted_build_args, monkeypatch, only, plat):
|
||||
assert options.globals.build_selector.skip_config == ""
|
||||
assert options.platform == plat
|
||||
assert options.globals.architectures == Architecture.all_archs(plat)
|
||||
assert options.globals.build_selector.prerelease_pythons is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize("only", ("cp311-manylxinux_x86_64", "some_linux_thing"))
|
||||
|
||||
+137
-18
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import random
|
||||
@@ -12,32 +13,50 @@ import pytest
|
||||
import tomli_w
|
||||
|
||||
from cibuildwheel.environment import EnvironmentAssignmentBash
|
||||
from cibuildwheel.oci_container import OCIContainer
|
||||
from cibuildwheel.oci_container import OCIContainer, OCIContainerEngineConfig
|
||||
from cibuildwheel.util import detect_ci_provider
|
||||
|
||||
# Test utilities
|
||||
|
||||
# for these tests we use manylinux2014 images, because they're available on
|
||||
# multi architectures and include python3.8
|
||||
DEFAULT_IMAGE_TEMPLATE = "quay.io/pypa/manylinux2014_{machine}:2023-09-04-0828984"
|
||||
pm = platform.machine()
|
||||
if pm == "x86_64":
|
||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_x86_64:2020-05-17-2f8ac3b"
|
||||
elif pm == "aarch64":
|
||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_aarch64:2020-05-17-2f8ac3b"
|
||||
elif pm == "ppc64le":
|
||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_ppc64le:2020-05-17-2f8ac3b"
|
||||
elif pm == "s390x":
|
||||
DEFAULT_IMAGE = "quay.io/pypa/manylinux2014_s390x:2020-05-17-2f8ac3b"
|
||||
if pm in {"x86_64", "ppc64le", "s390x"}:
|
||||
DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine=pm)
|
||||
elif pm in {"aarch64", "arm64"}:
|
||||
DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine="aarch64")
|
||||
else:
|
||||
DEFAULT_IMAGE = ""
|
||||
|
||||
PODMAN = OCIContainerEngineConfig(name="podman")
|
||||
|
||||
@pytest.fixture(params=["docker", "podman"])
|
||||
|
||||
@pytest.fixture(params=["docker", "podman"], scope="module")
|
||||
def container_engine(request):
|
||||
if request.param == "docker" and not request.config.getoption("--run-docker"):
|
||||
pytest.skip("need --run-docker option to run")
|
||||
if request.param == "podman" and not request.config.getoption("--run-podman"):
|
||||
pytest.skip("need --run-podman option to run")
|
||||
return request.param
|
||||
|
||||
def get_images() -> set[str]:
|
||||
if detect_ci_provider() is None:
|
||||
return set()
|
||||
images = subprocess.run(
|
||||
[request.param, "image", "ls", "--format", "{{json .ID}}"],
|
||||
text=True,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
).stdout
|
||||
return {json.loads(image.strip()) for image in images.splitlines() if image.strip()}
|
||||
|
||||
images_before = get_images()
|
||||
try:
|
||||
yield OCIContainerEngineConfig(name=request.param)
|
||||
finally:
|
||||
images_after = get_images()
|
||||
for image in images_after - images_before:
|
||||
subprocess.run([request.param, "rmi", image], check=False)
|
||||
|
||||
|
||||
# Tests
|
||||
@@ -70,6 +89,17 @@ def test_environment(container_engine):
|
||||
)
|
||||
|
||||
|
||||
def test_environment_pass(container_engine, monkeypatch):
|
||||
monkeypatch.setenv("CIBUILDWHEEL", "1")
|
||||
monkeypatch.setenv("SOURCE_DATE_EPOCH", "1489957071")
|
||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
||||
assert container.call(["sh", "-c", "echo $CIBUILDWHEEL"], capture_output=True) == "1\n"
|
||||
assert (
|
||||
container.call(["sh", "-c", "echo $SOURCE_DATE_EPOCH"], capture_output=True)
|
||||
== "1489957071\n"
|
||||
)
|
||||
|
||||
|
||||
def test_cwd(container_engine):
|
||||
with OCIContainer(
|
||||
engine=container_engine, image=DEFAULT_IMAGE, cwd="/cibuildwheel/working_directory"
|
||||
@@ -81,7 +111,7 @@ def test_cwd(container_engine):
|
||||
def test_container_removed(container_engine):
|
||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
||||
docker_containers_listing = subprocess.run(
|
||||
f"{container.engine} container ls",
|
||||
f"{container.engine.name} container ls",
|
||||
shell=True,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
@@ -92,7 +122,7 @@ def test_container_removed(container_engine):
|
||||
old_container_name = container.name
|
||||
|
||||
docker_containers_listing = subprocess.run(
|
||||
f"{container.engine} container ls",
|
||||
f"{container.engine.name} container ls",
|
||||
shell=True,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
@@ -219,10 +249,9 @@ def test_environment_executor(container_engine):
|
||||
assert assignment.evaluated_value({}, container.environment_executor) == "42"
|
||||
|
||||
|
||||
def test_podman_vfs(tmp_path: Path, monkeypatch, request):
|
||||
# Tests podman VFS, for the podman in docker use-case
|
||||
if not request.config.getoption("--run-podman"):
|
||||
pytest.skip("need --run-podman option to run")
|
||||
def test_podman_vfs(tmp_path: Path, monkeypatch, container_engine):
|
||||
if container_engine.name != "podman":
|
||||
pytest.skip("only runs with podman")
|
||||
|
||||
# create the VFS configuration
|
||||
vfs_path = tmp_path / "podman_vfs"
|
||||
@@ -280,7 +309,7 @@ def test_podman_vfs(tmp_path: Path, monkeypatch, request):
|
||||
monkeypatch.setenv("CONTAINERS_CONF", str(vfs_containers_conf_fpath))
|
||||
monkeypatch.setenv("CONTAINERS_STORAGE_CONF", str(vfs_containers_storage_conf_fpath))
|
||||
|
||||
with OCIContainer(engine="podman", image=DEFAULT_IMAGE) as container:
|
||||
with OCIContainer(engine=PODMAN, image=DEFAULT_IMAGE) as container:
|
||||
# test running a command
|
||||
assert container.call(["echo", "hello"], capture_output=True) == "hello\n"
|
||||
|
||||
@@ -296,3 +325,93 @@ def test_podman_vfs(tmp_path: Path, monkeypatch, request):
|
||||
# as UID 0. The reason why permission errors occur on podman is documented
|
||||
# in https://podman.io/blogs/2018/10/03/podman-remove-content-homedir.html
|
||||
subprocess.run(["podman", "unshare", "rm", "-rf", vfs_path], check=True)
|
||||
|
||||
|
||||
def test_create_args_volume(tmp_path: Path, container_engine):
|
||||
if container_engine.name != "docker":
|
||||
pytest.skip("only runs with docker")
|
||||
|
||||
if "CIRCLECI" in os.environ or "GITLAB_CI" in os.environ:
|
||||
pytest.skip(
|
||||
"Skipping test on CircleCI/GitLab because docker there does not support --volume"
|
||||
)
|
||||
|
||||
test_mount_dir = tmp_path / "test_mount"
|
||||
test_mount_dir.mkdir()
|
||||
(test_mount_dir / "test_file.txt").write_text("1234")
|
||||
container_engine = OCIContainerEngineConfig(
|
||||
name="docker", create_args=[f"--volume={test_mount_dir}:/test_mount"]
|
||||
)
|
||||
|
||||
with OCIContainer(
|
||||
engine=container_engine,
|
||||
image=DEFAULT_IMAGE,
|
||||
) as container:
|
||||
assert container.call(["cat", "/test_mount/test_file.txt"], capture_output=True) == "1234"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("config", "name", "create_args"),
|
||||
[
|
||||
(
|
||||
"docker",
|
||||
"docker",
|
||||
[],
|
||||
),
|
||||
(
|
||||
"docker;create_args:",
|
||||
"docker",
|
||||
[],
|
||||
),
|
||||
(
|
||||
"docker;create_args:--abc --def",
|
||||
"docker",
|
||||
["--abc", "--def"],
|
||||
),
|
||||
(
|
||||
"docker; create_args: --abc --def",
|
||||
"docker",
|
||||
["--abc", "--def"],
|
||||
),
|
||||
(
|
||||
"name:docker; create_args: --abc --def",
|
||||
"docker",
|
||||
["--abc", "--def"],
|
||||
),
|
||||
(
|
||||
'docker; create_args: --some-option="value with spaces"',
|
||||
"docker",
|
||||
["--some-option=value with spaces"],
|
||||
),
|
||||
(
|
||||
'docker; create_args: --some-option="value; with; semicolons" --another-option',
|
||||
"docker",
|
||||
["--some-option=value; with; semicolons", "--another-option"],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_parse_engine_config(config, name, create_args):
|
||||
engine_config = OCIContainerEngineConfig.from_config_string(config)
|
||||
assert engine_config.name == name
|
||||
assert engine_config.create_args == create_args
|
||||
|
||||
|
||||
@pytest.mark.skipif(pm != "x86_64", reason="Only runs on x86_64")
|
||||
@pytest.mark.parametrize(
|
||||
("image", "shell_args"),
|
||||
[
|
||||
(DEFAULT_IMAGE_TEMPLATE.format(machine="i686"), ["/bin/bash"]),
|
||||
(DEFAULT_IMAGE_TEMPLATE.format(machine="x86_64"), ["linux32", "/bin/bash"]),
|
||||
],
|
||||
)
|
||||
def test_enforce_32_bit(container_engine, image, shell_args):
|
||||
with OCIContainer(engine=container_engine, image=image, enforce_32_bit=True) as container:
|
||||
assert container.call(["uname", "-m"], capture_output=True).strip() == "i686"
|
||||
container_args = subprocess.run(
|
||||
f"{container.engine.name} inspect -f '{{{{json .Args }}}}' {container.name}",
|
||||
shell=True,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True,
|
||||
).stdout
|
||||
assert json.loads(container_args) == shell_args
|
||||
|
||||
@@ -3,9 +3,9 @@ from __future__ import annotations
|
||||
import platform as platform_module
|
||||
import subprocess
|
||||
import sys
|
||||
import typing
|
||||
from contextlib import contextmanager
|
||||
from pathlib import PurePosixPath
|
||||
from typing import cast
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
@@ -13,7 +13,19 @@ import pytest
|
||||
from cibuildwheel import linux, util
|
||||
from cibuildwheel.__main__ import main
|
||||
|
||||
ALL_IDS = {"cp36", "cp37", "cp38", "cp39", "cp310", "cp311", "pp37", "pp38", "pp39"}
|
||||
ALL_IDS = {
|
||||
"cp36",
|
||||
"cp37",
|
||||
"cp38",
|
||||
"cp39",
|
||||
"cp310",
|
||||
"cp311",
|
||||
"cp312",
|
||||
"pp37",
|
||||
"pp38",
|
||||
"pp39",
|
||||
"pp310",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@@ -52,7 +64,7 @@ def test_build_default_launches(monkeypatch):
|
||||
|
||||
main()
|
||||
|
||||
build_in_container = cast(mock.Mock, linux.build_in_container)
|
||||
build_in_container = typing.cast(mock.Mock, linux.build_in_container)
|
||||
|
||||
assert build_in_container.call_count == 4
|
||||
|
||||
@@ -60,7 +72,7 @@ def test_build_default_launches(monkeypatch):
|
||||
kwargs = build_in_container.call_args_list[0][1]
|
||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert not kwargs["container"]["simulate_32_bit"]
|
||||
assert not kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {f"{x}-manylinux_x86_64" for x in ALL_IDS}
|
||||
@@ -68,7 +80,7 @@ def test_build_default_launches(monkeypatch):
|
||||
kwargs = build_in_container.call_args_list[1][1]
|
||||
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert kwargs["container"]["simulate_32_bit"]
|
||||
assert kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
||||
@@ -76,7 +88,7 @@ def test_build_default_launches(monkeypatch):
|
||||
kwargs = build_in_container.call_args_list[2][1]
|
||||
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert not kwargs["container"]["simulate_32_bit"]
|
||||
assert not kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {
|
||||
@@ -86,7 +98,7 @@ def test_build_default_launches(monkeypatch):
|
||||
kwargs = build_in_container.call_args_list[3][1]
|
||||
assert "quay.io/pypa/musllinux_1_1_i686" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert kwargs["container"]["simulate_32_bit"]
|
||||
assert kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
||||
@@ -101,13 +113,15 @@ def test_build_with_override_launches(monkeypatch, tmp_path):
|
||||
cibw_toml.write_text(
|
||||
"""
|
||||
[tool.cibuildwheel]
|
||||
manylinux-x86_64-image = "manylinux_2_24"
|
||||
manylinux-x86_64-image = "manylinux_2_28"
|
||||
musllinux-x86_64-image = "musllinux_1_2"
|
||||
|
||||
# Before Python 3.10, use manylinux2014
|
||||
# Before Python 3.10, use manylinux2014, musllinux_1_1
|
||||
[[tool.cibuildwheel.overrides]]
|
||||
select = "cp3?-*"
|
||||
manylinux-x86_64-image = "manylinux2014"
|
||||
manylinux-i686-image = "manylinux2014"
|
||||
musllinux-x86_64-image = "musllinux_1_1"
|
||||
|
||||
[[tool.cibuildwheel.overrides]]
|
||||
select = "cp36-manylinux_x86_64"
|
||||
@@ -120,14 +134,14 @@ before-all = "true"
|
||||
|
||||
main()
|
||||
|
||||
build_in_container = cast(mock.Mock, linux.build_in_container)
|
||||
build_in_container = typing.cast(mock.Mock, linux.build_in_container)
|
||||
|
||||
assert build_in_container.call_count == 6
|
||||
assert build_in_container.call_count == 7
|
||||
|
||||
kwargs = build_in_container.call_args_list[0][1]
|
||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert not kwargs["container"]["simulate_32_bit"]
|
||||
assert not kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {"cp36-manylinux_x86_64"}
|
||||
@@ -136,28 +150,29 @@ before-all = "true"
|
||||
kwargs = build_in_container.call_args_list[1][1]
|
||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert not kwargs["container"]["simulate_32_bit"]
|
||||
assert not kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {
|
||||
f"{x}-manylinux_x86_64"
|
||||
for x in ALL_IDS - {"cp36", "cp310", "cp311", "pp37", "pp38", "pp39"}
|
||||
for x in ALL_IDS - {"cp36", "cp310", "cp311", "cp312", "pp37", "pp38", "pp39", "pp310"}
|
||||
}
|
||||
assert kwargs["options"].build_options("cp37-manylinux_x86_64").before_all == ""
|
||||
|
||||
kwargs = build_in_container.call_args_list[2][1]
|
||||
assert "quay.io/pypa/manylinux_2_24_x86_64" in kwargs["container"]["image"]
|
||||
assert "quay.io/pypa/manylinux_2_28_x86_64" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert not kwargs["container"]["simulate_32_bit"]
|
||||
assert not kwargs["container"]["enforce_32_bit"]
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {
|
||||
f"{x}-manylinux_x86_64" for x in {"cp310", "cp311", "pp37", "pp38", "pp39"}
|
||||
f"{x}-manylinux_x86_64"
|
||||
for x in ["cp310", "cp311", "cp312", "pp37", "pp38", "pp39", "pp310"]
|
||||
}
|
||||
|
||||
kwargs = build_in_container.call_args_list[3][1]
|
||||
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert kwargs["container"]["simulate_32_bit"]
|
||||
assert kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
||||
@@ -165,17 +180,26 @@ before-all = "true"
|
||||
kwargs = build_in_container.call_args_list[4][1]
|
||||
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert not kwargs["container"]["simulate_32_bit"]
|
||||
assert not kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {
|
||||
f"{x}-musllinux_x86_64" for x in ALL_IDS for x in ALL_IDS if "pp" not in x
|
||||
f"{x}-musllinux_x86_64" for x in ALL_IDS & {"cp36", "cp37", "cp38", "cp39"} if "pp" not in x
|
||||
}
|
||||
|
||||
kwargs = build_in_container.call_args_list[5][1]
|
||||
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert not kwargs["container"]["enforce_32_bit"]
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {
|
||||
f"{x}-musllinux_x86_64" for x in ALL_IDS - {"cp36", "cp37", "cp38", "cp39"} if "pp" not in x
|
||||
}
|
||||
|
||||
kwargs = build_in_container.call_args_list[6][1]
|
||||
assert "quay.io/pypa/musllinux_1_1_i686" in kwargs["container"]["image"]
|
||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||
assert kwargs["container"]["simulate_32_bit"]
|
||||
assert kwargs["container"]["enforce_32_bit"]
|
||||
|
||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
||||
|
||||
+112
-2
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from cibuildwheel.__main__ import get_build_identifiers
|
||||
from cibuildwheel.__main__ import get_build_identifiers, get_platform_module
|
||||
from cibuildwheel.bashlex_eval import local_environment_executor
|
||||
from cibuildwheel.environment import parse_environment
|
||||
from cibuildwheel.options import (
|
||||
@@ -49,8 +49,9 @@ def test_options_1(tmp_path, monkeypatch):
|
||||
|
||||
options = Options(platform="linux", command_line_arguments=args, env={})
|
||||
|
||||
module = get_platform_module("linux")
|
||||
identifiers = get_build_identifiers(
|
||||
platform="linux",
|
||||
platform_module=module,
|
||||
build_selector=options.globals.build_selector,
|
||||
architectures=options.globals.architectures,
|
||||
)
|
||||
@@ -197,3 +198,112 @@ def test_toml_environment_quoting(tmp_path: Path, toml_assignment, result_value)
|
||||
)
|
||||
|
||||
assert environment_values["TEST_VAR"] == result_value
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("toml_assignment", "result_name", "result_create_args"),
|
||||
[
|
||||
(
|
||||
'container-engine = "podman"',
|
||||
"podman",
|
||||
[],
|
||||
),
|
||||
(
|
||||
'container-engine = {name = "podman"}',
|
||||
"podman",
|
||||
[],
|
||||
),
|
||||
(
|
||||
'container-engine = "docker; create_args: --some-option"',
|
||||
"docker",
|
||||
["--some-option"],
|
||||
),
|
||||
(
|
||||
'container-engine = {name = "docker", create-args = ["--some-option"]}',
|
||||
"docker",
|
||||
["--some-option"],
|
||||
),
|
||||
(
|
||||
'container-engine = {name = "docker", create-args = ["--some-option", "value that contains spaces"]}',
|
||||
"docker",
|
||||
["--some-option", "value that contains spaces"],
|
||||
),
|
||||
(
|
||||
'container-engine = {name = "docker", create-args = ["--some-option", "value;that;contains;semicolons"]}',
|
||||
"docker",
|
||||
["--some-option", "value;that;contains;semicolons"],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_container_engine_option(tmp_path: Path, toml_assignment, result_name, result_create_args):
|
||||
args = CommandLineArguments.defaults()
|
||||
args.package_dir = tmp_path
|
||||
|
||||
tmp_path.joinpath("pyproject.toml").write_text(
|
||||
textwrap.dedent(
|
||||
f"""\
|
||||
[tool.cibuildwheel]
|
||||
{toml_assignment}
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
options = Options(platform="linux", command_line_arguments=args, env={})
|
||||
parsed_container_engine = options.globals.container_engine
|
||||
|
||||
assert parsed_container_engine.name == result_name
|
||||
assert parsed_container_engine.create_args == result_create_args
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("toml_assignment", "result_name", "result_args"),
|
||||
[
|
||||
(
|
||||
"",
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
'build-frontend = "build"',
|
||||
"build",
|
||||
[],
|
||||
),
|
||||
(
|
||||
'build-frontend = {name = "build"}',
|
||||
"build",
|
||||
[],
|
||||
),
|
||||
(
|
||||
'build-frontend = "pip; args: --some-option"',
|
||||
"pip",
|
||||
["--some-option"],
|
||||
),
|
||||
(
|
||||
'build-frontend = {name = "pip", args = ["--some-option"]}',
|
||||
"pip",
|
||||
["--some-option"],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_build_frontend_option(tmp_path: Path, toml_assignment, result_name, result_args):
|
||||
args = CommandLineArguments.defaults()
|
||||
args.package_dir = tmp_path
|
||||
|
||||
tmp_path.joinpath("pyproject.toml").write_text(
|
||||
textwrap.dedent(
|
||||
f"""\
|
||||
[tool.cibuildwheel]
|
||||
{toml_assignment}
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
options = Options(platform="linux", command_line_arguments=args, env={})
|
||||
parsed_build_frontend = options.build_options(identifier=None).build_frontend
|
||||
|
||||
if toml_assignment:
|
||||
assert parsed_build_frontend is not None
|
||||
assert parsed_build_frontend.name == result_name
|
||||
assert parsed_build_frontend.args == result_args
|
||||
else:
|
||||
assert parsed_build_frontend is None
|
||||
|
||||
@@ -26,6 +26,72 @@ def test_read_setup_py_simple(tmp_path):
|
||||
assert get_requires_python_str(tmp_path) == "1.23"
|
||||
|
||||
|
||||
def test_read_setup_py_if_main(tmp_path):
|
||||
with open(tmp_path / "setup.py", "w") as f:
|
||||
f.write(
|
||||
dedent(
|
||||
"""
|
||||
from setuptools import setup
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup(
|
||||
name = "hello",
|
||||
other = 23,
|
||||
example = ["item", "other"],
|
||||
python_requires = "1.23",
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert setup_py_python_requires(tmp_path.joinpath("setup.py").read_text()) == "1.23"
|
||||
assert get_requires_python_str(tmp_path) == "1.23"
|
||||
|
||||
|
||||
def test_read_setup_py_if_main_reversed(tmp_path):
|
||||
with open(tmp_path / "setup.py", "w") as f:
|
||||
f.write(
|
||||
dedent(
|
||||
"""
|
||||
from setuptools import setup
|
||||
|
||||
if "__main__" == __name__:
|
||||
setup(
|
||||
name = "hello",
|
||||
other = 23,
|
||||
example = ["item", "other"],
|
||||
python_requires = "1.23",
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert setup_py_python_requires(tmp_path.joinpath("setup.py").read_text()) == "1.23"
|
||||
assert get_requires_python_str(tmp_path) == "1.23"
|
||||
|
||||
|
||||
def test_read_setup_py_if_invalid(tmp_path):
|
||||
with open(tmp_path / "setup.py", "w") as f:
|
||||
f.write(
|
||||
dedent(
|
||||
"""
|
||||
from setuptools import setup
|
||||
|
||||
if True:
|
||||
setup(
|
||||
name = "hello",
|
||||
other = 23,
|
||||
example = ["item", "other"],
|
||||
python_requires = "1.23",
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
assert not setup_py_python_requires(tmp_path.joinpath("setup.py").read_text())
|
||||
assert not get_requires_python_str(tmp_path)
|
||||
|
||||
|
||||
def test_read_setup_py_full(tmp_path):
|
||||
with open(tmp_path / "setup.py", "w", encoding="utf8") as f:
|
||||
f.write(
|
||||
|
||||
Reference in New Issue
Block a user