Compare commits
87
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5486e0b83 | ||
|
|
ff9508a3e1 | ||
|
|
faf86a6ed7 | ||
|
|
4241f37b2c | ||
|
|
d04cacbc98 | ||
|
|
5f4e019684 | ||
|
|
2efa648f38 | ||
|
|
42728e866b | ||
|
|
6e1527b153 | ||
|
|
c25fe60385 | ||
|
|
a880bf5105 | ||
|
|
c087d85b69 | ||
|
|
6cccd09a31 | ||
|
|
aa1534d2a3 | ||
|
|
ee23dd147b | ||
|
|
55037e9716 | ||
|
|
8874ee2048 | ||
|
|
f76d345e81 | ||
|
|
5a5e514fbd | ||
|
|
017abbba68 | ||
|
|
bb1fd3320e | ||
|
|
98a6f3bf64 | ||
|
|
ee63bf16da | ||
|
|
d3eeba7967 | ||
|
|
109020ed2d | ||
|
|
fd990007be | ||
|
|
e158f22d51 | ||
|
|
8f21eb17be | ||
|
|
aac31ae2fb | ||
|
|
b882b84e47 | ||
|
|
243085f047 | ||
|
|
df6f886390 | ||
|
|
6f21f84a71 | ||
|
|
393e0352e8 | ||
|
|
9459533408 | ||
|
|
d9f987df66 | ||
|
|
f97c1fb99b | ||
|
|
5cdddb2d46 | ||
|
|
e18a6e9eb0 | ||
|
|
c42b1cecf1 | ||
|
|
c940bed415 | ||
|
|
530f52dc9c | ||
|
|
cc1d977359 | ||
|
|
d2c7614c3a | ||
|
|
66d45de432 | ||
|
|
eaa861622a | ||
|
|
7c3b0fbee8 | ||
|
|
b98602705f | ||
|
|
b4d1e17765 | ||
|
|
4e93d9153e | ||
|
|
1001c837de | ||
|
|
18f54c08e2 | ||
|
|
5b7119ecef | ||
|
|
ddbd67cbde | ||
|
|
84ac771415 | ||
|
|
e792bb9705 | ||
|
|
7940a4c0e7 | ||
|
|
3d3159b37b | ||
|
|
0319c431de | ||
|
|
80ae9a50c9 | ||
|
|
006f1e6ec6 | ||
|
|
f185952832 | ||
|
|
d5c6a83aeb | ||
|
|
2e8e511106 | ||
|
|
ec591cdf47 | ||
|
|
ee7fa96f6d | ||
|
|
d625d18b91 | ||
|
|
895eae340a | ||
|
|
9fad66fcfb | ||
|
|
dfd01af9aa | ||
|
|
735e88deba | ||
|
|
bb2f6652b7 | ||
|
|
6dcd7dd34b | ||
|
|
1327af5077 | ||
|
|
311f64987b | ||
|
|
08e5b97e57 | ||
|
|
d4a2945fcc | ||
|
|
9913c03128 | ||
|
|
c0e28d3401 | ||
|
|
8c42e7980c | ||
|
|
01ecd4e011 | ||
|
|
33da1f7d14 | ||
|
|
79b0dd3287 | ||
|
|
0787a44d99 | ||
|
|
fd11286290 | ||
|
|
22dc864d60 | ||
|
|
9d2f46ce4e |
@@ -4,11 +4,13 @@ set -o xtrace
|
|||||||
|
|
||||||
if [ "$(uname -s)" == "Darwin" ]; then
|
if [ "$(uname -s)" == "Darwin" ]; then
|
||||||
sudo softwareupdate --install-rosetta --agree-to-license
|
sudo softwareupdate --install-rosetta --agree-to-license
|
||||||
|
else
|
||||||
|
docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$PYTHON --version
|
$PYTHON --version
|
||||||
$PYTHON -m venv venv
|
$PYTHON -m venv venv
|
||||||
venv/bin/python -m pip install -U pip
|
venv/bin/python -m pip install -U pip dependency-groups
|
||||||
venv/bin/python -m pip install -e ".[dev]"
|
venv/bin/python -m dependency_groups test | xargs venv/bin/python -m pip install -e.
|
||||||
venv/bin/python -m pip freeze
|
venv/bin/python -m pip freeze
|
||||||
venv/bin/python --version
|
venv/bin/python --version
|
||||||
|
|||||||
+6
-3
@@ -2,7 +2,8 @@ only_if: changesInclude('.cirrus.yml') || ($CIRRUS_BRANCH == "main" && !changesI
|
|||||||
|
|
||||||
run_tests: &RUN_TESTS
|
run_tests: &RUN_TESTS
|
||||||
install_cibuildwheel_script:
|
install_cibuildwheel_script:
|
||||||
- python -m pip install -e ".[dev]" pytest-custom-exit-code
|
- python -m pip install dependency-groups
|
||||||
|
- python -m dependency_groups test | xargs python -m pip install -e.
|
||||||
run_cibuildwheel_tests_script:
|
run_cibuildwheel_tests_script:
|
||||||
- python ./bin/run_tests.py
|
- python ./bin/run_tests.py
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ linux_x86_task:
|
|||||||
memory: 8G
|
memory: 8G
|
||||||
|
|
||||||
install_pre_requirements_script:
|
install_pre_requirements_script:
|
||||||
|
- docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
|
||||||
- apt install -y python3-venv python-is-python3
|
- apt install -y python3-venv python-is-python3
|
||||||
<<: *RUN_TESTS
|
<<: *RUN_TESTS
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@ linux_aarch64_task:
|
|||||||
memory: 4G
|
memory: 4G
|
||||||
|
|
||||||
install_pre_requirements_script:
|
install_pre_requirements_script:
|
||||||
|
- docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
|
||||||
- apt install -y python3-venv python-is-python3
|
- apt install -y python3-venv python-is-python3
|
||||||
<<: *RUN_TESTS
|
<<: *RUN_TESTS
|
||||||
|
|
||||||
@@ -50,7 +53,7 @@ windows_x86_task:
|
|||||||
|
|
||||||
macos_arm64_task:
|
macos_arm64_task:
|
||||||
macos_instance:
|
macos_instance:
|
||||||
image: ghcr.io/cirruslabs/macos-sonoma-xcode
|
image: ghcr.io/cirruslabs/macos-runner:sonoma
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PATH: /opt/homebrew/opt/python@3.10/libexec/bin:$PATH
|
PATH: /opt/homebrew/opt/python@3.10/libexec/bin:$PATH
|
||||||
@@ -60,7 +63,7 @@ macos_arm64_task:
|
|||||||
|
|
||||||
macos_arm64_cp38_task:
|
macos_arm64_cp38_task:
|
||||||
macos_instance:
|
macos_instance:
|
||||||
image: ghcr.io/cirruslabs/macos-sonoma-xcode
|
image: ghcr.io/cirruslabs/macos-runner:sonoma
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PATH: /opt/homebrew/opt/python@3.10/libexec/bin:$PATH
|
PATH: /opt/homebrew/opt/python@3.10/libexec/bin:$PATH
|
||||||
|
|||||||
@@ -7,22 +7,17 @@ on:
|
|||||||
types:
|
types:
|
||||||
- published
|
- published
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
dist:
|
dist:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Build SDist and wheel
|
|
||||||
run: pipx run build
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: cibw-sdist
|
persist-credentials: false
|
||||||
path: dist/*
|
|
||||||
|
|
||||||
- name: Check metadata
|
- uses: hynek/build-and-inspect-python-package@v2
|
||||||
run: pipx run twine check dist/*
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
needs: [dist]
|
needs: [dist]
|
||||||
@@ -36,15 +31,16 @@ jobs:
|
|||||||
attestations: write
|
attestations: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
pattern: cibw-*
|
name: Packages
|
||||||
path: dist
|
path: dist
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
- name: Generate artifact attestation for sdist and wheel
|
- name: Generate artifact attestation for sdist and wheel
|
||||||
uses: actions/attest-build-provenance@6149ea5740be74af77f260b9db67e633f6b0a9a1 # v1.4.2
|
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
|
||||||
with:
|
with:
|
||||||
subject-path: "dist/cibuildwheel-*"
|
subject-path: "dist/cibuildwheel-*"
|
||||||
|
|
||||||
- uses: pypa/gh-action-pypi-publish@release/v1
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
attestations: true
|
||||||
|
|||||||
+52
-37
@@ -4,6 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
- 2.x
|
||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
@@ -11,6 +12,8 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
# allow manual runs on branches without a PR
|
# allow manual runs on branches without a PR
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: test-${{ github.ref }}
|
group: test-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
@@ -20,14 +23,14 @@ jobs:
|
|||||||
name: Linters (mypy, flake8, etc.)
|
name: Linters (mypy, flake8, etc.)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v5
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
- uses: pre-commit/action@v3.0.1
|
- uses: j178/prek-action@v1
|
||||||
- name: Check manifest
|
|
||||||
run: pipx run --python "${{ steps.python.outputs.python-path }}" nox -s check_manifest
|
|
||||||
- name: PyLint checks
|
- name: PyLint checks
|
||||||
run: pipx run --python "${{ steps.python.outputs.python-path }}" nox -s pylint -- --output-format=github
|
run: pipx run --python "${{ steps.python.outputs.python-path }}" nox -s pylint -- --output-format=github
|
||||||
|
|
||||||
@@ -37,20 +40,23 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
|
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-15-intel, macos-latest]
|
||||||
python_version: ['3.12']
|
python_version: ['3.13']
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
python_version: '3.8'
|
python_version: '3.8'
|
||||||
timeout-minutes: 180
|
timeout-minutes: 180
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v5
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
name: Install Python ${{ matrix.python_version }}
|
name: Install Python ${{ matrix.python_version }}
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python_version }}
|
python-version: ${{ matrix.python_version }}
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
- uses: yezz123/setup-uv@v4
|
- uses: astral-sh/setup-uv@v7
|
||||||
|
|
||||||
# free some space to prevent reaching GHA disk space limits
|
# free some space to prevent reaching GHA disk space limits
|
||||||
- name: Clean docker images
|
- name: Clean docker images
|
||||||
@@ -59,13 +65,18 @@ jobs:
|
|||||||
docker system prune -a -f
|
docker system prune -a -f
|
||||||
df -h
|
df -h
|
||||||
|
|
||||||
|
# for oci_container unit tests
|
||||||
|
- name: Set up QEMU
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: docker/setup-qemu-action@v4
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
uv pip install --system ".[test]"
|
uv sync --no-dev --group test
|
||||||
|
|
||||||
- name: Generate a sample project
|
- name: Generate a sample project
|
||||||
run: |
|
run: |
|
||||||
python -m test.test_projects test.test_0_basic.basic_project sample_proj
|
uv run -m test.test_projects test.test_0_basic.basic_project sample_proj
|
||||||
|
|
||||||
- name: Run a sample build (GitHub Action)
|
- name: Run a sample build (GitHub Action)
|
||||||
uses: ./
|
uses: ./
|
||||||
@@ -83,7 +94,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
package-dir: sample_proj
|
package-dir: sample_proj
|
||||||
output-dir: wheelhouse_only
|
output-dir: wheelhouse_only
|
||||||
only: cp312-${{ runner.os == 'Linux' && 'manylinux_x86_64' || (runner.os == 'Windows' && 'win_amd64' || 'macosx_x86_64') }}
|
only: cp312-${{ runner.os == 'Linux' && (runner.arch == 'ARM64' && 'manylinux_aarch64' || 'manylinux_x86_64') || (runner.os == 'Windows' && 'win_amd64' || 'macosx_x86_64') }}
|
||||||
|
|
||||||
- name: Create custom configuration file
|
- name: Create custom configuration file
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -104,21 +115,21 @@ jobs:
|
|||||||
output-dir: wheelhouse_config_file
|
output-dir: wheelhouse_config_file
|
||||||
config-file: sample_proj/cibw.toml
|
config-file: sample_proj/cibw.toml
|
||||||
|
|
||||||
- name: Check Action artefacts
|
- name: Check Action artifacts
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
test $(find wheelhouse -name '*.whl' | wc -l) -ge 1
|
test $(find wheelhouse -name '*.whl' | wc -l) -ge 1
|
||||||
test $(find wheelhouse_only -name '*.whl' | wc -l) -eq 1
|
test $(find wheelhouse_only -name '*.whl' | wc -l) -eq 1
|
||||||
test $(find wheelhouse_config_file -name '*.whl' | wc -l) -eq 1
|
test $(find wheelhouse_config_file -name '*.whl' | wc -l) -eq 1
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
||||||
path: wheelhouse/*.whl
|
path: wheelhouse/*.whl
|
||||||
|
|
||||||
- name: Test cibuildwheel
|
- name: Test cibuildwheel
|
||||||
run: |
|
run: |
|
||||||
python ./bin/run_tests.py --run-podman
|
uv run bin/run_tests.py ${{ (runner.os == 'Linux' && runner.arch == 'X64') && '--run-podman' || '' }}
|
||||||
|
|
||||||
emulated-archs:
|
emulated-archs:
|
||||||
name: Get qemu emulated architectures
|
name: Get qemu emulated architectures
|
||||||
@@ -127,16 +138,19 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
archs: ${{ steps.archs.outputs.archs }}
|
archs: ${{ steps.archs.outputs.archs }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v5
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
|
- uses: astral-sh/setup-uv@v7
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: python -m pip install ".[test]"
|
run: uv sync --no-dev --group test
|
||||||
- name: Get qemu emulated architectures
|
- name: Get qemu emulated architectures
|
||||||
id: archs
|
id: archs
|
||||||
run: |
|
run: |
|
||||||
OUTPUT=$(python -c "from json import dumps; from test.utils import EMULATED_ARCHS; print(dumps(EMULATED_ARCHS))")
|
OUTPUT=$(uv run --no-sync python -c "from json import dumps; from test.utils import EMULATED_ARCHS; print(dumps(EMULATED_ARCHS))")
|
||||||
echo "${OUTPUT}"
|
echo "${OUTPUT}"
|
||||||
echo "archs=${OUTPUT}" >> "$GITHUB_OUTPUT"
|
echo "archs=${OUTPUT}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
@@ -149,41 +163,43 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
arch: ${{ fromJSON(needs.emulated-archs.outputs.archs) }}
|
arch: ${{ fromJSON(needs.emulated-archs.outputs.archs) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v5
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
|
- uses: astral-sh/setup-uv@v7
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: python -m pip install ".[test,uv]"
|
run: uv sync --no-dev --group test
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
id: qemu
|
uses: docker/setup-qemu-action@v4
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
with:
|
|
||||||
platforms: all
|
|
||||||
|
|
||||||
- name: Run the emulation tests
|
- name: Run the emulation tests
|
||||||
run: pytest --run-emulation ${{ matrix.arch }} test/test_emulation.py
|
run: uv run --no-sync pytest --run-emulation ${{ matrix.arch }} test/test_emulation.py
|
||||||
|
|
||||||
test-pyodide:
|
test-pyodide:
|
||||||
name: Test cibuildwheel building pyodide wheels
|
name: Test cibuildwheel building Pyodide wheels
|
||||||
needs: lint
|
needs: lint
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 180
|
timeout-minutes: 180
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v5
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
name: Install Python 3.12
|
name: Install Python 3.12
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.12'
|
||||||
|
- uses: astral-sh/setup-uv@v7
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: uv sync --no-dev --group test
|
||||||
python -m pip install ".[test]"
|
|
||||||
|
|
||||||
- name: Generate a sample project
|
- name: Generate a sample project
|
||||||
run: |
|
run: |
|
||||||
python -m test.test_projects test.test_0_basic.basic_project sample_proj
|
uv run -m test.test_projects test.test_0_basic.basic_project sample_proj
|
||||||
|
|
||||||
- name: Run a sample build (GitHub Action)
|
- name: Run a sample build (GitHub Action)
|
||||||
uses: ./
|
uses: ./
|
||||||
@@ -194,7 +210,6 @@ jobs:
|
|||||||
CIBW_PLATFORM: pyodide
|
CIBW_PLATFORM: pyodide
|
||||||
|
|
||||||
- name: Run tests with 'CIBW_PLATFORM' set to 'pyodide'
|
- name: Run tests with 'CIBW_PLATFORM' set to 'pyodide'
|
||||||
run: |
|
run: uv run --no-sync ./bin/run_tests.py
|
||||||
python ./bin/run_tests.py
|
|
||||||
env:
|
env:
|
||||||
CIBW_PLATFORM: pyodide
|
CIBW_PLATFORM: pyodide
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
name: Update dependencies
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/update-dependencies.yml'
|
|
||||||
- 'bin/update_pythons.py'
|
|
||||||
- 'bin/update_docker.py'
|
|
||||||
- 'bin/update_virtualenv.py'
|
|
||||||
- 'bin/projects.py'
|
|
||||||
- 'docs/data/projects.yml'
|
|
||||||
- 'noxfile.py'
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 6 * * 1' # "At 06:00 on Monday."
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-dependencies:
|
|
||||||
name: Update dependencies
|
|
||||||
if: github.repository_owner == 'pypa' || github.event_name != 'schedule'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: wntrblm/nox@2024.04.15
|
|
||||||
with:
|
|
||||||
python-versions: "3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13"
|
|
||||||
|
|
||||||
- name: "Run update: dependencies"
|
|
||||||
run: nox --force-color -s update_constraints
|
|
||||||
- name: "Run update: python configs"
|
|
||||||
run: nox --force-color -s update_pins
|
|
||||||
- name: "Run update: docs user projects"
|
|
||||||
run: nox --force-color -s update_proj -- --auth=${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
# 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@v2
|
|
||||||
id: generate-token
|
|
||||||
if: github.ref == 'refs/heads/main' && github.repository == 'pypa/cibuildwheel'
|
|
||||||
with:
|
|
||||||
app_id: ${{ secrets.CIBUILDWHEEL_BOT_APP_ID }}
|
|
||||||
private_key: ${{ secrets.CIBUILDWHEEL_BOT_APP_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
- name: Create Pull Request
|
|
||||||
if: github.ref == 'refs/heads/main' && github.repository == 'pypa/cibuildwheel'
|
|
||||||
uses: peter-evans/create-pull-request@v6
|
|
||||||
with:
|
|
||||||
commit-message: Update dependencies
|
|
||||||
title: '[Bot] Update dependencies'
|
|
||||||
body: |
|
|
||||||
Update the versions of our dependencies.
|
|
||||||
|
|
||||||
PR generated by "Update dependencies" [workflow](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}).
|
|
||||||
branch: update-dependencies-pr
|
|
||||||
committer: "cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>"
|
|
||||||
author: "cibuildwheel-bot[bot] <83877280+cibuildwheel-bot[bot]@users.noreply.github.com>"
|
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
|
||||||
delete-branch: true
|
|
||||||
@@ -21,7 +21,9 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Update the ${{ env.TAG_NAME }} tag
|
- name: Update the ${{ env.TAG_NAME }} tag
|
||||||
id: update-major-minor-tag
|
id: update-major-minor-tag
|
||||||
|
|||||||
+8
-4
@@ -15,7 +15,9 @@ linux:
|
|||||||
PYTEST_ADDOPTS: -k "unit_test or test_0_basic" --suppress-no-test-exit-code
|
PYTEST_ADDOPTS: -k "unit_test or test_0_basic" --suppress-no-test-exit-code
|
||||||
script:
|
script:
|
||||||
- curl -sSL https://get.docker.com/ | sh
|
- curl -sSL https://get.docker.com/ | sh
|
||||||
- python -m pip install -e ".[dev]" pytest-custom-exit-code
|
- docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
|
||||||
|
- python -m pip install dependency-groups
|
||||||
|
- python -m dependency_groups test | xargs python -m pip install -e. pytest-custom-exit-code
|
||||||
- python ./bin/run_tests.py
|
- python ./bin/run_tests.py
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
@@ -25,17 +27,19 @@ windows:
|
|||||||
before_script:
|
before_script:
|
||||||
- choco install python -y --version 3.12.4
|
- choco install python -y --version 3.12.4
|
||||||
script:
|
script:
|
||||||
- py -m pip install -e ".[dev]" pytest-custom-exit-code
|
- py -m pip install dependency-groups
|
||||||
|
- py -m pip install -e. pytest-custom-exit-code $(py -m dependency_groups test)
|
||||||
- py bin\run_tests.py
|
- py bin\run_tests.py
|
||||||
tags:
|
tags:
|
||||||
- saas-windows-medium-amd64
|
- saas-windows-medium-amd64
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
image: macos-14-xcode-15
|
image: macos-latest-xcode-15
|
||||||
variables:
|
variables:
|
||||||
PYTEST_ADDOPTS: -k "unit_test or test_0_basic" --suppress-no-test-exit-code
|
PYTEST_ADDOPTS: -k "unit_test or test_0_basic" --suppress-no-test-exit-code
|
||||||
script:
|
script:
|
||||||
- python3 -m pip install -e ".[dev]" pytest-custom-exit-code
|
- python3 -m pip install dependency-groups
|
||||||
|
- python3 -m dependency_groups test | xargs python3 -m pip install -e. pytest-custom-exit-code
|
||||||
- python3 ./bin/run_tests.py
|
- python3 ./bin/run_tests.py
|
||||||
tags:
|
tags:
|
||||||
- saas-macos-medium-m1
|
- saas-macos-medium-m1
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
repos:
|
repos:
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.6.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-case-conflict
|
- id: check-case-conflict
|
||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
@@ -14,14 +14,14 @@ repos:
|
|||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.6.3
|
rev: v0.8.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: ["--fix", "--show-fixes"]
|
args: ["--fix", "--show-fixes"]
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v1.11.2
|
rev: v1.13.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
name: mypy 3.8 on cibuildwheel/
|
name: mypy 3.8 on cibuildwheel/
|
||||||
@@ -29,9 +29,12 @@ repos:
|
|||||||
args: ["--python-version=3.8"]
|
args: ["--python-version=3.8"]
|
||||||
additional_dependencies: &mypy-dependencies
|
additional_dependencies: &mypy-dependencies
|
||||||
- bracex
|
- bracex
|
||||||
|
- dependency-groups>=1.2
|
||||||
- nox
|
- nox
|
||||||
|
- orjson
|
||||||
- packaging
|
- packaging
|
||||||
- pygithub
|
- pygithub
|
||||||
|
- pytest<9
|
||||||
- rich
|
- rich
|
||||||
- tomli
|
- tomli
|
||||||
- tomli_w
|
- tomli_w
|
||||||
@@ -40,6 +43,7 @@ repos:
|
|||||||
- types-jinja2
|
- types-jinja2
|
||||||
- types-pyyaml
|
- types-pyyaml
|
||||||
- types-requests
|
- types-requests
|
||||||
|
- types-setuptools
|
||||||
- uv
|
- uv
|
||||||
- validate-pyproject
|
- validate-pyproject
|
||||||
- id: mypy
|
- id: mypy
|
||||||
@@ -77,7 +81,7 @@ repos:
|
|||||||
|
|
||||||
|
|
||||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||||
rev: 0.29.2
|
rev: 0.29.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-dependabot
|
- id: check-dependabot
|
||||||
- id: check-github-actions
|
- id: check-github-actions
|
||||||
|
|||||||
+2
-4
@@ -3,13 +3,11 @@
|
|||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
build:
|
build:
|
||||||
os: ubuntu-22.04
|
os: ubuntu-24.04
|
||||||
tools:
|
tools:
|
||||||
python: "3.12"
|
python: "3.12"
|
||||||
commands:
|
commands:
|
||||||
- asdf plugin add uv
|
- asdf plugin add uv
|
||||||
- asdf install uv latest
|
- asdf install uv latest
|
||||||
- asdf global uv latest
|
- asdf global uv latest
|
||||||
- uv venv
|
- NO_COLOR=1 uv run --no-dev --group docs mkdocs build --strict --site-dir $READTHEDOCS_OUTPUT/html
|
||||||
- uv pip install -e.[docs]
|
|
||||||
- NO_COLOR=1 .venv/bin/mkdocs build --strict --site-dir $READTHEDOCS_OUTPUT/html
|
|
||||||
|
|||||||
+11
-2
@@ -20,6 +20,14 @@ jobs:
|
|||||||
group: edge
|
group: edge
|
||||||
virt: vm
|
virt: vm
|
||||||
env: PYTHON=python
|
env: PYTHON=python
|
||||||
|
# docker is outdated in the arm64-graviton2 vm focal image (19.x)
|
||||||
|
# we need to upgrade to get >= 24.0
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: 'deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable'
|
||||||
|
packages:
|
||||||
|
- docker-ce docker-ce-cli containerd.io
|
||||||
|
|
||||||
- name: Linux | ppc64le | Python 3.9
|
- name: Linux | ppc64le | Python 3.9
|
||||||
python: 3.9
|
python: 3.9
|
||||||
@@ -48,8 +56,9 @@ jobs:
|
|||||||
env: PYTHON=python
|
env: PYTHON=python
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- $PYTHON -m pip install -U pip
|
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all; fi
|
||||||
- $PYTHON -m pip install -e ".[dev]" pytest-custom-exit-code
|
- $PYTHON -m pip install -U pip dependency-groups
|
||||||
|
- $PYTHON -m dependency_groups test | xargs $PYTHON -m pip install -e.
|
||||||
|
|
||||||
script: |
|
script: |
|
||||||
# travis_wait disable the output while waiting
|
# travis_wait disable the output while waiting
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ cibuildwheel
|
|||||||
[](https://pypi.python.org/pypi/cibuildwheel)
|
[](https://pypi.python.org/pypi/cibuildwheel)
|
||||||
[](https://cibuildwheel.pypa.io/en/stable/?badge=stable)
|
[](https://cibuildwheel.pypa.io/en/stable/?badge=stable)
|
||||||
[](https://github.com/pypa/cibuildwheel/actions)
|
[](https://github.com/pypa/cibuildwheel/actions)
|
||||||
[](https://travis-ci.com/pypa/cibuildwheel)
|
[](https://travis-ci.com/github/pypa/cibuildwheel)
|
||||||
[](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/main)
|
[](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/main)
|
||||||
[](https://circleci.com/gh/pypa/cibuildwheel)
|
[](https://circleci.com/gh/pypa/cibuildwheel)
|
||||||
[](https://dev.azure.com/joerick0429/cibuildwheel/_build/latest?definitionId=4&branchName=main)
|
[](https://dev.azure.com/joerick0429/cibuildwheel/_build/latest?definitionId=4&branchName=main)
|
||||||
@@ -22,27 +22,31 @@ Python wheels are great. Building them across **Mac, Linux, Windows**, on **mult
|
|||||||
What does it do?
|
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 | Pyodide |
|
While cibuildwheel itself requires a recent Python version to run (we support the last three releases), it can target the following versions to build wheels:
|
||||||
|----------------|----|-----|-----|-----|-----|----|-----|----|-----|-----|-----|
|
|
||||||
| CPython 3.6 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
|
| | 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 | manylinux<br/>musllinux armv7l | Pyodide |
|
||||||
| CPython 3.7 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
|
|----------------|----|-----|-----|-----|-----|----|-----|----|-----|-----|---|-----|
|
||||||
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
|
| CPython 3.6 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A |
|
||||||
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
|
| CPython 3.7 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A |
|
||||||
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
|
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A |
|
||||||
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
|
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A |
|
||||||
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁴ |
|
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A |
|
||||||
| CPython 3.13³ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | N/A |
|
| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A |
|
||||||
| PyPy 3.7 v7.3 | ✅ | N/A | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A |
|
| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | ✅⁴ |
|
||||||
| PyPy 3.8 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A |
|
| CPython 3.13³ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ | ✅⁵ | N/A |
|
||||||
| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A |
|
| PyPy 3.7 v7.3 | ✅ | N/A | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A |
|
||||||
| PyPy 3.10 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 | N/A | N/A |
|
||||||
|
| PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A |
|
||||||
|
| PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A |
|
||||||
|
| PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A | N/A | N/A |
|
||||||
|
|
||||||
<sup>¹ PyPy is only supported for manylinux wheels.</sup><br>
|
<sup>¹ PyPy is only supported for manylinux wheels.</sup><br>
|
||||||
<sup>² Windows arm64 support is experimental.</sup><br>
|
<sup>² Windows arm64 support is experimental.</sup><br>
|
||||||
<sup>³ CPython 3.13 is built by default using Python RCs, starting with cibuildwheel 2.20. Free-threaded mode will still require opt-in using [`CIBW_FREE_THREADED_SUPPORT`](https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support).</sup><br>
|
<sup>³ Free-threaded mode requires opt-in using [`CIBW_FREE_THREADED_SUPPORT`](https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support).</sup><br>
|
||||||
<sup>⁴ Experimental, not yet supported on PyPI, but can be used directly in web deployment. Use `--platform pyodide` to build.</sup><br>
|
<sup>⁴ Experimental, not yet supported on PyPI, but can be used directly in web deployment. Use `--platform pyodide` to build.</sup><br>
|
||||||
|
<sup>⁵ manylinux armv7l support is experimental. As there are no RHEL based image for this architecture, it's using an Ubuntu based image instead.</sup><br>
|
||||||
|
|
||||||
- Builds manylinux, musllinux, macOS 10.9+, and Windows wheels for CPython and PyPy
|
- Builds manylinux, musllinux, macOS 10.9+ (10.13+ for Python 3.12+), and Windows wheels for CPython and PyPy
|
||||||
- Works on GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, CircleCI, GitLab CI, and Cirrus CI
|
- Works on GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, CircleCI, GitLab CI, and Cirrus CI
|
||||||
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
|
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
|
||||||
- Runs your library's tests against the wheel-installed version of your library
|
- Runs your library's tests against the wheel-installed version of your library
|
||||||
@@ -56,7 +60,7 @@ Usage
|
|||||||
|
|
||||||
| | Linux | macOS | Windows | Linux ARM | macOS ARM | Windows ARM |
|
| | Linux | macOS | Windows | Linux ARM | macOS ARM | Windows ARM |
|
||||||
|-----------------|-------|-------|---------|-----------|-----------|-------------|
|
|-----------------|-------|-------|---------|-----------|-----------|-------------|
|
||||||
| GitHub Actions | ✅ | ✅ | ✅ | ✅¹ | ✅ | ✅² |
|
| GitHub Actions | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
|
||||||
| Azure Pipelines | ✅ | ✅ | ✅ | | ✅ | ✅² |
|
| Azure Pipelines | ✅ | ✅ | ✅ | | ✅ | ✅² |
|
||||||
| Travis CI | ✅ | | ✅ | ✅ | | |
|
| Travis CI | ✅ | | ✅ | ✅ | | |
|
||||||
| AppVeyor | ✅ | ✅ | ✅ | | ✅ | ✅² |
|
| AppVeyor | ✅ | ✅ | ✅ | | ✅ | ✅² |
|
||||||
@@ -85,7 +89,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
|
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-15-intel, macos-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -94,7 +98,7 @@ jobs:
|
|||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v5
|
||||||
|
|
||||||
- name: Install cibuildwheel
|
- name: Install cibuildwheel
|
||||||
run: python -m pip install cibuildwheel==2.20.0
|
run: python -m pip install cibuildwheel==2.23.4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
run: python -m cibuildwheel --output-dir wheelhouse
|
run: python -m cibuildwheel --output-dir wheelhouse
|
||||||
@@ -211,65 +215,40 @@ Changelog
|
|||||||
|
|
||||||
<!-- this section was generated by bin/update_readme_changelog.py -- do not edit manually -->
|
<!-- this section was generated by bin/update_readme_changelog.py -- do not edit manually -->
|
||||||
|
|
||||||
### v2.20.0
|
### v2.23.4
|
||||||
|
|
||||||
- 🌟 CPython 3.13 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.13.0rc1, which is guaranteed to be ABI compatible with the final release. Free-threading is still behind a flag/config option. (#1950)
|
_16 March 2026_
|
||||||
- ✨ Provide a `CIBW_ALLOW_EMPTY` environment variable as an alternative to the command line flag. (#1937)
|
|
||||||
- 🐛 Don't use uv on PyPy3.8 on Windows, it stopped working starting in 0.2.25. Note that PyPy 3.8 is EoL. (#1868)
|
|
||||||
- 🛠 Set the `VSCMD_ARG_TGT_ARCH` variable based on target arch. (#1876)
|
|
||||||
- 🛠 Undo cleaner output on pytest 8-8.2 now that 8.3 is out. (#1943)
|
|
||||||
- 📚 Update examples to use Python 3.12 on host (cibuildwheel will require Python 3.11+ on the host machine starting in October 2024) (#1919)
|
|
||||||
|
|
||||||
|
- 🐛 Fix HTTP 429 errors while downloading virtualenv from GitHub blob URLs – uses a https://bootstrap.pypa.io/ URL instead. (#2775)
|
||||||
|
|
||||||
### v2.19.2
|
### v2.23.3
|
||||||
|
|
||||||
- 🐛 Update manylinux2014 pins to versions that support past-EoL CentOS 7 mirrors. (#1917)
|
_26 April 2025_
|
||||||
- 🐛 Support `--no-isolation` with `build[uv]` build-frontend. (#1889)
|
|
||||||
- 🛠 Provide attestations for releases at <https://github.com/pypa/cibuildwheel/attestations>. (#1916)
|
|
||||||
- 🛠 Provide CPython 3.13.0b3. (#1913)
|
|
||||||
- 🛠 Remove some workarounds now that pip 21.1 is available. (#1891, #1892)
|
|
||||||
- 📚 Remove nosetest from our docs. (#1821)
|
|
||||||
- 📚 Document the macOS ARM workaround for 3.8 on GHA. (#1871)
|
|
||||||
- 📚 GitLab CI + macOS is now a supported platform with an example. (#1911)
|
|
||||||
|
|
||||||
|
- 🛠 Dependency updates, including Python 3.13.3 (#2371)
|
||||||
|
|
||||||
### v2.19.1
|
### v2.23.2
|
||||||
|
|
||||||
- 🐛 Don't require setup-python on GHA for Pyodide (#1868)
|
_24 March 2025_
|
||||||
- 🐛 Specify full python path for uv (fixes issue in 0.2.10 & 0.2.11) (#1881)
|
|
||||||
- 🛠 Update for pip 24.1b2 on CPython 3.13. (#1879)
|
|
||||||
- 🛠 Fix a warning in our schema generation script. (#1866)
|
|
||||||
- 🛠 Cleaner output on pytest 8-8.2. (#1865)
|
|
||||||
|
|
||||||
|
- 🐛 Workaround an issue with pyodide builds when running cibuildwheel with a Python that was installed via UV (#2328 via #2331)
|
||||||
|
- 🛠 Dependency updates, including a manylinux update that fixes an ['undefined symbol' error](https://github.com/pypa/manylinux/issues/1760) in gcc-toolset (#2334)
|
||||||
|
|
||||||
### v2.19.0
|
### v2.23.1
|
||||||
|
|
||||||
See the [release post](https://iscinumpy.dev/post/cibuildwheel-2-19-0/) for more info on new features!
|
_15 March 2025_
|
||||||
|
|
||||||
- 🌟 Add Pyodide platform. Set with `--platform pyodide` or `CIBW_PLATFORM: pyodide` on Linux with a host Python 3.12 to build WebAssembly wheels. Not accepted on PyPI currently, but usable directly in a website using Pyodide, for live docs, etc. (#1456, #1859)
|
- ⚠️ Added warnings when the shorthand values `manylinux1`, `manylinux2010`, `manylinux_2_24`, and `musllinux_1_1` are used to specify the images in linux builds. The shorthand to these (unmaintainted) images will be removed in v3.0. If you want to keep using these images, explicitly opt-in using the full image URL, which can be found in [this file](https://github.com/pypa/cibuildwheel/blob/v2.23.1/cibuildwheel/resources/pinned_docker_images.cfg). (#2312)
|
||||||
- 🌟 Add `build[uv]` backend, which will take a pre-existing uv install (or install `cibuildwheel[uv]`) and use `uv` for all environment setup and installs on Python 3.8+. This is significantly faster in most cases. (#1856)
|
- 🛠 Dependency updates, including a manylinux update which fixes an [issue with rustup](https://github.com/pypa/cibuildwheel/issues/2303). (#2315)
|
||||||
- ✨ Add free-threaded macOS builds and update CPython to 3.13.0b2. (#1854)
|
|
||||||
- 🐛 Issue copying a wheel to a non-existent output dir fixed. (#1851, #1862)
|
|
||||||
- 🐛 Better determinism for the test environment seeding. (#1835)
|
|
||||||
- 🛠 `VIRTUAL_ENV` variable now set. (#1842)
|
|
||||||
- 🛠 Remove a pip<21.3 workaround. (#1842)
|
|
||||||
- 🛠 Error handling was refactored to use exceptions. (#1719)
|
|
||||||
- 🛠 Hardcoded paths in tests avoided. (#1834)
|
|
||||||
- 🛠 Single Python tests made more generic. (#1835)
|
|
||||||
- 🛠 Sped up our ci by splitting up emulation tests. (#1839)
|
|
||||||
|
|
||||||
|
### v2.23.0
|
||||||
|
|
||||||
|
_1 March 2025_
|
||||||
|
|
||||||
### v2.18.1
|
- ✨ Adds official support for the new GitHub Actions Arm runners. In fact these worked out-of-the-box, now we include them in our tests and example configs. (#2135 via #2281)
|
||||||
|
- ✨ Adds support for building PyPy 3.11 wheels (#2268 via #2281)
|
||||||
- 🌟 Add free-threaded Linux and Windows builds for 3.13. New identifiers `cp313t-*`, new option `CIBW_FREE_THREADED_SUPPORT`/`tool.cibuildwheel.free-threaded-support` required to opt-in. [See the docs](https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support) for more information. (#1831)
|
- 🛠 Adopts the beta pypa/manylinux image for armv7l builds (#2269 via #2281)
|
||||||
- ✨ The `container-engine` is now a build (non-global) option. (#1792)
|
- 🛠 Dependency updates, including Pyodide 0.27 (#2117 and #2281)
|
||||||
- 🛠 The build backend for cibuildwheel is now hatchling. (#1297)
|
|
||||||
- 🛠 Significant improvements and modernization to our noxfile. (#1823)
|
|
||||||
- 🛠 Use pylint's new GitHub Actions reporter instead of a custom matcher. (#1823)
|
|
||||||
- 🛠 Unpin virtualenv updates for Python 3.7+ (#1830)
|
|
||||||
- 🐛 Fix running linux tests from Windows or macOS ARM. (#1788)
|
|
||||||
- 📚 Fix our documentation build. (#1821)
|
|
||||||
|
|
||||||
<!-- END bin/update_readme_changelog.py -->
|
<!-- END bin/update_readme_changelog.py -->
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ init:
|
|||||||
if (-not ($BRANCH -eq 'main' -or $BRANCH.ToLower().StartsWith('appveyor-'))) {
|
if (-not ($BRANCH -eq 'main' -or $BRANCH.ToLower().StartsWith('appveyor-'))) {
|
||||||
$env:PYTEST_ADDOPTS = '-k "unit_test or test_0_basic" --suppress-no-test-exit-code'
|
$env:PYTEST_ADDOPTS = '-k "unit_test or test_0_basic" --suppress-no-test-exit-code'
|
||||||
}
|
}
|
||||||
|
if ($IsLinux) {
|
||||||
|
docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
|
||||||
|
}
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- python -m pip install -U pip
|
- python -m pip install -U pip
|
||||||
|
|||||||
+10
-6
@@ -7,32 +7,36 @@ pr:
|
|||||||
jobs:
|
jobs:
|
||||||
- job: linux_38
|
- job: linux_38
|
||||||
timeoutInMinutes: 120
|
timeoutInMinutes: 120
|
||||||
pool: {vmImage: 'Ubuntu-20.04'}
|
pool: {vmImage: 'ubuntu-latest'}
|
||||||
steps:
|
steps:
|
||||||
- task: UsePythonVersion@0
|
- task: UsePythonVersion@0
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '3.8'
|
versionSpec: '3.8'
|
||||||
- bash: |
|
- bash: |
|
||||||
python -m pip install -e ".[dev]"
|
docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
|
||||||
|
python -m pip install dependency-groups
|
||||||
|
python -m dependency_groups test | xargs python -m pip install -e.
|
||||||
python ./bin/run_tests.py
|
python ./bin/run_tests.py
|
||||||
|
|
||||||
- job: macos_38
|
- job: macos_38
|
||||||
pool: {vmImage: 'macOS-12'}
|
pool: {vmImage: 'macos-latest'}
|
||||||
steps:
|
steps:
|
||||||
- task: UsePythonVersion@0
|
- task: UsePythonVersion@0
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '3.8'
|
versionSpec: '3.8'
|
||||||
- bash: |
|
- bash: |
|
||||||
python -m pip install -e ".[dev]"
|
python -m pip install dependency-groups
|
||||||
|
python -m dependency_groups test | xargs python -m pip install -e.
|
||||||
python ./bin/run_tests.py --num-processes 2
|
python ./bin/run_tests.py --num-processes 2
|
||||||
|
|
||||||
- job: windows_38
|
- job: windows_38
|
||||||
pool: {vmImage: 'windows-2019'}
|
pool: {vmImage: 'windows-latest'}
|
||||||
timeoutInMinutes: 180
|
timeoutInMinutes: 180
|
||||||
steps:
|
steps:
|
||||||
- task: UsePythonVersion@0
|
- task: UsePythonVersion@0
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '3.8'
|
versionSpec: '3.8'
|
||||||
- bash: |
|
- bash: |
|
||||||
python -m pip install -e ".[dev]"
|
python -m pip install dependency-groups
|
||||||
|
python -m dependency_groups test | xargs python -m pip install -e.
|
||||||
python ./bin/run_tests.py
|
python ./bin/run_tests.py
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ $defs:
|
|||||||
- append
|
- append
|
||||||
default: none
|
default: none
|
||||||
description: How to inherit the parent's value.
|
description: How to inherit the parent's value.
|
||||||
|
enable:
|
||||||
|
enum:
|
||||||
|
- cpython-freethreading
|
||||||
|
- cpython-prerelease
|
||||||
|
- pypy
|
||||||
|
description: A Python version or flavor to enable.
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: cibuildwheel's settings.
|
description: cibuildwheel's settings.
|
||||||
type: object
|
type: object
|
||||||
@@ -99,6 +105,13 @@ properties:
|
|||||||
default: pinned
|
default: pinned
|
||||||
description: Specify how cibuildwheel controls the versions of the tools it uses
|
description: Specify how cibuildwheel controls the versions of the tools it uses
|
||||||
type: string
|
type: string
|
||||||
|
enable:
|
||||||
|
description: Enable or disable certain builds.
|
||||||
|
oneOf:
|
||||||
|
- $ref: "#/$defs/enable"
|
||||||
|
- type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/$defs/enable"
|
||||||
environment:
|
environment:
|
||||||
description: Set environment variables needed during the build.
|
description: Set environment variables needed during the build.
|
||||||
type: string_table
|
type: string_table
|
||||||
@@ -110,9 +123,13 @@ properties:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
description: The project supports free-threaded builds of Python (PEP703)
|
description: The project supports free-threaded builds of Python (PEP703)
|
||||||
|
deprecated: Use the `enable` option instead.
|
||||||
manylinux-aarch64-image:
|
manylinux-aarch64-image:
|
||||||
type: string
|
type: string
|
||||||
description: Specify alternative manylinux / musllinux container images
|
description: Specify alternative manylinux / musllinux container images
|
||||||
|
manylinux-armv7l-image:
|
||||||
|
type: string
|
||||||
|
description: Specify alternative manylinux / musllinux container images
|
||||||
manylinux-i686-image:
|
manylinux-i686-image:
|
||||||
type: string
|
type: string
|
||||||
description: Specify alternative manylinux / musllinux container images
|
description: Specify alternative manylinux / musllinux container images
|
||||||
@@ -137,6 +154,9 @@ properties:
|
|||||||
musllinux-aarch64-image:
|
musllinux-aarch64-image:
|
||||||
type: string
|
type: string
|
||||||
description: Specify alternative manylinux / musllinux container images
|
description: Specify alternative manylinux / musllinux container images
|
||||||
|
musllinux-armv7l-image:
|
||||||
|
type: string
|
||||||
|
description: Specify alternative manylinux / musllinux container images
|
||||||
musllinux-i686-image:
|
musllinux-i686-image:
|
||||||
type: string
|
type: string
|
||||||
description: Specify alternative manylinux / musllinux container images
|
description: Specify alternative manylinux / musllinux container images
|
||||||
@@ -161,6 +181,9 @@ properties:
|
|||||||
test-extras:
|
test-extras:
|
||||||
description: Install your wheel for testing using `extras_require`
|
description: Install your wheel for testing using `extras_require`
|
||||||
type: string_array
|
type: string_array
|
||||||
|
test-groups:
|
||||||
|
description: Install extra groups when testing
|
||||||
|
type: string_array
|
||||||
test-requires:
|
test-requires:
|
||||||
description: Install Python dependencies before running the tests
|
description: Install Python dependencies before running the tests
|
||||||
type: string_array
|
type: string_array
|
||||||
@@ -255,6 +278,7 @@ del non_global_options["build"]
|
|||||||
del non_global_options["skip"]
|
del non_global_options["skip"]
|
||||||
del non_global_options["test-skip"]
|
del non_global_options["test-skip"]
|
||||||
del non_global_options["free-threaded-support"]
|
del non_global_options["free-threaded-support"]
|
||||||
|
del non_global_options["enable"]
|
||||||
|
|
||||||
overrides["items"]["properties"]["select"]["oneOf"] = string_array
|
overrides["items"]["properties"]["select"]["oneOf"] = string_array
|
||||||
overrides["items"]["properties"] |= non_global_options.copy()
|
overrides["items"]["properties"] |= non_global_options.copy()
|
||||||
|
|||||||
@@ -3,27 +3,29 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import run
|
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
|
||||||
def shell(cmd, *, check: bool, **kwargs):
|
def shell(cmd: str, *, check: bool, **kwargs: object) -> subprocess.CompletedProcess[str]:
|
||||||
return run([cmd], shell=True, check=check, **kwargs)
|
return subprocess.run([cmd], shell=True, check=check, **kwargs) # type: ignore[call-overload, no-any-return]
|
||||||
|
|
||||||
|
|
||||||
def git_repo_has_changes():
|
def git_repo_has_changes() -> bool:
|
||||||
unstaged_changes = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
|
unstaged_changes: bool = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
|
||||||
staged_changes = shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
|
staged_changes: bool = (
|
||||||
|
shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
|
||||||
|
)
|
||||||
return unstaged_changes or staged_changes
|
return unstaged_changes or staged_changes
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
def main():
|
def main() -> None:
|
||||||
project_root = Path(__file__).parent / ".."
|
project_root = Path(__file__).parent / ".."
|
||||||
os.chdir(project_root)
|
os.chdir(project_root)
|
||||||
|
|
||||||
@@ -57,7 +59,7 @@ def main():
|
|||||||
PR generated by `{os.path.basename(__file__)}`.
|
PR generated by `{os.path.basename(__file__)}`.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
run(
|
subprocess.run(
|
||||||
[
|
[
|
||||||
"gh",
|
"gh",
|
||||||
"pr",
|
"pr",
|
||||||
|
|||||||
+4
-2
@@ -172,7 +172,9 @@ def get_projects(
|
|||||||
return sorted((Project(item, github) for item in config), reverse=online)
|
return sorted((Project(item, github) for item in config), reverse=online)
|
||||||
|
|
||||||
|
|
||||||
def render_projects(projects: Sequence[Project], *, dest_path: Path, include_info: bool = True):
|
def render_projects(
|
||||||
|
projects: Sequence[Project], *, dest_path: Path, include_info: bool = True
|
||||||
|
) -> str:
|
||||||
io = StringIO()
|
io = StringIO()
|
||||||
print = functools.partial(builtins.print, file=io)
|
print = functools.partial(builtins.print, file=io)
|
||||||
|
|
||||||
@@ -203,7 +205,7 @@ def insert_projects_table(
|
|||||||
projects: Sequence[Project],
|
projects: Sequence[Project],
|
||||||
input_filename: str,
|
input_filename: str,
|
||||||
include_info: bool = True,
|
include_info: bool = True,
|
||||||
):
|
) -> None:
|
||||||
text = file.read_text()
|
text = file.read_text()
|
||||||
projects_table = render_projects(projects, include_info=include_info, dest_path=file)
|
projects_table = render_projects(projects, include_info=include_info, dest_path=file)
|
||||||
|
|
||||||
|
|||||||
@@ -4,29 +4,29 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import time
|
import time
|
||||||
import typing
|
import typing
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import run
|
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
|
||||||
def shell(cmd, *, check: bool, **kwargs):
|
def shell(cmd: str, *, check: bool, **kwargs: object) -> subprocess.CompletedProcess[str]:
|
||||||
return run([cmd], shell=True, check=check, **kwargs)
|
return subprocess.run([cmd], shell=True, check=check, **kwargs) # type: ignore[call-overload, no-any-return]
|
||||||
|
|
||||||
|
|
||||||
def git_repo_has_changes():
|
def git_repo_has_changes() -> bool:
|
||||||
unstaged_changes = shell("git diff-index --quiet HEAD --", check=False).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
|
staged_changes = shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
|
||||||
return unstaged_changes or staged_changes
|
return unstaged_changes or staged_changes
|
||||||
|
|
||||||
|
|
||||||
def generate_basic_project(path):
|
def generate_basic_project(path: Path) -> None:
|
||||||
sys.path.insert(0, "")
|
sys.path.insert(0, "")
|
||||||
from test.test_projects.c import new_c_project
|
from test.test_projects.c import new_c_project
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ services = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def ci_service_for_config_file(config_file):
|
def ci_service_for_config_file(config_file: str) -> CIService:
|
||||||
filename = Path(config_file).name
|
filename = Path(config_file).name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -134,7 +134,7 @@ def run_example_ci_configs(config_files=None):
|
|||||||
dst_config_file.parent.mkdir(parents=True, exist_ok=True)
|
dst_config_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
shutil.copyfile(src_config_file, dst_config_file)
|
shutil.copyfile(src_config_file, dst_config_file)
|
||||||
|
|
||||||
run(["git", "add", example_project], check=True)
|
subprocess.run(["git", "add", example_project], check=True)
|
||||||
message = textwrap.dedent(
|
message = textwrap.dedent(
|
||||||
f"""\
|
f"""\
|
||||||
Test example minimal configs
|
Test example minimal configs
|
||||||
@@ -144,7 +144,7 @@ def run_example_ci_configs(config_files=None):
|
|||||||
Time: {timestamp}
|
Time: {timestamp}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
run(["git", "commit", "--no-verify", "--message", message], check=True)
|
subprocess.run(["git", "commit", "--no-verify", "--message", message], check=True)
|
||||||
shell(f"git subtree --prefix={example_project} push origin {branch_name}", check=True)
|
shell(f"git subtree --prefix={example_project} push origin {branch_name}", check=True)
|
||||||
|
|
||||||
print("---")
|
print("---")
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ if __name__ == "__main__":
|
|||||||
# unit tests
|
# unit tests
|
||||||
unit_test_args = [sys.executable, "-m", "pytest", "unit_test"]
|
unit_test_args = [sys.executable, "-m", "pytest", "unit_test"]
|
||||||
|
|
||||||
if sys.platform.startswith("linux"):
|
if sys.platform.startswith("linux") and os.environ.get("CIBW_PLATFORM", "linux") == "linux":
|
||||||
# run the docker unit tests only on Linux
|
# run the docker unit tests only on Linux
|
||||||
unit_test_args += ["--run-docker"]
|
unit_test_args += ["--run-docker"]
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from packaging.version import Version
|
||||||
|
|
||||||
DIR = Path(__file__).parent.resolve()
|
DIR = Path(__file__).parent.resolve()
|
||||||
RESOURCES = DIR.parent / "cibuildwheel/resources"
|
RESOURCES = DIR.parent / "cibuildwheel/resources"
|
||||||
@@ -53,6 +54,8 @@ images = [
|
|||||||
Image("manylinux_2_28", "s390x", "quay.io/pypa/manylinux_2_28_s390x", None),
|
Image("manylinux_2_28", "s390x", "quay.io/pypa/manylinux_2_28_s390x", None),
|
||||||
Image("manylinux_2_28", "pypy_x86_64", "quay.io/pypa/manylinux_2_28_x86_64", None),
|
Image("manylinux_2_28", "pypy_x86_64", "quay.io/pypa/manylinux_2_28_x86_64", None),
|
||||||
Image("manylinux_2_28", "pypy_aarch64", "quay.io/pypa/manylinux_2_28_aarch64", None),
|
Image("manylinux_2_28", "pypy_aarch64", "quay.io/pypa/manylinux_2_28_aarch64", None),
|
||||||
|
# manylinux_2_31 images
|
||||||
|
Image("manylinux_2_31", "armv7l", "quay.io/pypa/manylinux_2_31_armv7l", None),
|
||||||
# musllinux_1_1 images
|
# musllinux_1_1 images
|
||||||
Image("musllinux_1_1", "x86_64", "quay.io/pypa/musllinux_1_1_x86_64", None),
|
Image("musllinux_1_1", "x86_64", "quay.io/pypa/musllinux_1_1_x86_64", None),
|
||||||
Image("musllinux_1_1", "i686", "quay.io/pypa/musllinux_1_1_i686", None),
|
Image("musllinux_1_1", "i686", "quay.io/pypa/musllinux_1_1_i686", None),
|
||||||
@@ -65,6 +68,7 @@ images = [
|
|||||||
Image("musllinux_1_2", "aarch64", "quay.io/pypa/musllinux_1_2_aarch64", 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", "ppc64le", "quay.io/pypa/musllinux_1_2_ppc64le", None),
|
||||||
Image("musllinux_1_2", "s390x", "quay.io/pypa/musllinux_1_2_s390x", None),
|
Image("musllinux_1_2", "s390x", "quay.io/pypa/musllinux_1_2_s390x", None),
|
||||||
|
Image("musllinux_1_2", "armv7l", "quay.io/pypa/musllinux_1_2_armv7l", None),
|
||||||
]
|
]
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
@@ -90,6 +94,21 @@ for image in images:
|
|||||||
for (name, info) in tags_dict.items()
|
for (name, info) in tags_dict.items()
|
||||||
if info["manifest_digest"] == latest_tag["manifest_digest"]
|
if info["manifest_digest"] == latest_tag["manifest_digest"]
|
||||||
)
|
)
|
||||||
|
elif image.image_name.startswith("ghcr.io/"):
|
||||||
|
repository = image.image_name[8:]
|
||||||
|
response = requests.get(
|
||||||
|
"https://ghcr.io/token", params={"scope": f"repository:{repository}:pull"}
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
token = response.json()["token"]
|
||||||
|
response = requests.get(
|
||||||
|
f"https://ghcr.io/v2/{repository}/tags/list",
|
||||||
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
ghcr_tags = [(Version(tag), tag) for tag in response.json()["tags"] if tag != "latest"]
|
||||||
|
ghcr_tags.sort(reverse=True)
|
||||||
|
tag_name = ghcr_tags[0][1]
|
||||||
else:
|
else:
|
||||||
response = requests.get(f"https://hub.docker.com/v2/repositories/{image.image_name}/tags")
|
response = requests.get(f"https://hub.docker.com/v2/repositories/{image.image_name}/tags")
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ except ImportError:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
subprocess.run(["mkdocs", "build"], check=True)
|
subprocess.run(["mkdocs", "build"], check=True)
|
||||||
|
|
||||||
hti = Html2Image(custom_flags=["--force-device-scale-factor=2"])
|
hti = Html2Image(custom_flags=["--force-device-scale-factor=2"])
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ README_CHANGELOG_SECTION = re.compile(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
changelog_text = CHANGELOG_FILE.read_text()
|
changelog_text = CHANGELOG_FILE.read_text()
|
||||||
readme_text = README_FILE.read_text()
|
readme_text = README_FILE.read_text()
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class VersionTuple:
|
|||||||
version_string: str
|
version_string: str
|
||||||
|
|
||||||
|
|
||||||
def git_ls_remote_versions(url) -> list[VersionTuple]:
|
def git_ls_remote_versions(url: str) -> list[VersionTuple]:
|
||||||
versions: list[VersionTuple] = []
|
versions: list[VersionTuple] = []
|
||||||
tags = subprocess.run(
|
tags = subprocess.run(
|
||||||
["git", "ls-remote", "--tags", url], check=True, text=True, capture_output=True
|
["git", "ls-remote", "--tags", url], check=True, text=True, capture_output=True
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
__version__ = "2.20.0"
|
__version__ = "2.23.4"
|
||||||
|
|||||||
@@ -271,7 +271,6 @@ class PlatformModule(Protocol):
|
|||||||
def build(self, options: Options, tmp_path: Path) -> None: ...
|
def build(self, options: Options, tmp_path: Path) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable-next=inconsistent-return-statements
|
|
||||||
def get_platform_module(platform: PlatformName) -> PlatformModule:
|
def get_platform_module(platform: PlatformName) -> PlatformModule:
|
||||||
if platform == "linux":
|
if platform == "linux":
|
||||||
return cibuildwheel.linux
|
return cibuildwheel.linux
|
||||||
@@ -381,14 +380,13 @@ def print_preamble(platform: str, options: Options, identifiers: Sequence[str])
|
|||||||
|
|
||||||
print()
|
print()
|
||||||
print(f"Cache folder: {CIBW_CACHE_PATH}")
|
print(f"Cache folder: {CIBW_CACHE_PATH}")
|
||||||
|
print()
|
||||||
|
|
||||||
warnings = detect_warnings(options=options, identifiers=identifiers)
|
warnings = detect_warnings(options=options, identifiers=identifiers)
|
||||||
if warnings:
|
for warning in warnings:
|
||||||
print("\nWarnings:")
|
log.warning(warning)
|
||||||
for warning in warnings:
|
|
||||||
print(" " + warning)
|
|
||||||
|
|
||||||
print("\nHere we go!\n")
|
print("Here we go!\n")
|
||||||
|
|
||||||
|
|
||||||
def get_build_identifiers(
|
def get_build_identifiers(
|
||||||
@@ -403,6 +401,16 @@ def get_build_identifiers(
|
|||||||
def detect_warnings(*, options: Options, identifiers: Iterable[str]) -> list[str]:
|
def detect_warnings(*, options: Options, identifiers: Iterable[str]) -> list[str]:
|
||||||
warnings = []
|
warnings = []
|
||||||
|
|
||||||
|
python_version_deprecation = ((3, 11), 3)
|
||||||
|
if sys.version_info[:2] < python_version_deprecation[0]:
|
||||||
|
python_version = ".".join(map(str, python_version_deprecation[0]))
|
||||||
|
msg = (
|
||||||
|
f"cibuildwheel {python_version_deprecation[1]} will require Python {python_version}+, "
|
||||||
|
"please upgrade the Python version used to run cibuildwheel. "
|
||||||
|
"This does not affect the versions you can target when building wheels. See: https://cibuildwheel.pypa.io/en/stable/#what-does-it-do"
|
||||||
|
)
|
||||||
|
warnings.append(msg)
|
||||||
|
|
||||||
# warn about deprecated {python} and {pip}
|
# warn about deprecated {python} and {pip}
|
||||||
for option_name in ["test_command", "before_build"]:
|
for option_name in ["test_command", "before_build"]:
|
||||||
option_values = [getattr(options.build_options(i), option_name) for i in identifiers]
|
option_values = [getattr(options.build_options(i), option_name) for i in identifiers]
|
||||||
@@ -411,7 +419,7 @@ def detect_warnings(*, options: Options, identifiers: Iterable[str]) -> list[str
|
|||||||
# Reminder: in an f-string, double braces means literal single brace
|
# Reminder: in an f-string, double braces means literal single brace
|
||||||
msg = (
|
msg = (
|
||||||
f"{option_name}: '{{python}}' and '{{pip}}' are no longer needed, "
|
f"{option_name}: '{{python}}' and '{{pip}}' are no longer needed, "
|
||||||
"and will be removed in a future release. Simply use 'python' or 'pip' instead."
|
"and will be removed in cibuildwheel 3. Simply use 'python' or 'pip' instead."
|
||||||
)
|
)
|
||||||
warnings.append(msg)
|
warnings.append(msg)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ else:
|
|||||||
from typing import NotRequired, Self, assert_never
|
from typing import NotRequired, Self, assert_never
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
"assert_never",
|
|
||||||
"NotRequired",
|
"NotRequired",
|
||||||
"Self",
|
"Self",
|
||||||
|
"assert_never",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class Architecture(Enum):
|
|||||||
aarch64 = "aarch64"
|
aarch64 = "aarch64"
|
||||||
ppc64le = "ppc64le"
|
ppc64le = "ppc64le"
|
||||||
s390x = "s390x"
|
s390x = "s390x"
|
||||||
|
armv7l = "armv7l"
|
||||||
|
|
||||||
# mac archs
|
# mac archs
|
||||||
universal2 = "universal2"
|
universal2 = "universal2"
|
||||||
@@ -64,7 +65,9 @@ class Architecture(Enum):
|
|||||||
if arch_str == "auto":
|
if arch_str == "auto":
|
||||||
result |= Architecture.auto_archs(platform=platform)
|
result |= Architecture.auto_archs(platform=platform)
|
||||||
elif arch_str == "native":
|
elif arch_str == "native":
|
||||||
result.add(Architecture(platform_module.machine()))
|
native_arch = Architecture.native_arch(platform=platform)
|
||||||
|
if native_arch:
|
||||||
|
result.add(native_arch)
|
||||||
elif arch_str == "all":
|
elif arch_str == "all":
|
||||||
result |= Architecture.all_archs(platform=platform)
|
result |= Architecture.all_archs(platform=platform)
|
||||||
elif arch_str == "auto64":
|
elif arch_str == "auto64":
|
||||||
@@ -130,6 +133,7 @@ class Architecture(Enum):
|
|||||||
Architecture.aarch64,
|
Architecture.aarch64,
|
||||||
Architecture.ppc64le,
|
Architecture.ppc64le,
|
||||||
Architecture.s390x,
|
Architecture.s390x,
|
||||||
|
Architecture.armv7l,
|
||||||
},
|
},
|
||||||
"macos": {Architecture.x86_64, Architecture.arm64, Architecture.universal2},
|
"macos": {Architecture.x86_64, Architecture.arm64, Architecture.universal2},
|
||||||
"windows": {Architecture.x86, Architecture.AMD64, Architecture.ARM64},
|
"windows": {Architecture.x86, Architecture.AMD64, Architecture.ARM64},
|
||||||
@@ -138,17 +142,15 @@ class Architecture(Enum):
|
|||||||
return all_archs_map[platform]
|
return all_archs_map[platform]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
# pylint: disable-next=inconsistent-return-statements
|
|
||||||
def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> set[Architecture]:
|
def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> set[Architecture]:
|
||||||
archs_32 = {Architecture.i686, Architecture.x86}
|
archs_32 = {Architecture.i686, Architecture.x86, Architecture.armv7l}
|
||||||
auto_archs = Architecture.auto_archs(platform)
|
auto_archs = Architecture.auto_archs(platform)
|
||||||
|
|
||||||
if bitness == "64":
|
if bitness == "64":
|
||||||
return auto_archs - archs_32
|
return auto_archs - archs_32
|
||||||
elif bitness == "32":
|
if bitness == "32":
|
||||||
return auto_archs & archs_32
|
return auto_archs & archs_32
|
||||||
else:
|
assert_never(bitness)
|
||||||
assert_never(bitness)
|
|
||||||
|
|
||||||
|
|
||||||
def allowed_architectures_check(
|
def allowed_architectures_check(
|
||||||
|
|||||||
+31
-4
@@ -35,11 +35,14 @@ class NonPlatformWheelError(FatalError):
|
|||||||
"""
|
"""
|
||||||
Build failed because a pure Python wheel was generated.
|
Build failed because a pure Python wheel was generated.
|
||||||
|
|
||||||
If you intend to build a pure-Python wheel, you don't need cibuildwheel - use
|
If you intend to build a pure-Python wheel, you don't need
|
||||||
`pip wheel -w DEST_DIR .` instead.
|
cibuildwheel - use `pip wheel .`, `pipx run build --wheel`, `uv
|
||||||
|
build --wheel`, etc. instead. You only need cibuildwheel if you
|
||||||
|
have compiled (not Python) code in your wheels making them depend
|
||||||
|
on the platform.
|
||||||
|
|
||||||
If you expected a platform wheel, check your project configuration, or run
|
If you expected a platform wheel, check your project configuration,
|
||||||
cibuildwheel with CIBW_BUILD_VERBOSITY=1 to view build logs.
|
or run cibuildwheel with CIBW_BUILD_VERBOSITY=1 to view build logs.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
@@ -58,3 +61,27 @@ class AlreadyBuiltWheelError(FatalError):
|
|||||||
)
|
)
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
self.return_code = 6
|
self.return_code = 6
|
||||||
|
|
||||||
|
|
||||||
|
class OCIEngineTooOldError(FatalError):
|
||||||
|
def __init__(self, message: str) -> None:
|
||||||
|
super().__init__(message)
|
||||||
|
self.return_code = 7
|
||||||
|
|
||||||
|
|
||||||
|
class RepairStepProducedNoWheelError(FatalError):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
message = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
Build failed because the repair step completed successfully but
|
||||||
|
did not produce a wheel.
|
||||||
|
|
||||||
|
Your `repair-wheel-command` is expected to place the repaired
|
||||||
|
wheel in the {dest_dir} directory. See the documentation for
|
||||||
|
example configurations:
|
||||||
|
|
||||||
|
https://cibuildwheel.pypa.io/en/stable/options/#repair-wheel-command
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
super().__init__(message)
|
||||||
|
self.return_code = 8
|
||||||
|
|||||||
+39
-18
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import contextlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
@@ -14,7 +15,7 @@ from . import errors
|
|||||||
from ._compat.typing import assert_never
|
from ._compat.typing import assert_never
|
||||||
from .architecture import Architecture
|
from .architecture import Architecture
|
||||||
from .logger import log
|
from .logger import log
|
||||||
from .oci_container import OCIContainer, OCIContainerEngineConfig
|
from .oci_container import OCIContainer, OCIContainerEngineConfig, OCIPlatform
|
||||||
from .options import BuildOptions, Options
|
from .options import BuildOptions, Options
|
||||||
from .typing import PathOrStr
|
from .typing import PathOrStr
|
||||||
from .util import (
|
from .util import (
|
||||||
@@ -29,6 +30,15 @@ from .util import (
|
|||||||
unwrap,
|
unwrap,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ARCHITECTURE_OCI_PLATFORM_MAP = {
|
||||||
|
Architecture.x86_64: OCIPlatform.AMD64,
|
||||||
|
Architecture.i686: OCIPlatform.i386,
|
||||||
|
Architecture.aarch64: OCIPlatform.ARM64,
|
||||||
|
Architecture.ppc64le: OCIPlatform.PPC64LE,
|
||||||
|
Architecture.s390x: OCIPlatform.S390X,
|
||||||
|
Architecture.armv7l: OCIPlatform.ARMV7,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class PythonConfiguration:
|
class PythonConfiguration:
|
||||||
@@ -124,26 +134,33 @@ def check_all_python_exist(
|
|||||||
*, platform_configs: Iterable[PythonConfiguration], container: OCIContainer
|
*, platform_configs: Iterable[PythonConfiguration], container: OCIContainer
|
||||||
) -> None:
|
) -> None:
|
||||||
exist = True
|
exist = True
|
||||||
has_manylinux_interpreters = True
|
has_manylinux_interpreters = False
|
||||||
messages = []
|
messages = []
|
||||||
|
|
||||||
try:
|
with contextlib.suppress(subprocess.CalledProcessError):
|
||||||
# use capture_output to keep quiet
|
# use capture_output to keep quiet
|
||||||
container.call(["manylinux-interpreters", "--help"], capture_output=True)
|
container.call(["manylinux-interpreters", "--help"], capture_output=True)
|
||||||
except subprocess.CalledProcessError:
|
has_manylinux_interpreters = True
|
||||||
has_manylinux_interpreters = False
|
|
||||||
|
|
||||||
for config in platform_configs:
|
for config in platform_configs:
|
||||||
python_path = config.path / "bin" / "python"
|
python_path = config.path / "bin" / "python"
|
||||||
try:
|
if has_manylinux_interpreters:
|
||||||
if has_manylinux_interpreters:
|
try:
|
||||||
container.call(["manylinux-interpreters", "ensure", config.path.name])
|
container.call(["manylinux-interpreters", "ensure", config.path.name])
|
||||||
container.call(["test", "-x", python_path])
|
except subprocess.CalledProcessError:
|
||||||
except subprocess.CalledProcessError:
|
messages.append(
|
||||||
messages.append(
|
f" 'manylinux-interpreters ensure {config.path.name}' needed to build '{config.identifier}' failed in container running image '{container.image}'."
|
||||||
f" '{python_path}' executable doesn't exist in image '{container.image}' to build '{config.identifier}'."
|
" Either the installation failed or this interpreter is not available in that image. Please check the logs."
|
||||||
)
|
)
|
||||||
exist = False
|
exist = False
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
container.call(["test", "-x", python_path])
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
messages.append(
|
||||||
|
f" '{python_path}' executable doesn't exist in image '{container.image}' to build '{config.identifier}'."
|
||||||
|
)
|
||||||
|
exist = False
|
||||||
if not exist:
|
if not exist:
|
||||||
message = "\n".join(messages)
|
message = "\n".join(messages)
|
||||||
raise errors.FatalError(message)
|
raise errors.FatalError(message)
|
||||||
@@ -171,7 +188,7 @@ def build_in_container(
|
|||||||
log.step("Running before_all...")
|
log.step("Running before_all...")
|
||||||
|
|
||||||
env = container.get_environment()
|
env = container.get_environment()
|
||||||
env["PATH"] = f'/opt/python/cp38-cp38/bin:{env["PATH"]}'
|
env["PATH"] = f'/opt/python/cp39-cp39/bin:{env["PATH"]}'
|
||||||
env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1"
|
env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1"
|
||||||
env["PIP_ROOT_USER_ACTION"] = "ignore"
|
env["PIP_ROOT_USER_ACTION"] = "ignore"
|
||||||
env = before_all_options.environment.as_dictionary(
|
env = before_all_options.environment.as_dictionary(
|
||||||
@@ -196,6 +213,8 @@ def build_in_container(
|
|||||||
|
|
||||||
dependency_constraint_flags: list[PathOrStr] = []
|
dependency_constraint_flags: list[PathOrStr] = []
|
||||||
|
|
||||||
|
log.step("Setting up build environment...")
|
||||||
|
|
||||||
if build_options.dependency_constraints:
|
if build_options.dependency_constraints:
|
||||||
constraints_file = build_options.dependency_constraints.get_for_python_version(
|
constraints_file = build_options.dependency_constraints.get_for_python_version(
|
||||||
config.version
|
config.version
|
||||||
@@ -205,8 +224,6 @@ def build_in_container(
|
|||||||
container.copy_into(constraints_file, container_constraints_file)
|
container.copy_into(constraints_file, container_constraints_file)
|
||||||
dependency_constraint_flags = ["-c", container_constraints_file]
|
dependency_constraint_flags = ["-c", container_constraints_file]
|
||||||
|
|
||||||
log.step("Setting up build environment...")
|
|
||||||
|
|
||||||
env = container.get_environment()
|
env = container.get_environment()
|
||||||
env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1"
|
env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1"
|
||||||
env["PIP_ROOT_USER_ACTION"] = "ignore"
|
env["PIP_ROOT_USER_ACTION"] = "ignore"
|
||||||
@@ -317,6 +334,9 @@ def build_in_container(
|
|||||||
|
|
||||||
repaired_wheels = container.glob(repaired_wheel_dir, "*.whl")
|
repaired_wheels = container.glob(repaired_wheel_dir, "*.whl")
|
||||||
|
|
||||||
|
if not repaired_wheels:
|
||||||
|
raise errors.RepairStepProducedNoWheelError()
|
||||||
|
|
||||||
for repaired_wheel in repaired_wheels:
|
for repaired_wheel in repaired_wheels:
|
||||||
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
||||||
raise errors.AlreadyBuiltWheelError(repaired_wheel.name)
|
raise errors.AlreadyBuiltWheelError(repaired_wheel.name)
|
||||||
@@ -337,7 +357,7 @@ def build_in_container(
|
|||||||
venv_dir = testing_temp_dir / "venv"
|
venv_dir = testing_temp_dir / "venv"
|
||||||
|
|
||||||
if use_uv:
|
if use_uv:
|
||||||
container.call(["uv", "venv", venv_dir], env=env)
|
container.call(["uv", "venv", venv_dir, "--python", python_bin / "python"], env=env)
|
||||||
else:
|
else:
|
||||||
# Use embedded dependencies from virtualenv to ensure determinism
|
# Use embedded dependencies from virtualenv to ensure determinism
|
||||||
venv_args = ["--no-periodic-update", "--pip=embed"]
|
venv_args = ["--no-periodic-update", "--pip=embed"]
|
||||||
@@ -446,10 +466,11 @@ def build(options: Options, tmp_path: Path) -> None: # noqa: ARG001
|
|||||||
log.step(f"Starting container image {build_step.container_image}...")
|
log.step(f"Starting container image {build_step.container_image}...")
|
||||||
|
|
||||||
print(f"info: This container will host the build for {', '.join(ids_to_build)}...")
|
print(f"info: This container will host the build for {', '.join(ids_to_build)}...")
|
||||||
|
architecture = Architecture(build_step.platform_tag.split("_", 1)[1])
|
||||||
|
|
||||||
with OCIContainer(
|
with OCIContainer(
|
||||||
image=build_step.container_image,
|
image=build_step.container_image,
|
||||||
enforce_32_bit=build_step.platform_tag.endswith("i686"),
|
oci_platform=ARCHITECTURE_OCI_PLATFORM_MAP[architecture],
|
||||||
cwd=container_project_path,
|
cwd=container_project_path,
|
||||||
engine=build_step.container_engine,
|
engine=build_step.container_engine,
|
||||||
) as container:
|
) as container:
|
||||||
|
|||||||
@@ -23,11 +23,13 @@ PLATFORM_IDENTIFIER_DESCRIPTIONS: Final[dict[str, str]] = {
|
|||||||
"manylinux_aarch64": "manylinux aarch64",
|
"manylinux_aarch64": "manylinux aarch64",
|
||||||
"manylinux_ppc64le": "manylinux ppc64le",
|
"manylinux_ppc64le": "manylinux ppc64le",
|
||||||
"manylinux_s390x": "manylinux s390x",
|
"manylinux_s390x": "manylinux s390x",
|
||||||
|
"manylinux_armv7l": "manylinux armv7l",
|
||||||
"musllinux_x86_64": "musllinux x86_64",
|
"musllinux_x86_64": "musllinux x86_64",
|
||||||
"musllinux_i686": "musllinux i686",
|
"musllinux_i686": "musllinux i686",
|
||||||
"musllinux_aarch64": "musllinux aarch64",
|
"musllinux_aarch64": "musllinux aarch64",
|
||||||
"musllinux_ppc64le": "musllinux ppc64le",
|
"musllinux_ppc64le": "musllinux ppc64le",
|
||||||
"musllinux_s390x": "manylinux s390x",
|
"musllinux_s390x": "musllinux s390x",
|
||||||
|
"musllinux_armv7l": "musllinux armv7l",
|
||||||
"win32": "Windows 32bit",
|
"win32": "Windows 32bit",
|
||||||
"win_amd64": "Windows 64bit",
|
"win_amd64": "Windows 64bit",
|
||||||
"win_arm64": "Windows on ARM 64bit",
|
"win_arm64": "Windows on ARM 64bit",
|
||||||
|
|||||||
+36
-27
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
import inspect
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
@@ -149,11 +150,15 @@ def install_cpython(tmp: Path, version: str, url: str, free_threading: bool) ->
|
|||||||
if detect_ci_provider() is None:
|
if detect_ci_provider() is None:
|
||||||
# if running locally, we don't want to install CPython with sudo
|
# if running locally, we don't want to install CPython with sudo
|
||||||
# let the user know & provide a link to the installer
|
# let the user know & provide a link to the installer
|
||||||
msg = (
|
msg = inspect.cleandoc(
|
||||||
f"Error: CPython {version} is not installed.\n"
|
f"""
|
||||||
"cibuildwheel will not perform system-wide installs when running outside of CI.\n"
|
Error: CPython {version} is not installed.
|
||||||
f"To build locally, install CPython {version} on this machine, or, disable this version of Python using CIBW_SKIP=cp{version.replace('.', '')}-macosx_*\n"
|
cibuildwheel will not perform system-wide installs when running outside of CI.
|
||||||
f"\nDownload link: {url}"
|
To build locally, install CPython {version} on this machine, or, disable this
|
||||||
|
version of Python using CIBW_SKIP=cp{version.replace('.', '')}-macosx_*
|
||||||
|
For portable builds, cibuildwheel needs the official builds from python.org.
|
||||||
|
Download link: {url}
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
raise errors.FatalError(msg)
|
raise errors.FatalError(msg)
|
||||||
pkg_path = tmp / "Python.pkg"
|
pkg_path = tmp / "Python.pkg"
|
||||||
@@ -193,6 +198,11 @@ def install_pypy(tmp: Path, url: str) -> Path:
|
|||||||
return installation_path / "bin" / "pypy3"
|
return installation_path / "bin" / "pypy3"
|
||||||
|
|
||||||
|
|
||||||
|
def can_use_uv(python_configuration: PythonConfiguration) -> bool:
|
||||||
|
conditions = (Version(python_configuration.version) >= Version("3.8"),)
|
||||||
|
return all(conditions)
|
||||||
|
|
||||||
|
|
||||||
def setup_python(
|
def setup_python(
|
||||||
tmp: Path,
|
tmp: Path,
|
||||||
python_configuration: PythonConfiguration,
|
python_configuration: PythonConfiguration,
|
||||||
@@ -200,13 +210,11 @@ def setup_python(
|
|||||||
environment: ParsedEnvironment,
|
environment: ParsedEnvironment,
|
||||||
build_frontend: BuildFrontendName,
|
build_frontend: BuildFrontendName,
|
||||||
) -> tuple[Path, dict[str, str]]:
|
) -> tuple[Path, dict[str, str]]:
|
||||||
if build_frontend == "build[uv]" and Version(python_configuration.version) < Version("3.8"):
|
if build_frontend == "build[uv]" and not can_use_uv(python_configuration):
|
||||||
build_frontend = "build"
|
build_frontend = "build"
|
||||||
|
|
||||||
uv_path = find_uv()
|
uv_path = find_uv()
|
||||||
use_uv = build_frontend == "build[uv]" and Version(python_configuration.version) >= Version(
|
use_uv = build_frontend == "build[uv]"
|
||||||
"3.8"
|
|
||||||
)
|
|
||||||
|
|
||||||
tmp.mkdir()
|
tmp.mkdir()
|
||||||
implementation_id = python_configuration.identifier.split("-")[0]
|
implementation_id = python_configuration.identifier.split("-")[0]
|
||||||
@@ -270,23 +278,23 @@ def setup_python(
|
|||||||
# Apply our environment after pip is ready
|
# Apply our environment after pip is ready
|
||||||
env = environment.as_dictionary(prev_environment=env)
|
env = environment.as_dictionary(prev_environment=env)
|
||||||
|
|
||||||
# check what pip version we're on
|
|
||||||
if not use_uv:
|
|
||||||
assert (venv_bin_path / "pip").exists()
|
|
||||||
call("which", "pip", env=env)
|
|
||||||
call("pip", "--version", env=env)
|
|
||||||
which_pip = call("which", "pip", env=env, capture_stdout=True).strip()
|
|
||||||
if which_pip != str(venv_bin_path / "pip"):
|
|
||||||
msg = "cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it."
|
|
||||||
raise errors.FatalError(msg)
|
|
||||||
|
|
||||||
# check what Python version we're on
|
# check what Python version we're on
|
||||||
call("which", "python", env=env)
|
|
||||||
call("python", "--version", env=env)
|
|
||||||
which_python = call("which", "python", env=env, capture_stdout=True).strip()
|
which_python = call("which", "python", env=env, capture_stdout=True).strip()
|
||||||
|
print(which_python)
|
||||||
if which_python != str(venv_bin_path / "python"):
|
if which_python != str(venv_bin_path / "python"):
|
||||||
msg = "cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it."
|
msg = "cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it."
|
||||||
raise errors.FatalError(msg)
|
raise errors.FatalError(msg)
|
||||||
|
call("python", "--version", env=env)
|
||||||
|
|
||||||
|
# check what pip version we're on
|
||||||
|
if not use_uv:
|
||||||
|
assert (venv_bin_path / "pip").exists()
|
||||||
|
which_pip = call("which", "pip", env=env, capture_stdout=True).strip()
|
||||||
|
print(which_pip)
|
||||||
|
if which_pip != str(venv_bin_path / "pip"):
|
||||||
|
msg = "cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it."
|
||||||
|
raise errors.FatalError(msg)
|
||||||
|
call("pip", "--version", env=env)
|
||||||
|
|
||||||
config_is_arm64 = python_configuration.identifier.endswith("arm64")
|
config_is_arm64 = python_configuration.identifier.endswith("arm64")
|
||||||
config_is_universal2 = python_configuration.identifier.endswith("universal2")
|
config_is_universal2 = python_configuration.identifier.endswith("universal2")
|
||||||
@@ -294,10 +302,10 @@ def setup_python(
|
|||||||
# Set MACOSX_DEPLOYMENT_TARGET, if the user didn't set it.
|
# Set MACOSX_DEPLOYMENT_TARGET, if the user didn't set it.
|
||||||
# For arm64, the minimal deployment target is 11.0.
|
# For arm64, the minimal deployment target is 11.0.
|
||||||
# On x86_64 (or universal2), use 10.9 as a default.
|
# On x86_64 (or universal2), use 10.9 as a default.
|
||||||
# CPython 3.13 needs 10.13.
|
# CPython 3.12.6+ needs 10.13.
|
||||||
if config_is_arm64:
|
if config_is_arm64:
|
||||||
default_target = "11.0"
|
default_target = "11.0"
|
||||||
elif Version(python_configuration.version) >= Version("3.13"):
|
elif Version(python_configuration.version) >= Version("3.12"):
|
||||||
default_target = "10.13"
|
default_target = "10.13"
|
||||||
elif python_configuration.identifier.startswith("pp") and Version(
|
elif python_configuration.identifier.startswith("pp") and Version(
|
||||||
python_configuration.version
|
python_configuration.version
|
||||||
@@ -415,9 +423,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
for config in python_configurations:
|
for config in python_configurations:
|
||||||
build_options = options.build_options(config.identifier)
|
build_options = options.build_options(config.identifier)
|
||||||
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||||
use_uv = build_frontend.name == "build[uv]" and Version(config.version) >= Version(
|
use_uv = build_frontend.name == "build[uv]" and can_use_uv(config)
|
||||||
"3.8"
|
|
||||||
)
|
|
||||||
uv_path = find_uv()
|
uv_path = find_uv()
|
||||||
if use_uv and uv_path is None:
|
if use_uv and uv_path is None:
|
||||||
msg = "uv not found"
|
msg = "uv not found"
|
||||||
@@ -545,7 +551,10 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
else:
|
else:
|
||||||
shutil.move(str(built_wheel), repaired_wheel_dir)
|
shutil.move(str(built_wheel), repaired_wheel_dir)
|
||||||
|
|
||||||
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
|
try:
|
||||||
|
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
|
||||||
|
except StopIteration:
|
||||||
|
raise errors.RepairStepProducedNoWheelError() from None
|
||||||
|
|
||||||
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
||||||
raise errors.AlreadyBuiltWheelError(repaired_wheel.name)
|
raise errors.AlreadyBuiltWheelError(repaired_wheel.name)
|
||||||
|
|||||||
+132
-41
@@ -8,18 +8,23 @@ import shlex
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
import typing
|
import typing
|
||||||
import uuid
|
import uuid
|
||||||
from collections.abc import Mapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
from enum import Enum
|
||||||
from pathlib import Path, PurePath, PurePosixPath
|
from pathlib import Path, PurePath, PurePosixPath
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import IO, Dict, Literal
|
from typing import IO, Dict, Literal
|
||||||
|
|
||||||
from ._compat.typing import Self
|
from ._compat.typing import Self, assert_never
|
||||||
|
from .errors import OCIEngineTooOldError
|
||||||
|
from .logger import log
|
||||||
from .typing import PathOrStr, PopenBytes
|
from .typing import PathOrStr, PopenBytes
|
||||||
from .util import (
|
from .util import (
|
||||||
CIProvider,
|
CIProvider,
|
||||||
|
FlexibleVersion,
|
||||||
call,
|
call,
|
||||||
detect_ci_provider,
|
detect_ci_provider,
|
||||||
parse_key_value_string,
|
parse_key_value_string,
|
||||||
@@ -29,6 +34,16 @@ from .util import (
|
|||||||
ContainerEngineName = Literal["docker", "podman"]
|
ContainerEngineName = Literal["docker", "podman"]
|
||||||
|
|
||||||
|
|
||||||
|
# Order of the enum matters for tests. 386 shall appear before amd64.
|
||||||
|
class OCIPlatform(Enum):
|
||||||
|
i386 = "linux/386"
|
||||||
|
AMD64 = "linux/amd64"
|
||||||
|
ARMV7 = "linux/arm/v7"
|
||||||
|
ARM64 = "linux/arm64"
|
||||||
|
PPC64LE = "linux/ppc64le"
|
||||||
|
S390X = "linux/s390x"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class OCIContainerEngineConfig:
|
class OCIContainerEngineConfig:
|
||||||
name: ContainerEngineName
|
name: ContainerEngineName
|
||||||
@@ -56,6 +71,15 @@ class OCIContainerEngineConfig:
|
|||||||
disable_host_mount = (
|
disable_host_mount = (
|
||||||
strtobool(disable_host_mount_options[-1]) if disable_host_mount_options else False
|
strtobool(disable_host_mount_options[-1]) if disable_host_mount_options else False
|
||||||
)
|
)
|
||||||
|
if "--platform" in create_args or any(arg.startswith("--platform=") for arg in create_args):
|
||||||
|
msg = "Using '--platform' in 'container-engine::create_args' is deprecated. It will be ignored."
|
||||||
|
log.warning(msg)
|
||||||
|
if "--platform" in create_args:
|
||||||
|
index = create_args.index("--platform")
|
||||||
|
create_args.pop(index)
|
||||||
|
create_args.pop(index)
|
||||||
|
else:
|
||||||
|
create_args = [arg for arg in create_args if not arg.startswith("--platform=")]
|
||||||
|
|
||||||
return OCIContainerEngineConfig(
|
return OCIContainerEngineConfig(
|
||||||
name=name, create_args=tuple(create_args), disable_host_mount=disable_host_mount
|
name=name, create_args=tuple(create_args), disable_host_mount=disable_host_mount
|
||||||
@@ -75,6 +99,52 @@ class OCIContainerEngineConfig:
|
|||||||
DEFAULT_ENGINE = OCIContainerEngineConfig("docker")
|
DEFAULT_ENGINE = OCIContainerEngineConfig("docker")
|
||||||
|
|
||||||
|
|
||||||
|
def _check_engine_version(engine: OCIContainerEngineConfig) -> None:
|
||||||
|
try:
|
||||||
|
version_string = call(engine.name, "version", "-f", "{{json .}}", capture_stdout=True)
|
||||||
|
version_info = json.loads(version_string.strip())
|
||||||
|
if engine.name == "docker":
|
||||||
|
client_api_version = FlexibleVersion(version_info["Client"]["ApiVersion"])
|
||||||
|
server_api_version = FlexibleVersion(version_info["Server"]["ApiVersion"])
|
||||||
|
# --platform support was introduced in 1.32 as experimental, 1.41 removed the experimental flag
|
||||||
|
version = min(client_api_version, server_api_version)
|
||||||
|
minimum_version = FlexibleVersion("1.41")
|
||||||
|
minimum_version_str = "20.10.0" # docker version
|
||||||
|
error_msg = textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
Build failed because {engine.name} is too old.
|
||||||
|
|
||||||
|
cibuildwheel requires {engine.name}>={minimum_version_str} running API version {minimum_version}.
|
||||||
|
The API version found by cibuildwheel is {version}.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
elif engine.name == "podman":
|
||||||
|
# podman uses the same version string for "Version" & "ApiVersion"
|
||||||
|
client_version = FlexibleVersion(version_info["Client"]["Version"])
|
||||||
|
if "Server" in version_info:
|
||||||
|
server_version = FlexibleVersion(version_info["Server"]["Version"])
|
||||||
|
else:
|
||||||
|
server_version = client_version
|
||||||
|
# --platform support was introduced in v3
|
||||||
|
version = min(client_version, server_version)
|
||||||
|
minimum_version = FlexibleVersion("3")
|
||||||
|
error_msg = textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
Build failed because {engine.name} is too old.
|
||||||
|
|
||||||
|
cibuildwheel requires {engine.name}>={minimum_version}.
|
||||||
|
The version found by cibuildwheel is {version}.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert_never(engine.name)
|
||||||
|
if version < minimum_version:
|
||||||
|
raise OCIEngineTooOldError(error_msg) from None
|
||||||
|
except (subprocess.CalledProcessError, KeyError, ValueError) as e:
|
||||||
|
msg = f"Build failed because {engine.name} is too old or is not working properly."
|
||||||
|
raise OCIEngineTooOldError(msg) from e
|
||||||
|
|
||||||
|
|
||||||
class OCIContainer:
|
class OCIContainer:
|
||||||
"""
|
"""
|
||||||
An object that represents a running OCI (e.g. Docker) container.
|
An object that represents a running OCI (e.g. Docker) container.
|
||||||
@@ -98,7 +168,7 @@ class OCIContainer:
|
|||||||
... print(self.debug_info())
|
... print(self.debug_info())
|
||||||
"""
|
"""
|
||||||
|
|
||||||
UTILITY_PYTHON = "/opt/python/cp38-cp38/bin/python"
|
UTILITY_PYTHON = "/opt/python/cp39-cp39/bin/python"
|
||||||
|
|
||||||
process: PopenBytes
|
process: PopenBytes
|
||||||
bash_stdin: IO[bytes]
|
bash_stdin: IO[bytes]
|
||||||
@@ -108,7 +178,7 @@ class OCIContainer:
|
|||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
image: str,
|
image: str,
|
||||||
enforce_32_bit: bool = False,
|
oci_platform: OCIPlatform,
|
||||||
cwd: PathOrStr | None = None,
|
cwd: PathOrStr | None = None,
|
||||||
engine: OCIContainerEngineConfig = DEFAULT_ENGINE,
|
engine: OCIContainerEngineConfig = DEFAULT_ENGINE,
|
||||||
):
|
):
|
||||||
@@ -117,14 +187,48 @@ class OCIContainer:
|
|||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
self.image = image
|
self.image = image
|
||||||
self.enforce_32_bit = enforce_32_bit
|
self.oci_platform = oci_platform
|
||||||
self.cwd = cwd
|
self.cwd = cwd
|
||||||
self.name: str | None = None
|
self.name: str | None = None
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
|
self.host_tar_format = ""
|
||||||
|
if sys.platform.startswith("darwin"):
|
||||||
|
self.host_tar_format = "--format gnutar"
|
||||||
|
|
||||||
|
def _get_platform_args(self, *, oci_platform: OCIPlatform | None = None) -> tuple[str, str]:
|
||||||
|
if oci_platform is None:
|
||||||
|
oci_platform = self.oci_platform
|
||||||
|
|
||||||
|
# we need '--pull=always' otherwise some images with the wrong platform get re-used (e.g. 386 image for amd64)
|
||||||
|
# c.f. https://github.com/moby/moby/issues/48197#issuecomment-2282802313
|
||||||
|
pull = "always"
|
||||||
|
try:
|
||||||
|
image_platform = call(
|
||||||
|
self.engine.name,
|
||||||
|
"image",
|
||||||
|
"inspect",
|
||||||
|
self.image,
|
||||||
|
"--format",
|
||||||
|
(
|
||||||
|
"{{.Os}}/{{.Architecture}}/{{.Variant}}"
|
||||||
|
if len(oci_platform.value.split("/")) == 3
|
||||||
|
else "{{.Os}}/{{.Architecture}}"
|
||||||
|
),
|
||||||
|
capture_stdout=True,
|
||||||
|
).strip()
|
||||||
|
if image_platform == oci_platform.value:
|
||||||
|
# in case the correct image is already present, don't pull
|
||||||
|
# this allows to run local only images
|
||||||
|
pull = "never"
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
pass
|
||||||
|
return f"--platform={oci_platform.value}", f"--pull={pull}"
|
||||||
|
|
||||||
def __enter__(self) -> Self:
|
def __enter__(self) -> Self:
|
||||||
self.name = f"cibuildwheel-{uuid.uuid4()}"
|
self.name = f"cibuildwheel-{uuid.uuid4()}"
|
||||||
|
|
||||||
|
_check_engine_version(self.engine)
|
||||||
|
|
||||||
# work-around for Travis-CI PPC64le Docker runs since 2021:
|
# work-around for Travis-CI PPC64le Docker runs since 2021:
|
||||||
# this avoids network splits
|
# this avoids network splits
|
||||||
# https://github.com/pypa/cibuildwheel/issues/904
|
# https://github.com/pypa/cibuildwheel/issues/904
|
||||||
@@ -133,15 +237,30 @@ class OCIContainer:
|
|||||||
if detect_ci_provider() == CIProvider.travis_ci and platform.machine() == "ppc64le":
|
if detect_ci_provider() == CIProvider.travis_ci and platform.machine() == "ppc64le":
|
||||||
network_args = ["--network=host"]
|
network_args = ["--network=host"]
|
||||||
|
|
||||||
|
platform_args = self._get_platform_args()
|
||||||
|
|
||||||
simulate_32_bit = False
|
simulate_32_bit = False
|
||||||
if self.enforce_32_bit:
|
if self.oci_platform in {OCIPlatform.i386, OCIPlatform.ARMV7}:
|
||||||
# If the architecture running the image is already the right one
|
# 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
|
# or the image entrypoint takes care of enforcing this, then we don't need to
|
||||||
# simulate this
|
# simulate this
|
||||||
container_machine = call(
|
run_cmd = [self.engine.name, "run", "--rm"]
|
||||||
self.engine.name, "run", "--rm", self.image, "uname", "-m", capture_stdout=True
|
ctr_cmd = ["uname", "-m"]
|
||||||
).strip()
|
try:
|
||||||
simulate_32_bit = container_machine != "i686"
|
container_machine = call(
|
||||||
|
*run_cmd, *platform_args, self.image, *ctr_cmd, capture_stdout=True
|
||||||
|
).strip()
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
if self.oci_platform == OCIPlatform.i386:
|
||||||
|
# The image might have been built with amd64 architecture
|
||||||
|
# Let's try that
|
||||||
|
platform_args = self._get_platform_args(oci_platform=OCIPlatform.AMD64)
|
||||||
|
container_machine = call(
|
||||||
|
*run_cmd, *platform_args, self.image, *ctr_cmd, capture_stdout=True
|
||||||
|
).strip()
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
simulate_32_bit = container_machine not in {"i686", "armv7l", "armv8l"}
|
||||||
|
|
||||||
shell_args = ["linux32", "/bin/bash"] if simulate_32_bit else ["/bin/bash"]
|
shell_args = ["linux32", "/bin/bash"] if simulate_32_bit else ["/bin/bash"]
|
||||||
|
|
||||||
@@ -155,6 +274,7 @@ class OCIContainer:
|
|||||||
"--interactive",
|
"--interactive",
|
||||||
*(["--volume=/:/host"] if not self.engine.disable_host_mount else []),
|
*(["--volume=/:/host"] if not self.engine.disable_host_mount else []),
|
||||||
*network_args,
|
*network_args,
|
||||||
|
*platform_args,
|
||||||
*self.engine.create_args,
|
*self.engine.create_args,
|
||||||
self.image,
|
self.image,
|
||||||
*shell_args,
|
*shell_args,
|
||||||
@@ -221,15 +341,10 @@ class OCIContainer:
|
|||||||
self.name = None
|
self.name = None
|
||||||
|
|
||||||
def copy_into(self, from_path: Path, to_path: PurePath) -> None:
|
def copy_into(self, from_path: Path, to_path: PurePath) -> None:
|
||||||
# `docker cp` causes 'no space left on device' error when
|
|
||||||
# a container is running and the host filesystem is
|
|
||||||
# mounted. https://github.com/moby/moby/issues/38995
|
|
||||||
# Use `docker exec` instead.
|
|
||||||
|
|
||||||
if from_path.is_dir():
|
if from_path.is_dir():
|
||||||
self.call(["mkdir", "-p", to_path])
|
self.call(["mkdir", "-p", to_path])
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
f"tar cf - . | {self.engine.name} exec -i {self.name} tar --no-same-owner -xC {shell_quote(to_path)} -f -",
|
f"tar -c {self.host_tar_format} -f - . | {self.engine.name} exec -i {self.name} tar --no-same-owner -xC {shell_quote(to_path)} -f -",
|
||||||
shell=True,
|
shell=True,
|
||||||
check=True,
|
check=True,
|
||||||
cwd=from_path,
|
cwd=from_path,
|
||||||
@@ -250,8 +365,7 @@ class OCIContainer:
|
|||||||
) as exec_process:
|
) as exec_process:
|
||||||
assert exec_process.stdin
|
assert exec_process.stdin
|
||||||
with open(from_path, "rb") as from_file:
|
with open(from_path, "rb") as from_file:
|
||||||
# Bug in mypy, https://github.com/python/mypy/issues/15031
|
shutil.copyfileobj(from_file, exec_process.stdin)
|
||||||
shutil.copyfileobj(from_file, exec_process.stdin) # type: ignore[misc]
|
|
||||||
|
|
||||||
exec_process.stdin.close()
|
exec_process.stdin.close()
|
||||||
exec_process.wait()
|
exec_process.wait()
|
||||||
@@ -264,30 +378,7 @@ class OCIContainer:
|
|||||||
def copy_out(self, from_path: PurePath, to_path: Path) -> None:
|
def copy_out(self, from_path: PurePath, to_path: Path) -> None:
|
||||||
# note: we assume from_path is a dir
|
# note: we assume from_path is a dir
|
||||||
to_path.mkdir(parents=True, exist_ok=True)
|
to_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
call(self.engine.name, "cp", f"{self.name}:{from_path}/.", to_path)
|
||||||
if self.engine.name == "podman":
|
|
||||||
subprocess.run(
|
|
||||||
[
|
|
||||||
self.engine.name,
|
|
||||||
"cp",
|
|
||||||
f"{self.name}:{from_path}/.",
|
|
||||||
str(to_path),
|
|
||||||
],
|
|
||||||
check=True,
|
|
||||||
cwd=to_path,
|
|
||||||
)
|
|
||||||
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.name} exec -i {self.name} tar -cC {shell_quote(from_path)} -f - . | tar -xf -"
|
|
||||||
subprocess.run(
|
|
||||||
command,
|
|
||||||
shell=True,
|
|
||||||
check=True,
|
|
||||||
cwd=to_path,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
raise KeyError(self.engine.name)
|
|
||||||
|
|
||||||
def glob(self, path: PurePosixPath, pattern: str) -> list[PurePosixPath]:
|
def glob(self, path: PurePosixPath, pattern: str) -> list[PurePosixPath]:
|
||||||
glob_pattern = path.joinpath(pattern)
|
glob_pattern = path.joinpath(pattern)
|
||||||
|
|||||||
+86
-21
@@ -22,7 +22,7 @@ from .architecture import Architecture
|
|||||||
from .environment import EnvironmentParseError, ParsedEnvironment, parse_environment
|
from .environment import EnvironmentParseError, ParsedEnvironment, parse_environment
|
||||||
from .logger import log
|
from .logger import log
|
||||||
from .oci_container import OCIContainerEngineConfig
|
from .oci_container import OCIContainerEngineConfig
|
||||||
from .projectfiles import get_requires_python_str
|
from .projectfiles import get_requires_python_str, resolve_dependency_groups
|
||||||
from .typing import PLATFORMS, PlatformName
|
from .typing import PLATFORMS, PlatformName
|
||||||
from .util import (
|
from .util import (
|
||||||
MANYLINUX_ARCHS,
|
MANYLINUX_ARCHS,
|
||||||
@@ -30,8 +30,10 @@ from .util import (
|
|||||||
BuildFrontendConfig,
|
BuildFrontendConfig,
|
||||||
BuildSelector,
|
BuildSelector,
|
||||||
DependencyConstraints,
|
DependencyConstraints,
|
||||||
|
EnableGroups,
|
||||||
TestSelector,
|
TestSelector,
|
||||||
format_safe,
|
format_safe,
|
||||||
|
read_python_configs,
|
||||||
resources_dir,
|
resources_dir,
|
||||||
selector_matches,
|
selector_matches,
|
||||||
strtobool,
|
strtobool,
|
||||||
@@ -92,6 +94,7 @@ class BuildOptions:
|
|||||||
before_test: str | None
|
before_test: str | None
|
||||||
test_requires: list[str]
|
test_requires: list[str]
|
||||||
test_extras: str
|
test_extras: str
|
||||||
|
test_groups: list[str]
|
||||||
build_verbosity: int
|
build_verbosity: int
|
||||||
build_frontend: BuildFrontendConfig | None
|
build_frontend: BuildFrontendConfig | None
|
||||||
config_settings: str
|
config_settings: str
|
||||||
@@ -307,7 +310,6 @@ def _resolve_cascade(
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable-next=inconsistent-return-statements
|
|
||||||
def _apply_inherit_rule(
|
def _apply_inherit_rule(
|
||||||
before: str | None, after: str, rule: InheritRule, option_format: OptionFormat | None
|
before: str | None, after: str, rule: InheritRule, option_format: OptionFormat | None
|
||||||
) -> str:
|
) -> str:
|
||||||
@@ -329,10 +331,10 @@ def _apply_inherit_rule(
|
|||||||
|
|
||||||
if rule == InheritRule.APPEND:
|
if rule == InheritRule.APPEND:
|
||||||
return option_format.merge_values(before, after)
|
return option_format.merge_values(before, after)
|
||||||
elif rule == InheritRule.PREPEND:
|
if rule == InheritRule.PREPEND:
|
||||||
return option_format.merge_values(after, before)
|
return option_format.merge_values(after, before)
|
||||||
else:
|
|
||||||
assert_never(rule)
|
assert_never(rule)
|
||||||
|
|
||||||
|
|
||||||
def _stringify_setting(
|
def _stringify_setting(
|
||||||
@@ -512,6 +514,7 @@ class OptionsReader:
|
|||||||
env_plat: bool = True,
|
env_plat: bool = True,
|
||||||
option_format: OptionFormat | None = None,
|
option_format: OptionFormat | None = None,
|
||||||
ignore_empty: bool = False,
|
ignore_empty: bool = False,
|
||||||
|
env_rule: InheritRule = InheritRule.NONE,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Get and return the value for the named option from environment,
|
Get and return the value for the named option from environment,
|
||||||
@@ -543,33 +546,44 @@ class OptionsReader:
|
|||||||
(o.options.get(name), o.inherit.get(name, InheritRule.NONE))
|
(o.options.get(name), o.inherit.get(name, InheritRule.NONE))
|
||||||
for o in self.active_config_overrides
|
for o in self.active_config_overrides
|
||||||
],
|
],
|
||||||
(self.env.get(envvar), InheritRule.NONE),
|
(self.env.get(envvar), env_rule),
|
||||||
(self.env.get(plat_envvar) if env_plat else None, InheritRule.NONE),
|
(self.env.get(plat_envvar) if env_plat else None, env_rule),
|
||||||
ignore_empty=ignore_empty,
|
ignore_empty=ignore_empty,
|
||||||
option_format=option_format,
|
option_format=option_format,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Options:
|
class Options:
|
||||||
|
pyproject_toml: dict[str, Any] | None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
platform: PlatformName,
|
platform: PlatformName,
|
||||||
command_line_arguments: CommandLineArguments,
|
command_line_arguments: CommandLineArguments,
|
||||||
env: Mapping[str, str],
|
env: Mapping[str, str],
|
||||||
read_config_file: bool = True,
|
defaults: bool = False,
|
||||||
):
|
):
|
||||||
self.platform = platform
|
self.platform = platform
|
||||||
self.command_line_arguments = command_line_arguments
|
self.command_line_arguments = command_line_arguments
|
||||||
self.env = env
|
self.env = env
|
||||||
|
self._defaults = defaults
|
||||||
|
self._image_warnings: set[str] = set()
|
||||||
|
|
||||||
self.reader = OptionsReader(
|
self.reader = OptionsReader(
|
||||||
self.config_file_path if read_config_file else None,
|
None if defaults else self.config_file_path,
|
||||||
platform=platform,
|
platform=platform,
|
||||||
env=env,
|
env=env,
|
||||||
disallow=DISALLOWED_OPTIONS,
|
disallow=DISALLOWED_OPTIONS,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
self.package_dir = Path(command_line_arguments.package_dir)
|
||||||
|
try:
|
||||||
|
with self.package_dir.joinpath("pyproject.toml").open("rb") as f:
|
||||||
|
self.pyproject_toml = tomllib.load(f)
|
||||||
|
except FileNotFoundError:
|
||||||
|
self.pyproject_toml = None
|
||||||
|
|
||||||
|
@functools.cached_property
|
||||||
def config_file_path(self) -> Path | None:
|
def config_file_path(self) -> Path | None:
|
||||||
args = self.command_line_arguments
|
args = self.command_line_arguments
|
||||||
|
|
||||||
@@ -585,10 +599,9 @@ class Options:
|
|||||||
|
|
||||||
@functools.cached_property
|
@functools.cached_property
|
||||||
def package_requires_python_str(self) -> str | None:
|
def package_requires_python_str(self) -> str | None:
|
||||||
args = self.command_line_arguments
|
return get_requires_python_str(self.package_dir, self.pyproject_toml)
|
||||||
return get_requires_python_str(Path(args.package_dir))
|
|
||||||
|
|
||||||
@property
|
@functools.cached_property
|
||||||
def globals(self) -> GlobalOptions:
|
def globals(self) -> GlobalOptions:
|
||||||
args = self.command_line_arguments
|
args = self.command_line_arguments
|
||||||
package_dir = args.package_dir
|
package_dir = args.package_dir
|
||||||
@@ -600,16 +613,34 @@ class Options:
|
|||||||
skip_config = self.reader.get("skip", env_plat=False, option_format=ListFormat(sep=" "))
|
skip_config = self.reader.get("skip", env_plat=False, option_format=ListFormat(sep=" "))
|
||||||
test_skip = self.reader.get("test-skip", env_plat=False, option_format=ListFormat(sep=" "))
|
test_skip = self.reader.get("test-skip", env_plat=False, option_format=ListFormat(sep=" "))
|
||||||
|
|
||||||
|
allow_empty = args.allow_empty or strtobool(self.env.get("CIBW_ALLOW_EMPTY", "0"))
|
||||||
|
|
||||||
|
enable_groups = self.reader.get(
|
||||||
|
"enable", env_plat=False, option_format=ListFormat(sep=" "), env_rule=InheritRule.APPEND
|
||||||
|
)
|
||||||
|
enable = {EnableGroups(group) for group in enable_groups.split()}
|
||||||
|
|
||||||
free_threaded_support = strtobool(
|
free_threaded_support = strtobool(
|
||||||
self.reader.get("free-threaded-support", env_plat=False, ignore_empty=True)
|
self.reader.get("free-threaded-support", env_plat=False, ignore_empty=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
allow_empty = args.allow_empty or strtobool(self.env.get("CIBW_ALLOW_EMPTY", "0"))
|
|
||||||
|
|
||||||
prerelease_pythons = args.prerelease_pythons or strtobool(
|
prerelease_pythons = args.prerelease_pythons or strtobool(
|
||||||
self.env.get("CIBW_PRERELEASE_PYTHONS", "0")
|
self.env.get("CIBW_PRERELEASE_PYTHONS", "0")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if free_threaded_support or prerelease_pythons:
|
||||||
|
msg = (
|
||||||
|
"free-threaded-support and prerelease-pythons should be specified by enable instead"
|
||||||
|
)
|
||||||
|
if enable:
|
||||||
|
raise OptionsReaderError(msg)
|
||||||
|
log.warning(msg)
|
||||||
|
|
||||||
|
if free_threaded_support:
|
||||||
|
enable.add(EnableGroups.CPythonFreeThreading)
|
||||||
|
if prerelease_pythons:
|
||||||
|
enable.add(EnableGroups.CPythonPrerelease)
|
||||||
|
|
||||||
# This is not supported in tool.cibuildwheel, as it comes from a standard location.
|
# This is not supported in tool.cibuildwheel, as it comes from a standard location.
|
||||||
# Passing this in as an environment variable will override pyproject.toml, setup.cfg, or setup.py
|
# Passing this in as an environment variable will override pyproject.toml, setup.cfg, or setup.py
|
||||||
requires_python_str: str | None = (
|
requires_python_str: str | None = (
|
||||||
@@ -625,18 +656,30 @@ class Options:
|
|||||||
build_config = args.only
|
build_config = args.only
|
||||||
skip_config = ""
|
skip_config = ""
|
||||||
architectures = Architecture.all_archs(self.platform)
|
architectures = Architecture.all_archs(self.platform)
|
||||||
prerelease_pythons = True
|
enable = set(EnableGroups)
|
||||||
free_threaded_support = True
|
|
||||||
|
|
||||||
build_selector = BuildSelector(
|
build_selector = BuildSelector(
|
||||||
build_config=build_config,
|
build_config=build_config,
|
||||||
skip_config=skip_config,
|
skip_config=skip_config,
|
||||||
requires_python=requires_python,
|
requires_python=requires_python,
|
||||||
prerelease_pythons=prerelease_pythons,
|
enable=frozenset(
|
||||||
free_threaded_support=free_threaded_support,
|
enable | {EnableGroups.PyPy}
|
||||||
|
), # For backwards compatibility, we are adding PyPy for now
|
||||||
)
|
)
|
||||||
test_selector = TestSelector(skip_config=test_skip)
|
test_selector = TestSelector(skip_config=test_skip)
|
||||||
|
|
||||||
|
all_configs = read_python_configs(self.platform)
|
||||||
|
all_pypy_ids = {
|
||||||
|
config["identifier"] for config in all_configs if config["identifier"].startswith("pp")
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
not self._defaults
|
||||||
|
and EnableGroups.PyPy not in enable
|
||||||
|
and any(build_selector(build_id) for build_id in all_pypy_ids)
|
||||||
|
):
|
||||||
|
msg = "PyPy builds will be disabled by default in version 3. Enabling PyPy builds should be specified by enable"
|
||||||
|
log.warning(msg)
|
||||||
|
|
||||||
return GlobalOptions(
|
return GlobalOptions(
|
||||||
package_dir=package_dir,
|
package_dir=package_dir,
|
||||||
output_dir=output_dir,
|
output_dir=output_dir,
|
||||||
@@ -646,6 +689,20 @@ class Options:
|
|||||||
allow_empty=allow_empty,
|
allow_empty=allow_empty,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _check_pinned_image(self, value: str, pinned_images: Mapping[str, str]) -> None:
|
||||||
|
if (
|
||||||
|
value in {"manylinux1", "manylinux2010", "manylinux_2_24", "musllinux_1_1"}
|
||||||
|
and value not in self._image_warnings
|
||||||
|
):
|
||||||
|
self._image_warnings.add(value)
|
||||||
|
msg = (
|
||||||
|
f"Deprecated image {value!r}. This value will not work"
|
||||||
|
" in a future version of cibuildwheel. Either upgrade to a supported"
|
||||||
|
" image or continue using the deprecated image by pinning directly"
|
||||||
|
f" to {pinned_images[value]!r}."
|
||||||
|
)
|
||||||
|
log.warning(msg)
|
||||||
|
|
||||||
def build_options(self, identifier: str | None) -> BuildOptions:
|
def build_options(self, identifier: str | None) -> BuildOptions:
|
||||||
"""
|
"""
|
||||||
Compute BuildOptions for a single run configuration.
|
Compute BuildOptions for a single run configuration.
|
||||||
@@ -673,6 +730,11 @@ class Options:
|
|||||||
"test-requires", option_format=ListFormat(sep=" ")
|
"test-requires", option_format=ListFormat(sep=" ")
|
||||||
).split()
|
).split()
|
||||||
test_extras = self.reader.get("test-extras", option_format=ListFormat(sep=","))
|
test_extras = self.reader.get("test-extras", option_format=ListFormat(sep=","))
|
||||||
|
test_groups_str = self.reader.get("test-groups", option_format=ListFormat(sep=" "))
|
||||||
|
test_groups = [x for x in test_groups_str.split() if x]
|
||||||
|
test_requirements_from_groups = resolve_dependency_groups(
|
||||||
|
self.pyproject_toml, *test_groups
|
||||||
|
)
|
||||||
build_verbosity_str = self.reader.get("build-verbosity")
|
build_verbosity_str = self.reader.get("build-verbosity")
|
||||||
|
|
||||||
build_frontend_str = self.reader.get(
|
build_frontend_str = self.reader.get(
|
||||||
@@ -738,6 +800,7 @@ class Options:
|
|||||||
# default to manylinux2014
|
# default to manylinux2014
|
||||||
image = pinned_images["manylinux2014"]
|
image = pinned_images["manylinux2014"]
|
||||||
elif config_value in pinned_images:
|
elif config_value in pinned_images:
|
||||||
|
self._check_pinned_image(config_value, pinned_images)
|
||||||
image = pinned_images[config_value]
|
image = pinned_images[config_value]
|
||||||
else:
|
else:
|
||||||
image = config_value
|
image = config_value
|
||||||
@@ -752,6 +815,7 @@ class Options:
|
|||||||
if not config_value:
|
if not config_value:
|
||||||
image = pinned_images["musllinux_1_2"]
|
image = pinned_images["musllinux_1_2"]
|
||||||
elif config_value in pinned_images:
|
elif config_value in pinned_images:
|
||||||
|
self._check_pinned_image(config_value, pinned_images)
|
||||||
image = pinned_images[config_value]
|
image = pinned_images[config_value]
|
||||||
else:
|
else:
|
||||||
image = config_value
|
image = config_value
|
||||||
@@ -772,8 +836,9 @@ class Options:
|
|||||||
return BuildOptions(
|
return BuildOptions(
|
||||||
globals=self.globals,
|
globals=self.globals,
|
||||||
test_command=test_command,
|
test_command=test_command,
|
||||||
test_requires=test_requires,
|
test_requires=[*test_requires, *test_requirements_from_groups],
|
||||||
test_extras=test_extras,
|
test_extras=test_extras,
|
||||||
|
test_groups=test_groups,
|
||||||
before_test=before_test,
|
before_test=before_test,
|
||||||
before_build=before_build,
|
before_build=before_build,
|
||||||
before_all=before_all,
|
before_all=before_all,
|
||||||
@@ -817,7 +882,7 @@ class Options:
|
|||||||
platform=self.platform,
|
platform=self.platform,
|
||||||
command_line_arguments=CommandLineArguments.defaults(),
|
command_line_arguments=CommandLineArguments.defaults(),
|
||||||
env={},
|
env={},
|
||||||
read_config_file=False,
|
defaults=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def summary(self, identifiers: Iterable[str]) -> str:
|
def summary(self, identifiers: Iterable[str]) -> str:
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import ast
|
|||||||
import configparser
|
import configparser
|
||||||
import contextlib
|
import contextlib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from ._compat import tomllib
|
import dependency_groups
|
||||||
|
|
||||||
|
|
||||||
def get_parent(node: ast.AST | None, depth: int = 1) -> ast.AST | None:
|
def get_parent(node: ast.AST | None, depth: int = 1) -> ast.AST | None:
|
||||||
@@ -84,15 +85,12 @@ def setup_py_python_requires(content: str) -> str | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_requires_python_str(package_dir: Path) -> str | None:
|
def get_requires_python_str(package_dir: Path, pyproject_toml: dict[str, Any] | None) -> str | None:
|
||||||
"""Return the python requires string from the most canonical source available, or None"""
|
"""Return the python requires string from the most canonical source available, or None"""
|
||||||
|
|
||||||
# Read in from pyproject.toml:project.requires-python
|
# Read in from pyproject.toml:project.requires-python
|
||||||
with contextlib.suppress(FileNotFoundError):
|
with contextlib.suppress(KeyError, IndexError, TypeError):
|
||||||
with (package_dir / "pyproject.toml").open("rb") as f1:
|
return str((pyproject_toml or {})["project"]["requires-python"])
|
||||||
info = tomllib.load(f1)
|
|
||||||
with contextlib.suppress(KeyError, IndexError, TypeError):
|
|
||||||
return str(info["project"]["requires-python"])
|
|
||||||
|
|
||||||
# Read in from setup.cfg:options.python_requires
|
# Read in from setup.cfg:options.python_requires
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
@@ -106,3 +104,26 @@ def get_requires_python_str(package_dir: Path) -> str | None:
|
|||||||
return setup_py_python_requires(f2.read())
|
return setup_py_python_requires(f2.read())
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_dependency_groups(
|
||||||
|
pyproject_toml: dict[str, Any] | None, *groups: str
|
||||||
|
) -> tuple[str, ...]:
|
||||||
|
"""
|
||||||
|
Get the packages in dependency-groups for a package.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not groups:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
if pyproject_toml is None:
|
||||||
|
msg = f"Didn't find a pyproject.toml, so can't read [dependency-groups] {groups!r} from it!"
|
||||||
|
raise FileNotFoundError(msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dependency_groups_toml = pyproject_toml["dependency-groups"]
|
||||||
|
except KeyError:
|
||||||
|
msg = f"Didn't find [dependency-groups] in pyproject.toml, which is needed to resolve {groups!r}."
|
||||||
|
raise KeyError(msg) from None
|
||||||
|
|
||||||
|
return dependency_groups.resolve(dependency_groups_toml, *groups)
|
||||||
|
|||||||
+24
-17
@@ -41,6 +41,7 @@ class PythonConfiguration:
|
|||||||
version: str
|
version: str
|
||||||
identifier: str
|
identifier: str
|
||||||
pyodide_version: str
|
pyodide_version: str
|
||||||
|
pyodide_build_version: str
|
||||||
emscripten_version: str
|
emscripten_version: str
|
||||||
node_version: str
|
node_version: str
|
||||||
|
|
||||||
@@ -65,10 +66,15 @@ def install_emscripten(tmp: Path, version: str) -> Path:
|
|||||||
return emcc_path
|
return emcc_path
|
||||||
|
|
||||||
|
|
||||||
def install_xbuildenv(env: dict[str, str], pyodide_version: str) -> str:
|
def install_xbuildenv(env: dict[str, str], pyodide_build_version: str, pyodide_version: str) -> str:
|
||||||
|
"""Install a particular Pyodide xbuildenv version and set a path to the Pyodide root."""
|
||||||
|
# Since pyodide-build was unvendored from Pyodide v0.27.0, the versions of pyodide-build are
|
||||||
|
# not guaranteed to match the versions of Pyodide or be in sync with them. Hence, we shall
|
||||||
|
# specify the pyodide-build version in the root path, which will set up the xbuildenv for
|
||||||
|
# the requested Pyodide version.
|
||||||
pyodide_root = (
|
pyodide_root = (
|
||||||
CIBW_CACHE_PATH
|
CIBW_CACHE_PATH
|
||||||
/ f".pyodide-xbuildenv-{pyodide_version}/{pyodide_version}/xbuildenv/pyodide-root"
|
/ f".pyodide-xbuildenv-{pyodide_build_version}/{pyodide_version}/xbuildenv/pyodide-root"
|
||||||
)
|
)
|
||||||
with FileLock(CIBW_CACHE_PATH / "xbuildenv.lock"):
|
with FileLock(CIBW_CACHE_PATH / "xbuildenv.lock"):
|
||||||
if pyodide_root.exists():
|
if pyodide_root.exists():
|
||||||
@@ -136,22 +142,22 @@ def setup_python(
|
|||||||
|
|
||||||
env = environment.as_dictionary(prev_environment=env)
|
env = environment.as_dictionary(prev_environment=env)
|
||||||
|
|
||||||
# check what pip version we're on
|
|
||||||
assert (venv_bin_path / "pip").exists()
|
|
||||||
call("which", "pip", env=env)
|
|
||||||
call("pip", "--version", env=env)
|
|
||||||
which_pip = call("which", "pip", env=env, capture_stdout=True).strip()
|
|
||||||
if which_pip != str(venv_bin_path / "pip"):
|
|
||||||
msg = "pip available on PATH doesn't match our venv instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it."
|
|
||||||
raise errors.FatalError(msg)
|
|
||||||
|
|
||||||
# check what Python version we're on
|
# check what Python version we're on
|
||||||
call("which", "python", env=env)
|
|
||||||
call("python", "--version", env=env)
|
|
||||||
which_python = call("which", "python", env=env, capture_stdout=True).strip()
|
which_python = call("which", "python", env=env, capture_stdout=True).strip()
|
||||||
|
print(which_python)
|
||||||
if which_python != str(venv_bin_path / "python"):
|
if which_python != str(venv_bin_path / "python"):
|
||||||
msg = "python available on PATH doesn't match our venv instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it."
|
msg = "python available on PATH doesn't match our venv instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it."
|
||||||
raise errors.FatalError(msg)
|
raise errors.FatalError(msg)
|
||||||
|
call("python", "--version", env=env)
|
||||||
|
|
||||||
|
# check what pip version we're on
|
||||||
|
assert (venv_bin_path / "pip").exists()
|
||||||
|
which_pip = call("which", "pip", env=env, capture_stdout=True).strip()
|
||||||
|
print(which_pip)
|
||||||
|
if which_pip != str(venv_bin_path / "pip"):
|
||||||
|
msg = "pip available on PATH doesn't match our venv instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it."
|
||||||
|
raise errors.FatalError(msg)
|
||||||
|
call("pip", "--version", env=env)
|
||||||
|
|
||||||
log.step("Installing build tools...")
|
log.step("Installing build tools...")
|
||||||
call(
|
call(
|
||||||
@@ -159,19 +165,20 @@ def setup_python(
|
|||||||
"install",
|
"install",
|
||||||
"--upgrade",
|
"--upgrade",
|
||||||
"auditwheel-emscripten",
|
"auditwheel-emscripten",
|
||||||
"build[virtualenv]",
|
|
||||||
"pyodide-build",
|
"pyodide-build",
|
||||||
*dependency_constraint_flags,
|
*dependency_constraint_flags,
|
||||||
env=env,
|
env=env,
|
||||||
)
|
)
|
||||||
|
|
||||||
log.step("Installing emscripten...")
|
log.step(f"Installing Emscripten version: {python_configuration.emscripten_version} ...")
|
||||||
emcc_path = install_emscripten(tmp, python_configuration.emscripten_version)
|
emcc_path = install_emscripten(tmp, python_configuration.emscripten_version)
|
||||||
|
|
||||||
env["PATH"] = os.pathsep.join([str(emcc_path.parent), env["PATH"]])
|
env["PATH"] = os.pathsep.join([str(emcc_path.parent), env["PATH"]])
|
||||||
|
|
||||||
log.step("Installing Pyodide xbuildenv...")
|
log.step(f"Installing Pyodide xbuildenv version: {python_configuration.pyodide_version} ...")
|
||||||
env["PYODIDE_ROOT"] = install_xbuildenv(env, python_configuration.pyodide_version)
|
env["PYODIDE_ROOT"] = install_xbuildenv(
|
||||||
|
env, python_configuration.pyodide_build_version, python_configuration.pyodide_version
|
||||||
|
)
|
||||||
|
|
||||||
return env
|
return env
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ python_configurations = [
|
|||||||
{ identifier = "pp38-manylinux_x86_64", version = "3.8", path_str = "/opt/python/pp38-pypy38_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 = "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 = "pp310-manylinux_x86_64", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
|
||||||
|
{ identifier = "pp311-manylinux_x86_64", version = "3.11", path_str = "/opt/python/pp311-pypy311_pp73" },
|
||||||
{ identifier = "cp36-manylinux_aarch64", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
{ 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 = "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 = "cp38-manylinux_aarch64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||||
@@ -49,14 +50,25 @@ python_configurations = [
|
|||||||
{ identifier = "cp312-manylinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
{ identifier = "cp312-manylinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||||
{ identifier = "cp313-manylinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
|
{ identifier = "cp313-manylinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
|
||||||
{ identifier = "cp313t-manylinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
|
{ identifier = "cp313t-manylinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
|
||||||
|
{ identifier = "cp36-manylinux_armv7l", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||||
|
{ identifier = "cp37-manylinux_armv7l", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||||
|
{ identifier = "cp38-manylinux_armv7l", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||||
|
{ identifier = "cp39-manylinux_armv7l", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||||
|
{ identifier = "cp310-manylinux_armv7l", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||||
|
{ identifier = "cp311-manylinux_armv7l", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||||
|
{ identifier = "cp312-manylinux_armv7l", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||||
|
{ identifier = "cp313-manylinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" },
|
||||||
|
{ identifier = "cp313t-manylinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
|
||||||
{ identifier = "pp37-manylinux_aarch64", version = "3.7", path_str = "/opt/python/pp37-pypy37_pp73" },
|
{ 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 = "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 = "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 = "pp310-manylinux_aarch64", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
|
||||||
|
{ identifier = "pp311-manylinux_aarch64", version = "3.11", path_str = "/opt/python/pp311-pypy311_pp73" },
|
||||||
{ identifier = "pp37-manylinux_i686", version = "3.7", path_str = "/opt/python/pp37-pypy37_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 = "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 = "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 = "pp310-manylinux_i686", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" },
|
||||||
|
{ identifier = "pp311-manylinux_i686", version = "3.11", path_str = "/opt/python/pp311-pypy311_pp73" },
|
||||||
{ identifier = "cp36-musllinux_x86_64", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
{ 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 = "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 = "cp38-musllinux_x86_64", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||||
@@ -102,6 +114,15 @@ python_configurations = [
|
|||||||
{ identifier = "cp312-musllinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
{ identifier = "cp312-musllinux_s390x", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||||
{ identifier = "cp313-musllinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
|
{ identifier = "cp313-musllinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313" },
|
||||||
{ identifier = "cp313t-musllinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
|
{ identifier = "cp313t-musllinux_s390x", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
|
||||||
|
{ identifier = "cp36-musllinux_armv7l", version = "3.6", path_str = "/opt/python/cp36-cp36m" },
|
||||||
|
{ identifier = "cp37-musllinux_armv7l", version = "3.7", path_str = "/opt/python/cp37-cp37m" },
|
||||||
|
{ identifier = "cp38-musllinux_armv7l", version = "3.8", path_str = "/opt/python/cp38-cp38" },
|
||||||
|
{ identifier = "cp39-musllinux_armv7l", version = "3.9", path_str = "/opt/python/cp39-cp39" },
|
||||||
|
{ identifier = "cp310-musllinux_armv7l", version = "3.10", path_str = "/opt/python/cp310-cp310" },
|
||||||
|
{ identifier = "cp311-musllinux_armv7l", version = "3.11", path_str = "/opt/python/cp311-cp311" },
|
||||||
|
{ identifier = "cp312-musllinux_armv7l", version = "3.12", path_str = "/opt/python/cp312-cp312" },
|
||||||
|
{ identifier = "cp313-musllinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" },
|
||||||
|
{ identifier = "cp313t-musllinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313t" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[macos]
|
[macos]
|
||||||
@@ -120,22 +141,24 @@ python_configurations = [
|
|||||||
{ identifier = "cp311-macosx_x86_64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.9/python-3.11.9-macos11.pkg" },
|
{ identifier = "cp311-macosx_x86_64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.9/python-3.11.9-macos11.pkg" },
|
||||||
{ identifier = "cp311-macosx_arm64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.9/python-3.11.9-macos11.pkg" },
|
{ identifier = "cp311-macosx_arm64", version = "3.11", url = "https://www.python.org/ftp/python/3.11.9/python-3.11.9-macos11.pkg" },
|
||||||
{ identifier = "cp311-macosx_universal2", version = "3.11", url = "https://www.python.org/ftp/python/3.11.9/python-3.11.9-macos11.pkg" },
|
{ identifier = "cp311-macosx_universal2", version = "3.11", url = "https://www.python.org/ftp/python/3.11.9/python-3.11.9-macos11.pkg" },
|
||||||
{ identifier = "cp312-macosx_x86_64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.5/python-3.12.5-macos11.pkg" },
|
{ identifier = "cp312-macosx_x86_64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.10/python-3.12.10-macos11.pkg" },
|
||||||
{ identifier = "cp312-macosx_arm64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.5/python-3.12.5-macos11.pkg" },
|
{ identifier = "cp312-macosx_arm64", version = "3.12", url = "https://www.python.org/ftp/python/3.12.10/python-3.12.10-macos11.pkg" },
|
||||||
{ identifier = "cp312-macosx_universal2", version = "3.12", url = "https://www.python.org/ftp/python/3.12.5/python-3.12.5-macos11.pkg" },
|
{ identifier = "cp312-macosx_universal2", version = "3.12", url = "https://www.python.org/ftp/python/3.12.10/python-3.12.10-macos11.pkg" },
|
||||||
{ identifier = "cp313-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0rc1-macos11.pkg" },
|
{ identifier = "cp313-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
|
||||||
{ identifier = "cp313-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0rc1-macos11.pkg" },
|
{ identifier = "cp313-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
|
||||||
{ identifier = "cp313-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0rc1-macos11.pkg" },
|
{ identifier = "cp313-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
|
||||||
{ identifier = "cp313t-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0rc1-macos11.pkg" },
|
{ identifier = "cp313t-macosx_x86_64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
|
||||||
{ identifier = "cp313t-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0rc1-macos11.pkg" },
|
{ identifier = "cp313t-macosx_arm64", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-macos11.pkg" },
|
||||||
{ identifier = "cp313t-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0rc1-macos11.pkg" },
|
{ identifier = "cp313t-macosx_universal2", version = "3.13", url = "https://www.python.org/ftp/python/3.13.3/python-3.13.3-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 = "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_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 = "pp38-macosx_arm64", version = "3.8", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.11-macos_arm64.tar.bz2" },
|
||||||
{ identifier = "pp39-macosx_x86_64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-macos_x86_64.tar.bz2" },
|
{ identifier = "pp39-macosx_x86_64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-macos_x86_64.tar.bz2" },
|
||||||
{ identifier = "pp39-macosx_arm64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-macos_arm64.tar.bz2" },
|
{ identifier = "pp39-macosx_arm64", version = "3.9", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-macos_arm64.tar.bz2" },
|
||||||
{ identifier = "pp310-macosx_x86_64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.17-macos_x86_64.tar.bz2" },
|
{ identifier = "pp310-macosx_x86_64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.19-macos_x86_64.tar.bz2" },
|
||||||
{ identifier = "pp310-macosx_arm64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.17-macos_arm64.tar.bz2" },
|
{ identifier = "pp310-macosx_arm64", version = "3.10", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.19-macos_arm64.tar.bz2" },
|
||||||
|
{ identifier = "pp311-macosx_x86_64", version = "3.11", url = "https://downloads.python.org/pypy/pypy3.11-v7.3.19-macos_x86_64.tar.bz2" },
|
||||||
|
{ identifier = "pp311-macosx_arm64", version = "3.11", url = "https://downloads.python.org/pypy/pypy3.11-v7.3.19-macos_arm64.tar.bz2" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[windows]
|
[windows]
|
||||||
@@ -152,25 +175,26 @@ python_configurations = [
|
|||||||
{ identifier = "cp310-win_amd64", version = "3.10.11", arch = "64" },
|
{ identifier = "cp310-win_amd64", version = "3.10.11", arch = "64" },
|
||||||
{ identifier = "cp311-win32", version = "3.11.9", arch = "32" },
|
{ identifier = "cp311-win32", version = "3.11.9", arch = "32" },
|
||||||
{ identifier = "cp311-win_amd64", version = "3.11.9", arch = "64" },
|
{ identifier = "cp311-win_amd64", version = "3.11.9", arch = "64" },
|
||||||
{ identifier = "cp312-win32", version = "3.12.5", arch = "32" },
|
{ identifier = "cp312-win32", version = "3.12.10", arch = "32" },
|
||||||
{ identifier = "cp312-win_amd64", version = "3.12.5", arch = "64" },
|
{ identifier = "cp312-win_amd64", version = "3.12.10", arch = "64" },
|
||||||
{ identifier = "cp313-win32", version = "3.13.0-rc1", arch = "32" },
|
{ identifier = "cp313-win32", version = "3.13.3", arch = "32" },
|
||||||
{ identifier = "cp313t-win32", version = "3.13.0-rc1", arch = "32" },
|
{ identifier = "cp313t-win32", version = "3.13.3", arch = "32" },
|
||||||
{ identifier = "cp313-win_amd64", version = "3.13.0-rc1", arch = "64" },
|
{ identifier = "cp313-win_amd64", version = "3.13.3", arch = "64" },
|
||||||
{ identifier = "cp313t-win_amd64", version = "3.13.0-rc1", arch = "64" },
|
{ identifier = "cp313t-win_amd64", version = "3.13.3", arch = "64" },
|
||||||
{ identifier = "cp39-win_arm64", version = "3.9.10", arch = "ARM64" },
|
{ identifier = "cp39-win_arm64", version = "3.9.10", arch = "ARM64" },
|
||||||
{ identifier = "cp310-win_arm64", version = "3.10.11", arch = "ARM64" },
|
{ identifier = "cp310-win_arm64", version = "3.10.11", arch = "ARM64" },
|
||||||
{ identifier = "cp311-win_arm64", version = "3.11.9", arch = "ARM64" },
|
{ identifier = "cp311-win_arm64", version = "3.11.9", arch = "ARM64" },
|
||||||
{ identifier = "cp312-win_arm64", version = "3.12.5", arch = "ARM64" },
|
{ identifier = "cp312-win_arm64", version = "3.12.10", arch = "ARM64" },
|
||||||
{ identifier = "cp313-win_arm64", version = "3.13.0-rc1", arch = "ARM64" },
|
{ identifier = "cp313-win_arm64", version = "3.13.3", arch = "ARM64" },
|
||||||
{ identifier = "cp313t-win_arm64", version = "3.13.0-rc1", arch = "ARM64" },
|
{ identifier = "cp313t-win_arm64", version = "3.13.3", 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 = "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 = "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.16-win64.zip" },
|
{ identifier = "pp39-win_amd64", version = "3.9", arch = "64", url = "https://downloads.python.org/pypy/pypy3.9-v7.3.16-win64.zip" },
|
||||||
{ identifier = "pp310-win_amd64", version = "3.10", arch = "64", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.17-win64.zip" },
|
{ identifier = "pp310-win_amd64", version = "3.10", arch = "64", url = "https://downloads.python.org/pypy/pypy3.10-v7.3.19-win64.zip" },
|
||||||
|
{ identifier = "pp311-win_amd64", version = "3.11", arch = "64", url = "https://downloads.python.org/pypy/pypy3.11-v7.3.19-win64.zip" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[pyodide]
|
[pyodide]
|
||||||
python_configurations = [
|
python_configurations = [
|
||||||
{ identifier = "cp312-pyodide_wasm32", version = "3.12.1", pyodide_version = "0.26.1", emscripten_version = "3.1.58", node_version = "v20" },
|
{ identifier = "cp312-pyodide_wasm32", version = "3.12", pyodide_version = "0.27.0", pyodide_build_version = "0.29.2", emscripten_version = "3.1.58", node_version = "v20" },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -10,7 +10,15 @@
|
|||||||
],
|
],
|
||||||
"default": "none",
|
"default": "none",
|
||||||
"description": "How to inherit the parent's value."
|
"description": "How to inherit the parent's value."
|
||||||
}
|
},
|
||||||
|
"enable": {
|
||||||
|
"enum": [
|
||||||
|
"cpython-freethreading",
|
||||||
|
"cpython-prerelease",
|
||||||
|
"pypy"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "A Python version or flavor to enable."
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "cibuildwheel's settings.",
|
"description": "cibuildwheel's settings.",
|
||||||
@@ -228,6 +236,21 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"title": "CIBW_DEPENDENCY_VERSIONS"
|
"title": "CIBW_DEPENDENCY_VERSIONS"
|
||||||
},
|
},
|
||||||
|
"enable": {
|
||||||
|
"description": "Enable or disable certain builds.",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/enable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/enable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "CIBW_ENABLE"
|
||||||
|
},
|
||||||
"environment": {
|
"environment": {
|
||||||
"description": "Set environment variables needed during the build.",
|
"description": "Set environment variables needed during the build.",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -265,6 +288,7 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"description": "The project supports free-threaded builds of Python (PEP703)",
|
"description": "The project supports free-threaded builds of Python (PEP703)",
|
||||||
|
"deprecated": "Use the `enable` option instead.",
|
||||||
"title": "CIBW_FREE_THREADED_SUPPORT"
|
"title": "CIBW_FREE_THREADED_SUPPORT"
|
||||||
},
|
},
|
||||||
"manylinux-aarch64-image": {
|
"manylinux-aarch64-image": {
|
||||||
@@ -272,6 +296,11 @@
|
|||||||
"description": "Specify alternative manylinux / musllinux container images",
|
"description": "Specify alternative manylinux / musllinux container images",
|
||||||
"title": "CIBW_MANYLINUX_AARCH64_IMAGE"
|
"title": "CIBW_MANYLINUX_AARCH64_IMAGE"
|
||||||
},
|
},
|
||||||
|
"manylinux-armv7l-image": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Specify alternative manylinux / musllinux container images",
|
||||||
|
"title": "CIBW_MANYLINUX_ARMV7L_IMAGE"
|
||||||
|
},
|
||||||
"manylinux-i686-image": {
|
"manylinux-i686-image": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Specify alternative manylinux / musllinux container images",
|
"description": "Specify alternative manylinux / musllinux container images",
|
||||||
@@ -312,6 +341,11 @@
|
|||||||
"description": "Specify alternative manylinux / musllinux container images",
|
"description": "Specify alternative manylinux / musllinux container images",
|
||||||
"title": "CIBW_MUSLLINUX_AARCH64_IMAGE"
|
"title": "CIBW_MUSLLINUX_AARCH64_IMAGE"
|
||||||
},
|
},
|
||||||
|
"musllinux-armv7l-image": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Specify alternative manylinux / musllinux container images",
|
||||||
|
"title": "CIBW_MUSLLINUX_ARMV7L_IMAGE"
|
||||||
|
},
|
||||||
"musllinux-i686-image": {
|
"musllinux-i686-image": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Specify alternative manylinux / musllinux container images",
|
"description": "Specify alternative manylinux / musllinux container images",
|
||||||
@@ -392,6 +426,21 @@
|
|||||||
],
|
],
|
||||||
"title": "CIBW_TEST_EXTRAS"
|
"title": "CIBW_TEST_EXTRAS"
|
||||||
},
|
},
|
||||||
|
"test-groups": {
|
||||||
|
"description": "Install extra groups when testing",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "CIBW_TEST_GROUPS"
|
||||||
|
},
|
||||||
"test-requires": {
|
"test-requires": {
|
||||||
"description": "Install Python dependencies before running the tests",
|
"description": "Install Python dependencies before running the tests",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -518,6 +567,9 @@
|
|||||||
"manylinux-aarch64-image": {
|
"manylinux-aarch64-image": {
|
||||||
"$ref": "#/properties/manylinux-aarch64-image"
|
"$ref": "#/properties/manylinux-aarch64-image"
|
||||||
},
|
},
|
||||||
|
"manylinux-armv7l-image": {
|
||||||
|
"$ref": "#/properties/manylinux-armv7l-image"
|
||||||
|
},
|
||||||
"manylinux-i686-image": {
|
"manylinux-i686-image": {
|
||||||
"$ref": "#/properties/manylinux-i686-image"
|
"$ref": "#/properties/manylinux-i686-image"
|
||||||
},
|
},
|
||||||
@@ -542,6 +594,9 @@
|
|||||||
"musllinux-aarch64-image": {
|
"musllinux-aarch64-image": {
|
||||||
"$ref": "#/properties/musllinux-aarch64-image"
|
"$ref": "#/properties/musllinux-aarch64-image"
|
||||||
},
|
},
|
||||||
|
"musllinux-armv7l-image": {
|
||||||
|
"$ref": "#/properties/musllinux-armv7l-image"
|
||||||
|
},
|
||||||
"musllinux-i686-image": {
|
"musllinux-i686-image": {
|
||||||
"$ref": "#/properties/musllinux-i686-image"
|
"$ref": "#/properties/musllinux-i686-image"
|
||||||
},
|
},
|
||||||
@@ -563,6 +618,9 @@
|
|||||||
"test-extras": {
|
"test-extras": {
|
||||||
"$ref": "#/properties/test-extras"
|
"$ref": "#/properties/test-extras"
|
||||||
},
|
},
|
||||||
|
"test-groups": {
|
||||||
|
"$ref": "#/properties/test-groups"
|
||||||
|
},
|
||||||
"test-requires": {
|
"test-requires": {
|
||||||
"$ref": "#/properties/test-requires"
|
"$ref": "#/properties/test-requires"
|
||||||
}
|
}
|
||||||
@@ -606,6 +664,9 @@
|
|||||||
"manylinux-aarch64-image": {
|
"manylinux-aarch64-image": {
|
||||||
"$ref": "#/properties/manylinux-aarch64-image"
|
"$ref": "#/properties/manylinux-aarch64-image"
|
||||||
},
|
},
|
||||||
|
"manylinux-armv7l-image": {
|
||||||
|
"$ref": "#/properties/manylinux-armv7l-image"
|
||||||
|
},
|
||||||
"manylinux-i686-image": {
|
"manylinux-i686-image": {
|
||||||
"$ref": "#/properties/manylinux-i686-image"
|
"$ref": "#/properties/manylinux-i686-image"
|
||||||
},
|
},
|
||||||
@@ -630,6 +691,9 @@
|
|||||||
"musllinux-aarch64-image": {
|
"musllinux-aarch64-image": {
|
||||||
"$ref": "#/properties/musllinux-aarch64-image"
|
"$ref": "#/properties/musllinux-aarch64-image"
|
||||||
},
|
},
|
||||||
|
"musllinux-armv7l-image": {
|
||||||
|
"$ref": "#/properties/musllinux-armv7l-image"
|
||||||
|
},
|
||||||
"musllinux-i686-image": {
|
"musllinux-i686-image": {
|
||||||
"$ref": "#/properties/musllinux-i686-image"
|
"$ref": "#/properties/musllinux-i686-image"
|
||||||
},
|
},
|
||||||
@@ -664,6 +728,9 @@
|
|||||||
"test-extras": {
|
"test-extras": {
|
||||||
"$ref": "#/properties/test-extras"
|
"$ref": "#/properties/test-extras"
|
||||||
},
|
},
|
||||||
|
"test-groups": {
|
||||||
|
"$ref": "#/properties/test-groups"
|
||||||
|
},
|
||||||
"test-requires": {
|
"test-requires": {
|
||||||
"$ref": "#/properties/test-requires"
|
"$ref": "#/properties/test-requires"
|
||||||
}
|
}
|
||||||
@@ -709,6 +776,9 @@
|
|||||||
"test-extras": {
|
"test-extras": {
|
||||||
"$ref": "#/properties/test-extras"
|
"$ref": "#/properties/test-extras"
|
||||||
},
|
},
|
||||||
|
"test-groups": {
|
||||||
|
"$ref": "#/properties/test-groups"
|
||||||
|
},
|
||||||
"test-requires": {
|
"test-requires": {
|
||||||
"$ref": "#/properties/test-requires"
|
"$ref": "#/properties/test-requires"
|
||||||
}
|
}
|
||||||
@@ -767,6 +837,9 @@
|
|||||||
"test-extras": {
|
"test-extras": {
|
||||||
"$ref": "#/properties/test-extras"
|
"$ref": "#/properties/test-extras"
|
||||||
},
|
},
|
||||||
|
"test-groups": {
|
||||||
|
"$ref": "#/properties/test-groups"
|
||||||
|
},
|
||||||
"test-requires": {
|
"test-requires": {
|
||||||
"$ref": "#/properties/test-requires"
|
"$ref": "#/properties/test-requires"
|
||||||
}
|
}
|
||||||
@@ -812,6 +885,9 @@
|
|||||||
"test-extras": {
|
"test-extras": {
|
||||||
"$ref": "#/properties/test-extras"
|
"$ref": "#/properties/test-extras"
|
||||||
},
|
},
|
||||||
|
"test-groups": {
|
||||||
|
"$ref": "#/properties/test-groups"
|
||||||
|
},
|
||||||
"test-requires": {
|
"test-requires": {
|
||||||
"$ref": "#/properties/test-requires"
|
"$ref": "#/properties/test-requires"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,122 +2,114 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
annotated-types==0.7.0
|
annotated-types==0.7.0
|
||||||
# via pydantic
|
# via pydantic
|
||||||
anyio==4.4.0
|
anyio==4.9.0
|
||||||
# via httpx
|
# via httpx
|
||||||
auditwheel-emscripten==0.0.16
|
auditwheel-emscripten==0.0.16
|
||||||
# via pyodide-build
|
# via pyodide-build
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via
|
# via
|
||||||
# -r .nox/update_constraints/tmp/constraints-pyodide.in
|
# -r .nox/update_constraints/tmp/constraints-pyodide.in
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
certifi==2024.8.30
|
certifi==2025.1.31
|
||||||
# via
|
# via
|
||||||
# httpcore
|
# httpcore
|
||||||
# httpx
|
# httpx
|
||||||
# requests
|
# requests
|
||||||
charset-normalizer==3.3.2
|
charset-normalizer==3.4.1
|
||||||
# via requests
|
# via requests
|
||||||
click==8.1.7
|
click==8.1.8
|
||||||
# via typer
|
# via typer
|
||||||
cloudpickle==3.0.0
|
cmake==4.0.0
|
||||||
# via loky
|
|
||||||
cmake==3.30.2
|
|
||||||
# via pyodide-build
|
# via pyodide-build
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.18.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
h11==0.14.0
|
h11==0.14.0
|
||||||
# via httpcore
|
# via httpcore
|
||||||
httpcore==1.0.5
|
httpcore==1.0.8
|
||||||
# via httpx
|
# via httpx
|
||||||
httpx==0.27.2
|
httpx==0.28.1
|
||||||
# via unearth
|
# via unearth
|
||||||
idna==3.8
|
idna==3.10
|
||||||
# via
|
# via
|
||||||
# anyio
|
# anyio
|
||||||
# httpx
|
# httpx
|
||||||
# requests
|
# requests
|
||||||
leb128==1.0.8
|
leb128==1.0.8
|
||||||
# via auditwheel-emscripten
|
# via auditwheel-emscripten
|
||||||
loky==3.4.1
|
|
||||||
# via pyodide-build
|
|
||||||
markdown-it-py==3.0.0
|
markdown-it-py==3.0.0
|
||||||
# via rich
|
# via rich
|
||||||
mdurl==0.1.2
|
mdurl==0.1.2
|
||||||
# via markdown-it-py
|
# via markdown-it-py
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# auditwheel-emscripten
|
# auditwheel-emscripten
|
||||||
# build
|
# build
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
# unearth
|
# unearth
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
|
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pydantic==2.8.2
|
pydantic==2.11.3
|
||||||
# via
|
# via
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
# pyodide-lock
|
# pyodide-lock
|
||||||
pydantic-core==2.20.1
|
pydantic-core==2.33.1
|
||||||
# via pydantic
|
# via pydantic
|
||||||
pygments==2.18.0
|
pygments==2.19.1
|
||||||
# via rich
|
# via rich
|
||||||
pyodide-build==0.26.1
|
pyodide-build==0.29.2
|
||||||
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
|
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
|
||||||
pyodide-cli==0.2.4
|
pyodide-cli==0.2.4
|
||||||
# via
|
# via
|
||||||
# auditwheel-emscripten
|
# auditwheel-emscripten
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
pyodide-lock==0.1.0a6
|
pyodide-lock==0.1.0a7
|
||||||
# via pyodide-build
|
# via pyodide-build
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
pyyaml==6.0.2
|
|
||||||
# via pyodide-build
|
|
||||||
requests==2.32.3
|
requests==2.32.3
|
||||||
# via pyodide-build
|
# via pyodide-build
|
||||||
resolvelib==1.0.1
|
resolvelib==1.1.0
|
||||||
# via pyodide-build
|
# via pyodide-build
|
||||||
rich==13.8.0
|
rich==14.0.0
|
||||||
# via
|
# via
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
# pyodide-cli
|
# pyodide-cli
|
||||||
# typer
|
# typer
|
||||||
ruamel-yaml==0.18.6
|
ruamel-yaml==0.18.10
|
||||||
# via pyodide-build
|
# via pyodide-build
|
||||||
ruamel-yaml-clib==0.2.8
|
ruamel-yaml-clib==0.2.12
|
||||||
# via ruamel-yaml
|
# via ruamel-yaml
|
||||||
shellingham==1.5.4
|
shellingham==1.5.4
|
||||||
# via typer
|
# via typer
|
||||||
sniffio==1.3.1
|
sniffio==1.3.1
|
||||||
# via
|
# via anyio
|
||||||
# anyio
|
typer==0.15.2
|
||||||
# httpx
|
|
||||||
typer==0.12.5
|
|
||||||
# via
|
# via
|
||||||
# auditwheel-emscripten
|
# auditwheel-emscripten
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
# pyodide-cli
|
# pyodide-cli
|
||||||
types-requests==2.32.0.20240712
|
typing-extensions==4.13.2
|
||||||
# via pyodide-build
|
|
||||||
typing-extensions==4.12.2
|
|
||||||
# via
|
# via
|
||||||
|
# anyio
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# typer
|
# typer
|
||||||
unearth==0.17.2
|
# typing-inspection
|
||||||
|
typing-inspection==0.4.0
|
||||||
|
# via pydantic
|
||||||
|
unearth==0.17.5
|
||||||
# via pyodide-build
|
# via pyodide-build
|
||||||
urllib3==2.2.2
|
urllib3==2.4.0
|
||||||
# via
|
# via requests
|
||||||
# requests
|
virtualenv==20.30.0
|
||||||
# types-requests
|
|
||||||
virtualenv==20.26.3
|
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
wheel==0.44.0
|
wheel==0.45.1
|
||||||
# via
|
# via
|
||||||
# auditwheel-emscripten
|
# auditwheel-emscripten
|
||||||
# pyodide-build
|
# pyodide-build
|
||||||
|
|||||||
@@ -2,33 +2,33 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
altgraph==0.17.4
|
altgraph==0.17.4
|
||||||
# via macholib
|
# via macholib
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.13.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.18.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
importlib-metadata==8.4.0
|
importlib-metadata==8.6.1
|
||||||
# via build
|
# via build
|
||||||
macholib==1.16.3
|
macholib==1.16.3
|
||||||
# via delocate
|
# via delocate
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# delocate
|
# delocate
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
tomli==2.0.1
|
tomli==2.2.1
|
||||||
# via build
|
# via build
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.13.2
|
||||||
# via delocate
|
# via delocate
|
||||||
virtualenv==20.26.3
|
virtualenv==20.30.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
zipp==3.20.1
|
zipp==3.21.0
|
||||||
# via importlib-metadata
|
# via importlib-metadata
|
||||||
|
|||||||
@@ -2,27 +2,27 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
altgraph==0.17.4
|
altgraph==0.17.4
|
||||||
# via macholib
|
# via macholib
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.13.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.18.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
macholib==1.16.3
|
macholib==1.16.3
|
||||||
# via delocate
|
# via delocate
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# delocate
|
# delocate
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.13.2
|
||||||
# via delocate
|
# via delocate
|
||||||
virtualenv==20.26.3
|
virtualenv==20.30.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
|
|||||||
@@ -2,27 +2,27 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
altgraph==0.17.4
|
altgraph==0.17.4
|
||||||
# via macholib
|
# via macholib
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.13.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.18.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
macholib==1.16.3
|
macholib==1.16.3
|
||||||
# via delocate
|
# via delocate
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# delocate
|
# delocate
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.13.2
|
||||||
# via delocate
|
# via delocate
|
||||||
virtualenv==20.26.3
|
virtualenv==20.30.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
|
|||||||
@@ -2,27 +2,27 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
altgraph==0.17.4
|
altgraph==0.17.4
|
||||||
# via macholib
|
# via macholib
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.13.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.18.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
macholib==1.16.3
|
macholib==1.16.3
|
||||||
# via delocate
|
# via delocate
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# delocate
|
# delocate
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.13.2
|
||||||
# via delocate
|
# via delocate
|
||||||
virtualenv==20.26.3
|
virtualenv==20.30.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ build==1.1.1
|
|||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.12.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.12.2
|
filelock==3.12.2
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
@@ -24,7 +24,7 @@ pip==24.0
|
|||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.0.0
|
platformdirs==4.0.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
tomli==2.0.1
|
tomli==2.0.1
|
||||||
# via build
|
# via build
|
||||||
@@ -33,7 +33,7 @@ typing-extensions==4.7.1
|
|||||||
# delocate
|
# delocate
|
||||||
# importlib-metadata
|
# importlib-metadata
|
||||||
# platformdirs
|
# platformdirs
|
||||||
virtualenv==20.26.3
|
virtualenv==20.26.6
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
zipp==3.15.0
|
zipp==3.15.0
|
||||||
# via importlib-metadata
|
# via importlib-metadata
|
||||||
|
|||||||
@@ -2,33 +2,33 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
altgraph==0.17.4
|
altgraph==0.17.4
|
||||||
# via macholib
|
# via macholib
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.12.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.16.1
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
importlib-metadata==8.4.0
|
importlib-metadata==8.5.0
|
||||||
# via build
|
# via build
|
||||||
macholib==1.16.3
|
macholib==1.16.3
|
||||||
# via delocate
|
# via delocate
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# delocate
|
# delocate
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.6
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
tomli==2.0.1
|
tomli==2.2.1
|
||||||
# via build
|
# via build
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.13.2
|
||||||
# via delocate
|
# via delocate
|
||||||
virtualenv==20.26.3
|
virtualenv==20.30.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
zipp==3.20.1
|
zipp==3.20.2
|
||||||
# via importlib-metadata
|
# via importlib-metadata
|
||||||
|
|||||||
@@ -2,33 +2,33 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
altgraph==0.17.4
|
altgraph==0.17.4
|
||||||
# via macholib
|
# via macholib
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.13.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.18.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
importlib-metadata==8.4.0
|
importlib-metadata==8.6.1
|
||||||
# via build
|
# via build
|
||||||
macholib==1.16.3
|
macholib==1.16.3
|
||||||
# via delocate
|
# via delocate
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# delocate
|
# delocate
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
tomli==2.0.1
|
tomli==2.2.1
|
||||||
# via build
|
# via build
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.13.2
|
||||||
# via delocate
|
# via delocate
|
||||||
virtualenv==20.26.3
|
virtualenv==20.30.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
zipp==3.20.1
|
zipp==3.21.0
|
||||||
# via importlib-metadata
|
# via importlib-metadata
|
||||||
|
|||||||
@@ -2,27 +2,27 @@
|
|||||||
# nox -s update_constraints
|
# nox -s update_constraints
|
||||||
altgraph==0.17.4
|
altgraph==0.17.4
|
||||||
# via macholib
|
# via macholib
|
||||||
build==1.2.1
|
build==1.2.2.post1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
delocate==0.12.0
|
delocate==0.13.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
distlib==0.3.8
|
distlib==0.3.9
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
filelock==3.15.4
|
filelock==3.18.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
macholib==1.16.3
|
macholib==1.16.3
|
||||||
# via delocate
|
# via delocate
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# build
|
# build
|
||||||
# delocate
|
# delocate
|
||||||
pip==24.2
|
pip==25.0.1
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
platformdirs==4.2.2
|
platformdirs==4.3.7
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
pyproject-hooks==1.1.0
|
pyproject-hooks==1.2.0
|
||||||
# via build
|
# via build
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.13.2
|
||||||
# via delocate
|
# via delocate
|
||||||
virtualenv==20.26.3
|
virtualenv==20.30.0
|
||||||
# via -r cibuildwheel/resources/constraints.in
|
# via -r cibuildwheel/resources/constraints.in
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ build = "*"
|
|||||||
skip = ""
|
skip = ""
|
||||||
test-skip = ""
|
test-skip = ""
|
||||||
free-threaded-support = false
|
free-threaded-support = false
|
||||||
|
enable = []
|
||||||
|
|
||||||
archs = ["auto"]
|
archs = ["auto"]
|
||||||
build-frontend = "default"
|
build-frontend = "default"
|
||||||
@@ -20,6 +21,7 @@ test-command = ""
|
|||||||
before-test = ""
|
before-test = ""
|
||||||
test-requires = []
|
test-requires = []
|
||||||
test-extras = []
|
test-extras = []
|
||||||
|
test-groups = []
|
||||||
|
|
||||||
container-engine = "docker"
|
container-engine = "docker"
|
||||||
|
|
||||||
@@ -28,6 +30,7 @@ manylinux-i686-image = "manylinux2014"
|
|||||||
manylinux-aarch64-image = "manylinux2014"
|
manylinux-aarch64-image = "manylinux2014"
|
||||||
manylinux-ppc64le-image = "manylinux2014"
|
manylinux-ppc64le-image = "manylinux2014"
|
||||||
manylinux-s390x-image = "manylinux2014"
|
manylinux-s390x-image = "manylinux2014"
|
||||||
|
manylinux-armv7l-image = "manylinux_2_31"
|
||||||
manylinux-pypy_x86_64-image = "manylinux2014"
|
manylinux-pypy_x86_64-image = "manylinux2014"
|
||||||
manylinux-pypy_i686-image = "manylinux2014"
|
manylinux-pypy_i686-image = "manylinux2014"
|
||||||
manylinux-pypy_aarch64-image = "manylinux2014"
|
manylinux-pypy_aarch64-image = "manylinux2014"
|
||||||
@@ -37,6 +40,7 @@ musllinux-i686-image = "musllinux_1_2"
|
|||||||
musllinux-aarch64-image = "musllinux_1_2"
|
musllinux-aarch64-image = "musllinux_1_2"
|
||||||
musllinux-ppc64le-image = "musllinux_1_2"
|
musllinux-ppc64le-image = "musllinux_1_2"
|
||||||
musllinux-s390x-image = "musllinux_1_2"
|
musllinux-s390x-image = "musllinux_1_2"
|
||||||
|
musllinux-armv7l-image = "musllinux_1_2"
|
||||||
|
|
||||||
|
|
||||||
[tool.cibuildwheel.linux]
|
[tool.cibuildwheel.linux]
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
url = "https://nodejs.org/dist/"
|
url = "https://nodejs.org/dist/"
|
||||||
v20 = "v20.17.0"
|
v22 = "v22.14.0"
|
||||||
|
v20 = "v20.19.0"
|
||||||
|
|||||||
@@ -1,54 +1,58 @@
|
|||||||
[x86_64]
|
[x86_64]
|
||||||
manylinux1 = quay.io/pypa/manylinux1_x86_64:2024-04-29-76807b8
|
manylinux1 = quay.io/pypa/manylinux1_x86_64:2024-04-29-76807b8
|
||||||
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
|
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-12-26-0d38463
|
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:2024.09.01-2
|
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.04.19-1
|
||||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2024.09.01-2
|
musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2024.10.26-1
|
||||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2024.09.01-2
|
musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2025.04.19-1
|
||||||
|
|
||||||
[i686]
|
[i686]
|
||||||
manylinux1 = quay.io/pypa/manylinux1_i686:2024-04-29-76807b8
|
manylinux1 = quay.io/pypa/manylinux1_i686:2024-04-29-76807b8
|
||||||
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
|
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_i686:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463
|
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463
|
||||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2024.09.01-2
|
musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2024.10.26-1
|
||||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2024.09.01-2
|
musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2025.04.19-1
|
||||||
|
|
||||||
[pypy_x86_64]
|
[pypy_x86_64]
|
||||||
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
|
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-12-26-0d38463
|
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:2024.09.01-2
|
manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.04.19-1
|
||||||
|
|
||||||
[pypy_i686]
|
[pypy_i686]
|
||||||
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
|
manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_i686:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463
|
manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463
|
||||||
|
|
||||||
[aarch64]
|
[aarch64]
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463
|
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463
|
||||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2024.09.01-2
|
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.04.19-1
|
||||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2024.09.01-2
|
musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2024.10.26-1
|
||||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2024.09.01-2
|
musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2025.04.19-1
|
||||||
|
|
||||||
[ppc64le]
|
[ppc64le]
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-12-26-0d38463
|
manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-12-26-0d38463
|
||||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2024.09.01-2
|
manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2025.04.19-1
|
||||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2024.09.01-2
|
musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2024.10.26-1
|
||||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2024.09.01-2
|
musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2025.04.19-1
|
||||||
|
|
||||||
[s390x]
|
[s390x]
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-12-26-0d38463
|
manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-12-26-0d38463
|
||||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2024.09.01-2
|
manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2025.04.19-1
|
||||||
musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2024.09.01-2
|
musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2024.10.26-1
|
||||||
musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2024.09.01-2
|
musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2025.04.19-1
|
||||||
|
|
||||||
[pypy_aarch64]
|
[pypy_aarch64]
|
||||||
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2024.09.01-2
|
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.04.19-1
|
||||||
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463
|
manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463
|
||||||
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2024.09.01-2
|
manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2025.04.19-1
|
||||||
|
|
||||||
|
[armv7l]
|
||||||
|
manylinux_2_31 = quay.io/pypa/manylinux_2_31_armv7l:2025.04.19-1
|
||||||
|
musllinux_1_2 = quay.io/pypa/musllinux_1_2_armv7l:2025.04.19-1
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
py36 = { version = "20.21.1", url = "https://github.com/pypa/get-virtualenv/blob/20.21.1/public/virtualenv.pyz?raw=true" }
|
py36 = { version = "20.17.1", url = "https://bootstrap.pypa.io/virtualenv/3.6/virtualenv.pyz" }
|
||||||
default = { version = "20.26.3", url = "https://github.com/pypa/get-virtualenv/blob/20.26.3/public/virtualenv.pyz?raw=true" }
|
default = { version = "20.26.6", url = "https://bootstrap.pypa.io/virtualenv/3.7/virtualenv.pyz" }
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ __all__ = (
|
|||||||
"PLATFORMS",
|
"PLATFORMS",
|
||||||
"PathOrStr",
|
"PathOrStr",
|
||||||
"PlatformName",
|
"PlatformName",
|
||||||
"PLATFORMS",
|
|
||||||
"PopenBytes",
|
"PopenBytes",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+104
-20
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import enum
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
@@ -19,11 +20,11 @@ from collections import defaultdict
|
|||||||
from collections.abc import Generator, Iterable, Mapping, MutableMapping, Sequence
|
from collections.abc import Generator, Iterable, Mapping, MutableMapping, Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from functools import lru_cache
|
from functools import lru_cache, total_ordering
|
||||||
from pathlib import Path, PurePath
|
from pathlib import Path, PurePath
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from typing import Any, ClassVar, Final, Literal, TextIO, TypeVar
|
from typing import Any, Final, Literal, TextIO, TypeVar
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
import bracex
|
import bracex
|
||||||
@@ -37,10 +38,12 @@ from platformdirs import user_cache_path
|
|||||||
|
|
||||||
from ._compat import tomllib
|
from ._compat import tomllib
|
||||||
from .architecture import Architecture
|
from .architecture import Architecture
|
||||||
|
from .errors import FatalError
|
||||||
from .typing import PathOrStr, PlatformName
|
from .typing import PathOrStr, PlatformName
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"MANYLINUX_ARCHS",
|
"MANYLINUX_ARCHS",
|
||||||
|
"EnableGroups",
|
||||||
"call",
|
"call",
|
||||||
"chdir",
|
"chdir",
|
||||||
"combine_constraints",
|
"combine_constraints",
|
||||||
@@ -66,6 +69,16 @@ free_thread_enable_313: Final[Path] = resources_dir / "free-threaded-enable-313.
|
|||||||
test_fail_cwd_file: Final[Path] = resources_dir / "testing_temp_dir_file.py"
|
test_fail_cwd_file: Final[Path] = resources_dir / "testing_temp_dir_file.py"
|
||||||
|
|
||||||
|
|
||||||
|
class EnableGroups(enum.Enum):
|
||||||
|
"""
|
||||||
|
Groups of build selectors that are not enabled by default.
|
||||||
|
"""
|
||||||
|
|
||||||
|
CPythonFreeThreading = "cpython-freethreading"
|
||||||
|
CPythonPrerelease = "cpython-prerelease"
|
||||||
|
PyPy = "pypy"
|
||||||
|
|
||||||
|
|
||||||
MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
|
MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
|
||||||
"x86_64",
|
"x86_64",
|
||||||
"i686",
|
"i686",
|
||||||
@@ -73,6 +86,7 @@ MANYLINUX_ARCHS: Final[tuple[str, ...]] = (
|
|||||||
"aarch64",
|
"aarch64",
|
||||||
"ppc64le",
|
"ppc64le",
|
||||||
"s390x",
|
"s390x",
|
||||||
|
"armv7l",
|
||||||
"pypy_aarch64",
|
"pypy_aarch64",
|
||||||
"pypy_i686",
|
"pypy_i686",
|
||||||
)
|
)
|
||||||
@@ -83,6 +97,7 @@ MUSLLINUX_ARCHS: Final[tuple[str, ...]] = (
|
|||||||
"aarch64",
|
"aarch64",
|
||||||
"ppc64le",
|
"ppc64le",
|
||||||
"s390x",
|
"s390x",
|
||||||
|
"armv7l",
|
||||||
)
|
)
|
||||||
|
|
||||||
DEFAULT_CIBW_CACHE_PATH: Final[Path] = user_cache_path(appname="cibuildwheel", appauthor="pypa")
|
DEFAULT_CIBW_CACHE_PATH: Final[Path] = user_cache_path(appname="cibuildwheel", appauthor="pypa")
|
||||||
@@ -126,13 +141,32 @@ def call(
|
|||||||
args_ = [str(arg) for arg in args]
|
args_ = [str(arg) for arg in args]
|
||||||
# print the command executing for the logs
|
# print the command executing for the logs
|
||||||
print("+ " + " ".join(shlex.quote(a) for a in args_))
|
print("+ " + " ".join(shlex.quote(a) for a in args_))
|
||||||
kwargs: dict[str, Any] = {}
|
# workaround platform behaviour differences outlined
|
||||||
if capture_stdout:
|
# in https://github.com/python/cpython/issues/52803
|
||||||
kwargs["universal_newlines"] = True
|
path_env = env if env is not None else os.environ
|
||||||
kwargs["stdout"] = subprocess.PIPE
|
path = path_env.get("PATH", None)
|
||||||
result = subprocess.run(args_, check=True, shell=IS_WIN, env=env, cwd=cwd, **kwargs)
|
executable = shutil.which(args_[0], path=path)
|
||||||
|
if executable is None:
|
||||||
|
msg = f"Couldn't find {args_[0]!r} in PATH {path!r}"
|
||||||
|
raise FatalError(msg)
|
||||||
|
args_[0] = executable
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
args_,
|
||||||
|
check=True,
|
||||||
|
shell=IS_WIN,
|
||||||
|
env=env,
|
||||||
|
cwd=cwd,
|
||||||
|
capture_output=capture_stdout,
|
||||||
|
text=capture_stdout,
|
||||||
|
)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
if capture_stdout:
|
||||||
|
sys.stderr.write(e.stderr)
|
||||||
|
raise
|
||||||
if not capture_stdout:
|
if not capture_stdout:
|
||||||
return None
|
return None
|
||||||
|
sys.stderr.write(result.stderr)
|
||||||
return typing.cast(str, result.stdout)
|
return typing.cast(str, result.stdout)
|
||||||
|
|
||||||
|
|
||||||
@@ -246,12 +280,7 @@ class BuildSelector:
|
|||||||
build_config: str
|
build_config: str
|
||||||
skip_config: str
|
skip_config: str
|
||||||
requires_python: SpecifierSet | None = None
|
requires_python: SpecifierSet | None = None
|
||||||
|
enable: frozenset[EnableGroups] = frozenset()
|
||||||
# a pattern that skips prerelease versions, when include_prereleases is False.
|
|
||||||
PRERELEASE_SKIP: ClassVar[str] = ""
|
|
||||||
prerelease_pythons: bool = False
|
|
||||||
|
|
||||||
free_threaded_support: bool = False
|
|
||||||
|
|
||||||
def __call__(self, build_id: str) -> bool:
|
def __call__(self, build_id: str) -> bool:
|
||||||
# Filter build selectors by python_requires if set
|
# Filter build selectors by python_requires if set
|
||||||
@@ -265,12 +294,16 @@ class BuildSelector:
|
|||||||
if not self.requires_python.contains(version):
|
if not self.requires_python.contains(version):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# filter out the prerelease pythons if self.prerelease_pythons is False
|
# filter out groups that are not enabled
|
||||||
if not self.prerelease_pythons and selector_matches(self.PRERELEASE_SKIP, build_id):
|
if EnableGroups.CPythonFreeThreading not in self.enable and selector_matches(
|
||||||
|
"cp3??t-*", build_id
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
|
if EnableGroups.CPythonPrerelease not in self.enable and selector_matches(
|
||||||
# filter out free threaded pythons if self.free_threaded_support is False
|
"cp314*", build_id
|
||||||
if not self.free_threaded_support and selector_matches("*t-*", build_id):
|
):
|
||||||
|
return False
|
||||||
|
if EnableGroups.PyPy not in self.enable and selector_matches("pp*", build_id):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
should_build = selector_matches(self.build_config, build_id)
|
should_build = selector_matches(self.build_config, build_id)
|
||||||
@@ -283,8 +316,7 @@ class BuildSelector:
|
|||||||
"build_config": self.build_config,
|
"build_config": self.build_config,
|
||||||
"skip_config": self.skip_config,
|
"skip_config": self.skip_config,
|
||||||
"requires_python": str(self.requires_python),
|
"requires_python": str(self.requires_python),
|
||||||
"prerelease_pythons": self.prerelease_pythons,
|
"enable": sorted(group.value for group in self.enable),
|
||||||
"free_threaded_support": self.free_threaded_support,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -673,6 +705,10 @@ def virtualenv(
|
|||||||
dependency_constraint_flags are ignored since nothing is installed in the
|
dependency_constraint_flags are ignored since nothing is installed in the
|
||||||
venv. Otherwise, pip is installed, and setuptools + wheel if Python < 3.12.
|
venv. Otherwise, pip is installed, and setuptools + wheel if Python < 3.12.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# virtualenv may fail if this is a symlink.
|
||||||
|
python = python.resolve()
|
||||||
|
|
||||||
assert python.exists()
|
assert python.exists()
|
||||||
|
|
||||||
if use_uv:
|
if use_uv:
|
||||||
@@ -899,3 +935,51 @@ def combine_constraints(
|
|||||||
env["UV_CONSTRAINT"] = env["PIP_CONSTRAINT"] = " ".join(
|
env["UV_CONSTRAINT"] = env["PIP_CONSTRAINT"] = " ".join(
|
||||||
c for c in [our_constraints, user_constraints] if c
|
c for c in [our_constraints, user_constraints] if c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@total_ordering
|
||||||
|
class FlexibleVersion:
|
||||||
|
version_str: str
|
||||||
|
version_parts: tuple[int, ...]
|
||||||
|
suffix: str
|
||||||
|
|
||||||
|
def __init__(self, version_str: str) -> None:
|
||||||
|
self.version_str = version_str
|
||||||
|
|
||||||
|
# Split into numeric parts and the optional suffix
|
||||||
|
match = re.match(r"^[v]?(\d+(\.\d+)*)(.*)$", version_str)
|
||||||
|
if not match:
|
||||||
|
msg = f"Invalid version string: {version_str}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
version_part, _, suffix = match.groups()
|
||||||
|
|
||||||
|
# Convert numeric version part into a tuple of integers
|
||||||
|
self.version_parts = tuple(map(int, version_part.split(".")))
|
||||||
|
self.suffix = suffix.strip() if suffix else ""
|
||||||
|
|
||||||
|
# Normalize by removing trailing zeros
|
||||||
|
self.version_parts = self._remove_trailing_zeros(self.version_parts)
|
||||||
|
|
||||||
|
def _remove_trailing_zeros(self, parts: tuple[int, ...]) -> tuple[int, ...]:
|
||||||
|
# Remove trailing zeros for accurate comparisons
|
||||||
|
# without this, "3.0" would be considered greater than "3"
|
||||||
|
while parts and parts[-1] == 0:
|
||||||
|
parts = parts[:-1]
|
||||||
|
return parts
|
||||||
|
|
||||||
|
def __eq__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, FlexibleVersion):
|
||||||
|
raise NotImplementedError()
|
||||||
|
return (self.version_parts, self.suffix) == (other.version_parts, other.suffix)
|
||||||
|
|
||||||
|
def __lt__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, FlexibleVersion):
|
||||||
|
raise NotImplementedError()
|
||||||
|
return (self.version_parts, self.suffix) < (other.version_parts, other.suffix)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"FlexibleVersion('{self.version_str}')"
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.version_str
|
||||||
|
|||||||
+21
-15
@@ -225,6 +225,14 @@ def setup_rust_cross_compile(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def can_use_uv(python_configuration: PythonConfiguration) -> bool:
|
||||||
|
conditions = (
|
||||||
|
Version(python_configuration.version) >= Version("3.8"),
|
||||||
|
not python_configuration.identifier.startswith("pp38-"),
|
||||||
|
)
|
||||||
|
return all(conditions)
|
||||||
|
|
||||||
|
|
||||||
def setup_python(
|
def setup_python(
|
||||||
tmp: Path,
|
tmp: Path,
|
||||||
python_configuration: PythonConfiguration,
|
python_configuration: PythonConfiguration,
|
||||||
@@ -254,11 +262,10 @@ def setup_python(
|
|||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
assert base_python.exists()
|
assert base_python.exists()
|
||||||
|
|
||||||
use_uv = (
|
if build_frontend == "build[uv]" and not can_use_uv(python_configuration):
|
||||||
build_frontend == "build[uv]"
|
build_frontend = "build"
|
||||||
and Version(python_configuration.version) >= Version("3.8")
|
|
||||||
and not python_configuration.identifier.startswith("pp38-")
|
use_uv = build_frontend == "build[uv]"
|
||||||
)
|
|
||||||
uv_path = find_uv()
|
uv_path = find_uv()
|
||||||
|
|
||||||
log.step("Setting up build environment...")
|
log.step("Setting up build environment...")
|
||||||
@@ -295,22 +302,22 @@ def setup_python(
|
|||||||
env = environment.as_dictionary(prev_environment=env)
|
env = environment.as_dictionary(prev_environment=env)
|
||||||
|
|
||||||
# check what Python version we're on
|
# check what Python version we're on
|
||||||
call("where", "python", env=env)
|
|
||||||
call("python", "--version", env=env)
|
|
||||||
call("python", "-c", "\"import struct; print(struct.calcsize('P') * 8)\"", env=env)
|
|
||||||
where_python = call("where", "python", env=env, capture_stdout=True).splitlines()[0].strip()
|
where_python = call("where", "python", env=env, capture_stdout=True).splitlines()[0].strip()
|
||||||
|
print(where_python)
|
||||||
if where_python != str(venv_path / "Scripts" / "python.exe"):
|
if where_python != str(venv_path / "Scripts" / "python.exe"):
|
||||||
msg = "python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it."
|
msg = "python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it."
|
||||||
raise errors.FatalError(msg)
|
raise errors.FatalError(msg)
|
||||||
|
call("python", "--version", env=env)
|
||||||
|
call("python", "-c", "\"import struct; print(struct.calcsize('P') * 8)\"", env=env)
|
||||||
|
|
||||||
# check what pip version we're on
|
# check what pip version we're on
|
||||||
if not use_uv:
|
if not use_uv:
|
||||||
assert (venv_path / "Scripts" / "pip.exe").exists()
|
assert (venv_path / "Scripts" / "pip.exe").exists()
|
||||||
where_pip = call("where", "pip", env=env, capture_stdout=True).splitlines()[0].strip()
|
where_pip = call("where", "pip", env=env, capture_stdout=True).splitlines()[0].strip()
|
||||||
|
print(where_pip)
|
||||||
if where_pip.strip() != str(venv_path / "Scripts" / "pip.exe"):
|
if where_pip.strip() != str(venv_path / "Scripts" / "pip.exe"):
|
||||||
msg = "pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it."
|
msg = "pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it."
|
||||||
raise errors.FatalError(msg)
|
raise errors.FatalError(msg)
|
||||||
|
|
||||||
call("pip", "--version", env=env)
|
call("pip", "--version", env=env)
|
||||||
|
|
||||||
log.step("Installing build tools...")
|
log.step("Installing build tools...")
|
||||||
@@ -368,11 +375,7 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
for config in python_configurations:
|
for config in python_configurations:
|
||||||
build_options = options.build_options(config.identifier)
|
build_options = options.build_options(config.identifier)
|
||||||
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
build_frontend = build_options.build_frontend or BuildFrontendConfig("pip")
|
||||||
use_uv = (
|
use_uv = build_frontend.name == "build[uv]" and can_use_uv(config)
|
||||||
build_frontend.name == "build[uv]"
|
|
||||||
and Version(config.version) >= Version("3.8")
|
|
||||||
and not config.identifier.startswith("pp38-")
|
|
||||||
)
|
|
||||||
log.build_start(config.identifier)
|
log.build_start(config.identifier)
|
||||||
|
|
||||||
identifier_tmp_dir = tmp_path / config.identifier
|
identifier_tmp_dir = tmp_path / config.identifier
|
||||||
@@ -487,7 +490,10 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
else:
|
else:
|
||||||
shutil.move(str(built_wheel), repaired_wheel_dir)
|
shutil.move(str(built_wheel), repaired_wheel_dir)
|
||||||
|
|
||||||
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
|
try:
|
||||||
|
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
|
||||||
|
except StopIteration:
|
||||||
|
raise errors.RepairStepProducedNoWheelError() from None
|
||||||
|
|
||||||
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
||||||
raise errors.AlreadyBuiltWheelError(repaired_wheel.name)
|
raise errors.AlreadyBuiltWheelError(repaired_wheel.name)
|
||||||
|
|||||||
+105
-2
@@ -4,8 +4,103 @@ title: Changelog
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### v2.23.4
|
||||||
|
|
||||||
|
_16 March 2026_
|
||||||
|
|
||||||
|
- 🐛 Fix HTTP 429 errors while downloading virtualenv from GitHub blob URLs – uses a https://bootstrap.pypa.io/ URL instead. (#2775)
|
||||||
|
|
||||||
|
### v2.23.3
|
||||||
|
|
||||||
|
_26 April 2025_
|
||||||
|
|
||||||
|
- 🛠 Dependency updates, including Python 3.13.3 (#2371)
|
||||||
|
|
||||||
|
### v2.23.2
|
||||||
|
|
||||||
|
_24 March 2025_
|
||||||
|
|
||||||
|
- 🐛 Workaround an issue with pyodide builds when running cibuildwheel with a Python that was installed via UV (#2328 via #2331)
|
||||||
|
- 🛠 Dependency updates, including a manylinux update that fixes an ['undefined symbol' error](https://github.com/pypa/manylinux/issues/1760) in gcc-toolset (#2334)
|
||||||
|
|
||||||
|
### v2.23.1
|
||||||
|
|
||||||
|
_15 March 2025_
|
||||||
|
|
||||||
|
- ⚠️ Added warnings when the shorthand values `manylinux1`, `manylinux2010`, `manylinux_2_24`, and `musllinux_1_1` are used to specify the images in linux builds. The shorthand to these (unmaintainted) images will be removed in v3.0. If you want to keep using these images, explicitly opt-in using the full image URL, which can be found in [this file](https://github.com/pypa/cibuildwheel/blob/v2.23.1/cibuildwheel/resources/pinned_docker_images.cfg). (#2312)
|
||||||
|
- 🛠 Dependency updates, including a manylinux update which fixes an [issue with rustup](https://github.com/pypa/cibuildwheel/issues/2303). (#2315)
|
||||||
|
|
||||||
|
### v2.23.0
|
||||||
|
|
||||||
|
_1 March 2025_
|
||||||
|
|
||||||
|
- ✨ Adds official support for the new GitHub Actions Arm runners. In fact these worked out-of-the-box, now we include them in our tests and example configs. (#2135 via #2281)
|
||||||
|
- ✨ Adds support for building PyPy 3.11 wheels (#2268 via #2281)
|
||||||
|
- 🛠 Adopts the beta pypa/manylinux image for armv7l builds (#2269 via #2281)
|
||||||
|
- 🛠 Dependency updates, including Pyodide 0.27 (#2117 and #2281)
|
||||||
|
|
||||||
|
### v2.22.0
|
||||||
|
|
||||||
|
_23 November 2024_
|
||||||
|
|
||||||
|
- 🌟 Added a new `CIBW_ENABLE`/`enable` feature that replaces `CIBW_FREETHREADED_SUPPORT`/`free-threaded-support` and `CIBW_PRERELEASE_PYTHONS` with a system that supports both. In cibuildwheel 3, this will also include a PyPy setting and the deprecated options will be removed. (#2048)
|
||||||
|
- 🌟 [Dependency groups](https://peps.python.org/pep-0735/) are now supported for tests. Use `CIBW_TEST_GROUPS`/`test-groups` to specify groups in `[dependency-groups]` for testing. (#2063)
|
||||||
|
- 🌟 Support for the experimental Ubuntu-based ARMv7l manylinux image (#2052)
|
||||||
|
- ✨ Show a warning when cibuildwheel is run from Python 3.10 or older; cibuildwheel 3.0 will require Python 3.11 or newer as host (#2050)
|
||||||
|
- 🐛 Fix issue with stderr interfering with checking the docker version (#2074)
|
||||||
|
- 🛠 Python 3.9 is now used in `CIBW_BEFORE_ALL`/`before-all` on linux, replacing 3.8, which is now EoL (#2043)
|
||||||
|
- 🛠 Error messages for producing a pure-Python wheel are slightly more informative (#2044)
|
||||||
|
- 🛠 Better error when `uname -m` fails on ARM (#2049)
|
||||||
|
- 🛠 Better error when repair fails and docs for abi3audit on Windows (#2058)
|
||||||
|
- 🛠 Better error when `manylinux-interpreters ensure` fails (#2066)
|
||||||
|
- 🛠 Update Pyodide to 0.26.4, and adapt to the unbundled pyodide-build (now 0.29) (#2090)
|
||||||
|
- 🛠 Now cibuildwheel uses dependency-groups for development dependencies (#2064, #2085)
|
||||||
|
- 📚 Docs updates and tidy ups (#2061, #2067, #2072)
|
||||||
|
|
||||||
|
|
||||||
|
### v2.21.3
|
||||||
|
|
||||||
|
_9 October 2024_
|
||||||
|
|
||||||
|
- 🛠 Update CPython 3.13 to 3.13.0 final release (#2032)
|
||||||
|
- 📚 Docs updates and tidy ups (#2035)
|
||||||
|
|
||||||
|
### v2.21.2
|
||||||
|
|
||||||
|
_2 October 2024_
|
||||||
|
|
||||||
|
- ✨ Adds support for building 32-bit armv7l wheels on musllinux. On a Linux system with emulation set up, set [CIBW_ARCHS](https://cibuildwheel.pypa.io/en/stable/options/#archs) to `armv7l` on Linux to try it out if you're interested! (#2017)
|
||||||
|
- 🐛 Fix Linux Podman builds on some systems (#2016)
|
||||||
|
- ✨ Adds official support for running on Python 3.13 (#2026)
|
||||||
|
- 🛠 Update CPython 3.13 to 3.13.0rc3 (#2029)
|
||||||
|
|
||||||
|
Note: the default [manylinux image](https://cibuildwheel.pypa.io/en/stable/options/#linux-image) is **scheduled to change** from `manylinux2014` to `manylinux_2_28` in a cibuildwheel release on or after **6th May 2025** - you can set the value now to avoid getting upgraded if you want. (#1992)
|
||||||
|
|
||||||
|
### v2.21.1
|
||||||
|
|
||||||
|
_16 September 2024_
|
||||||
|
|
||||||
|
- 🐛 Fix a bug in the Linux build, where files copied to the container would have invalid ownership permissions (#2007)
|
||||||
|
- 🐛 Fix a bug on Windows where cibuildwheel would call upon `uv` to install dependencies for versions of CPython that it does not support (#2005)
|
||||||
|
- 🐛 Fix a bug where `uv 0.4.10` would not use the right Python when testing on Linux. (#2008)
|
||||||
|
- 🛠 Bump our documentation pins, fixes an issue with a missing package (#2011)
|
||||||
|
|
||||||
|
### v2.21.0
|
||||||
|
|
||||||
|
_13 September 2024_
|
||||||
|
|
||||||
|
- ⚠️ Update CPython 3.12 to 3.12.6, which changes the macOS minimum deployment target on CPython 3.12 from macOS 10.9 to macOS 10.13 (#1998)
|
||||||
|
- 🛠 Changes the behaviour when inheriting `config-settings` in TOML overrides - rather than extending each key, which is rarely useful, individual keys will override previously set values. (#1803)
|
||||||
|
- 🛠 Update CPython 3.13 to 3.13.0rc2 (#1998)
|
||||||
|
- ✨ Adds support for multiarch OCI images (#1961)
|
||||||
|
- 🐛 Fixes some bugs building Linux wheels on macOS. (#1961)
|
||||||
|
- ⚠️ Changes the minimum version of Docker/Podman to Docker API version 1.43, Podman API version 3. The only mainstream runner this should affect is Travis Graviton2 runners - if so you can [upgrade your version of Docker](https://github.com/pypa/cibuildwheel/pull/1961#issuecomment-2304060019). (#1961)
|
||||||
|
|
||||||
|
|
||||||
### v2.20.0
|
### v2.20.0
|
||||||
|
|
||||||
|
_4 August 2024_
|
||||||
|
|
||||||
- 🌟 CPython 3.13 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.13.0rc1, which is guaranteed to be ABI compatible with the final release. Free-threading is still behind a flag/config option. (#1950)
|
- 🌟 CPython 3.13 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.13.0rc1, which is guaranteed to be ABI compatible with the final release. Free-threading is still behind a flag/config option. (#1950)
|
||||||
- ✨ Provide a `CIBW_ALLOW_EMPTY` environment variable as an alternative to the command line flag. (#1937)
|
- ✨ Provide a `CIBW_ALLOW_EMPTY` environment variable as an alternative to the command line flag. (#1937)
|
||||||
- 🐛 Don't use uv on PyPy3.8 on Windows, it stopped working starting in 0.2.25. Note that PyPy 3.8 is EoL. (#1868)
|
- 🐛 Don't use uv on PyPy3.8 on Windows, it stopped working starting in 0.2.25. Note that PyPy 3.8 is EoL. (#1868)
|
||||||
@@ -16,6 +111,8 @@ title: Changelog
|
|||||||
|
|
||||||
### v2.19.2
|
### v2.19.2
|
||||||
|
|
||||||
|
_2 July 2024_
|
||||||
|
|
||||||
- 🐛 Update manylinux2014 pins to versions that support past-EoL CentOS 7 mirrors. (#1917)
|
- 🐛 Update manylinux2014 pins to versions that support past-EoL CentOS 7 mirrors. (#1917)
|
||||||
- 🐛 Support `--no-isolation` with `build[uv]` build-frontend. (#1889)
|
- 🐛 Support `--no-isolation` with `build[uv]` build-frontend. (#1889)
|
||||||
- 🛠 Provide attestations for releases at <https://github.com/pypa/cibuildwheel/attestations>. (#1916)
|
- 🛠 Provide attestations for releases at <https://github.com/pypa/cibuildwheel/attestations>. (#1916)
|
||||||
@@ -28,6 +125,8 @@ title: Changelog
|
|||||||
|
|
||||||
### v2.19.1
|
### v2.19.1
|
||||||
|
|
||||||
|
_13 June 2024_
|
||||||
|
|
||||||
- 🐛 Don't require setup-python on GHA for Pyodide (#1868)
|
- 🐛 Don't require setup-python on GHA for Pyodide (#1868)
|
||||||
- 🐛 Specify full python path for uv (fixes issue in 0.2.10 & 0.2.11) (#1881)
|
- 🐛 Specify full python path for uv (fixes issue in 0.2.10 & 0.2.11) (#1881)
|
||||||
- 🛠 Update for pip 24.1b2 on CPython 3.13. (#1879)
|
- 🛠 Update for pip 24.1b2 on CPython 3.13. (#1879)
|
||||||
@@ -37,6 +136,8 @@ title: Changelog
|
|||||||
|
|
||||||
### v2.19.0
|
### v2.19.0
|
||||||
|
|
||||||
|
_10 June 2024_
|
||||||
|
|
||||||
See the [release post](https://iscinumpy.dev/post/cibuildwheel-2-19-0/) for more info on new features!
|
See the [release post](https://iscinumpy.dev/post/cibuildwheel-2-19-0/) for more info on new features!
|
||||||
|
|
||||||
- 🌟 Add Pyodide platform. Set with `--platform pyodide` or `CIBW_PLATFORM: pyodide` on Linux with a host Python 3.12 to build WebAssembly wheels. Not accepted on PyPI currently, but usable directly in a website using Pyodide, for live docs, etc. (#1456, #1859)
|
- 🌟 Add Pyodide platform. Set with `--platform pyodide` or `CIBW_PLATFORM: pyodide` on Linux with a host Python 3.12 to build WebAssembly wheels. Not accepted on PyPI currently, but usable directly in a website using Pyodide, for live docs, etc. (#1456, #1859)
|
||||||
@@ -55,6 +156,8 @@ See the [release post](https://iscinumpy.dev/post/cibuildwheel-2-19-0/) for more
|
|||||||
|
|
||||||
### v2.18.1
|
### v2.18.1
|
||||||
|
|
||||||
|
_20 May 2024_
|
||||||
|
|
||||||
- 🌟 Add free-threaded Linux and Windows builds for 3.13. New identifiers `cp313t-*`, new option `CIBW_FREE_THREADED_SUPPORT`/`tool.cibuildwheel.free-threaded-support` required to opt-in. [See the docs](https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support) for more information. (#1831)
|
- 🌟 Add free-threaded Linux and Windows builds for 3.13. New identifiers `cp313t-*`, new option `CIBW_FREE_THREADED_SUPPORT`/`tool.cibuildwheel.free-threaded-support` required to opt-in. [See the docs](https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support) for more information. (#1831)
|
||||||
- ✨ The `container-engine` is now a build (non-global) option. (#1792)
|
- ✨ The `container-engine` is now a build (non-global) option. (#1792)
|
||||||
- 🛠 The build backend for cibuildwheel is now hatchling. (#1297)
|
- 🛠 The build backend for cibuildwheel is now hatchling. (#1297)
|
||||||
@@ -88,7 +191,7 @@ _12 May 2024_
|
|||||||
_11 March 2024_
|
_11 March 2024_
|
||||||
|
|
||||||
- 🌟 Adds the ability to inherit configuration in TOML overrides. This makes certain configurations much simpler. If you're overriding an option like `before-build` or `environment`, and you just want to add an extra command or environment variable, you can just append (or prepend) to the previous config. See [the docs](https://cibuildwheel.pypa.io/en/stable/options/#inherit) for more information. (#1730)
|
- 🌟 Adds the ability to inherit configuration in TOML overrides. This makes certain configurations much simpler. If you're overriding an option like `before-build` or `environment`, and you just want to add an extra command or environment variable, you can just append (or prepend) to the previous config. See [the docs](https://cibuildwheel.pypa.io/en/stable/options/#inherit) for more information. (#1730)
|
||||||
- 🌟 Adds official support for native `arm64` macOS GitHub runners. To use them, just specify `macos-14` as an `os` of your job in your workflow file. You can also keep `macos-13` in your build matrix to build `x86_64`. Check out the new [GitHub Actions example config](https://cibuildwheel.pypa.io/en/stable/setup/#github-actions).
|
- 🌟 Adds official support for native `arm64` macOS GitHub runners. To use them, just specify `macos-latest` as an `os` of your job in your workflow file. You can also keep `macos-15-intel` in your build matrix to build `x86_64`. Check out the new [GitHub Actions example config](https://cibuildwheel.pypa.io/en/stable/setup/#github-actions).
|
||||||
- ✨ You no longer need to specify `--platform` to run cibuildwheel locally! Instead it will detect your platform automatically. This was a safety feature, no longer necessary. (#1727)
|
- ✨ You no longer need to specify `--platform` to run cibuildwheel locally! Instead it will detect your platform automatically. This was a safety feature, no longer necessary. (#1727)
|
||||||
- 🛠 Removed setuptools and wheel pinned versions. This only affects old-style projects without a `pyproject.toml`, projects with `pyproject.toml` are already getting fresh versions of their `build-system.requires` installed into an isolated environment. (#1725)
|
- 🛠 Removed setuptools and wheel pinned versions. This only affects old-style projects without a `pyproject.toml`, projects with `pyproject.toml` are already getting fresh versions of their `build-system.requires` installed into an isolated environment. (#1725)
|
||||||
- 🛠 Improve how the GitHub Action passes arguments (#1757)
|
- 🛠 Improve how the GitHub Action passes arguments (#1757)
|
||||||
@@ -105,7 +208,7 @@ _11 March 2024_
|
|||||||
_30 January 2024_
|
_30 January 2024_
|
||||||
|
|
||||||
- 🐛 Fix an incompatibility with the GitHub Action and new GitHub Runner images for Windows that bundle Powershell 7.3+ (#1741)
|
- 🐛 Fix an incompatibility with the GitHub Action and new GitHub Runner images for Windows that bundle Powershell 7.3+ (#1741)
|
||||||
- 🛠 Preliminary support for new `macos-14` arm64 runners (#1743)
|
- 🛠 Preliminary support for new `macos-latest` arm64 runners (#1743)
|
||||||
|
|
||||||
### v2.16.4
|
### v2.16.4
|
||||||
|
|
||||||
|
|||||||
+28
-10
@@ -17,11 +17,11 @@ Everyone contributing to the cibuildwheel project is expected to follow the [PSF
|
|||||||
- `cibuildwheel` should wrap the complexity of wheel building.
|
- `cibuildwheel` should wrap the complexity of wheel building.
|
||||||
- The user interface to `cibuildwheel` is the build script (e.g. `.travis.yml`). Feature additions should not increase the complexity of this script.
|
- The user interface to `cibuildwheel` is the build script (e.g. `.travis.yml`). Feature additions should not increase the complexity of this script.
|
||||||
- Options should be environment variables (these lend themselves better to YML config files). They should be prefixed with `CIBW_`.
|
- Options should be environment variables (these lend themselves better to YML config files). They should be prefixed with `CIBW_`.
|
||||||
- Options should be generalise to all platforms. If platform-specific options are required, they should be namespaced e.g. `CIBW_TEST_COMMAND_MACOS`
|
- Options should be generalised to all platforms. If platform-specific options are required, they should be namespaced e.g. `CIBW_TEST_COMMAND_MACOS`
|
||||||
|
|
||||||
Other notes:
|
Other notes:
|
||||||
|
|
||||||
- The platforms are very similar, until they're not. I'd rather have straight-forward code than totally DRY code, so let's keep airy platform abstractions to a minimum.
|
- The platforms are very similar, until they're not. I'd rather have straightforward code than totally DRY code, so let's keep airy platform abstractions to a minimum.
|
||||||
- I might want to break the options into a shared config file one day, so that config is more easily shared. That has motivated some of the design decisions.
|
- I might want to break the options into a shared config file one day, so that config is more easily shared. That has motivated some of the design decisions.
|
||||||
|
|
||||||
### cibuildwheel's relationship with build errors
|
### cibuildwheel's relationship with build errors
|
||||||
@@ -82,14 +82,11 @@ A few notes-
|
|||||||
|
|
||||||
- Running the macOS integration tests requires _system installs_ of Python from python.org for all the versions that are tested. We won't attempt to install these when running locally, but you can do so manually using the URL in the error message that is printed when the install is not found.
|
- Running the macOS integration tests requires _system installs_ of Python from python.org for all the versions that are tested. We won't attempt to install these when running locally, but you can do so manually using the URL in the error message that is printed when the install is not found.
|
||||||
|
|
||||||
#### Making a venv
|
#### Running pytest directly
|
||||||
|
|
||||||
More advanced users might prefer to invoke pytest directly-
|
More advanced users might prefer to invoke pytest directly. Set up a [dev environment](#setting-up-a-dev-environment), then,
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 -m venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install -e .[dev]
|
|
||||||
# run the unit tests
|
# run the unit tests
|
||||||
pytest unit_test
|
pytest unit_test
|
||||||
# run the whole integration test suite
|
# run the whole integration test suite
|
||||||
@@ -102,7 +99,7 @@ CIBW_PLATFORM=linux pytest test -k test_build_frontend_args
|
|||||||
|
|
||||||
### Linting, docs
|
### Linting, docs
|
||||||
|
|
||||||
Most developer tasks have a nox interface. This allows you to very simply run tasks without worrying about setting up a development environment (as shown below). This is a slower than setting up a development environment and reusing it, but has the (important) benefit of being highly reproducible; an earlier run does not affect a current run, or anything else on your machine.
|
Most developer tasks have a nox interface. This allows you to very simply run tasks without worrying about setting up a development environment (as shown below). This is slower than setting up a development environment and reusing it, but has the (important) benefit of being highly reproducible; an earlier run does not affect a current run, or anything else on your machine.
|
||||||
|
|
||||||
You can see a list of sessions by typing `nox -l`; here are a few common ones:
|
You can see a list of sessions by typing `nox -l`; here are a few common ones:
|
||||||
|
|
||||||
@@ -113,12 +110,33 @@ nox -s docs # Build and serve the documentation
|
|||||||
nox -s build # Make SDist and wheel
|
nox -s build # Make SDist and wheel
|
||||||
```
|
```
|
||||||
|
|
||||||
More advanced users can run the update scripts. `update_pins` should work directly, but `update_constraints` needs all versions of Python installed. If you don't want to do that locally, a fast way to run it to use docker to run nox:
|
More advanced users can run the update scripts:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
docker run --rm -itv $PWD:/src -w /src quay.io/pypa/manylinux_2_24_x86_64:latest pipx run nox -s update_constraints
|
nox -s update_constraints # update all constraints files in cibuildwheel/resources
|
||||||
|
nox -s update_pins # update tools, python interpreters & docker images used by cibuildwheel
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Setting up a dev environment
|
||||||
|
|
||||||
|
A dev environment isn't required for any of the `nox` tasks above. However, a dev environment is still useful, to be able to point an editor at, and a few other jobs.
|
||||||
|
|
||||||
|
cibuildwheel uses dependency groups. Set up a dev environment with UV by doing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you're not using `uv`, you can do:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pipx run dependency-groups dev | xargs pip install -e.
|
||||||
|
```
|
||||||
|
|
||||||
|
Your virtualenv is at `.venv`.
|
||||||
|
|
||||||
## Maintainer notes
|
## Maintainer notes
|
||||||
|
|
||||||
### Testing sample configs
|
### Testing sample configs
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Building Python wheels with modern C++ standards (C++11 and later) requires a fe
|
|||||||
|
|
||||||
|
|
||||||
## manylinux1 and C++14
|
## manylinux1 and C++14
|
||||||
The old `manylinux1` image (based on CentOS 5) contains a version of GCC and libstdc++ that only supports C++11 and earlier standards. There are however ways to compile wheels with the C++14 standard (and later): https://github.com/pypa/manylinux/issues/118
|
The past end-of-life `manylinux1` image (based on CentOS 5) contains a version of GCC and libstdc++ that only supports C++11 and earlier standards. There are however ways to compile wheels with the C++14 standard (and later): https://github.com/pypa/manylinux/issues/118
|
||||||
|
|
||||||
`manylinux2010` and `manylinux2014` are newer and support all C++ standards (up to C++17).
|
`manylinux2010` and `manylinux2014` are newer and support all C++ standards (up to C++17).
|
||||||
|
|
||||||
@@ -18,9 +18,8 @@ OS X/macOS allows you to specify a so-called "deployment target" version that wi
|
|||||||
|
|
||||||
However, to enable modern C++ standards, the deployment target needs to be set high enough (since older OS X/macOS versions did not have the necessary modern C++ standard library).
|
However, to enable modern C++ standards, the deployment target needs to be set high enough (since older OS X/macOS versions did not have the necessary modern C++ standard library).
|
||||||
|
|
||||||
To get C++11 and C++14 support, `MACOSX_DEPLOYMENT_TARGET` needs to be set to (at least) `"10.9"`. By default, `cibuildwheel` already does this, building 64-bit-only wheels for macOS 10.9 and later.
|
|
||||||
|
|
||||||
To get C++17 support, Xcode 9.3+ is needed, requiring at least macOS 10.13 on the build machine. To use C++17 library features and link against the C++ runtime library, set `MACOSX_DEPLOYMENT_TARGET` to `"10.13"` or `"10.14"` (or higher) - macOS 10.13 offers partial C++17 support (e.g., the filesystem header is in experimental, offering `#include <experimental/filesystem>` instead of `#include <filesystem>`); macOS 10.14 has full C++17 support.
|
To get C++17 support, Xcode 9.3+ is needed, requiring at least macOS 10.13 on the build machine. To use C++17 library features and link against the C++ runtime library, set `MACOSX_DEPLOYMENT_TARGET` to `"10.13"` or `"10.14"` (or higher) - macOS 10.13 offers partial C++17 support (e.g., the filesystem header is in experimental, offering `#include <experimental/filesystem>` instead of `#include <filesystem>`); macOS 10.14 has full C++17 support. CPython 3.12+ require 10.13+ anyway.
|
||||||
|
|
||||||
However, if only C++17 compiler and standard template library (STL) features are used (not needing a C++17 runtime) it might be possible to set `MACOSX_DEPLOYMENT_TARGET` to a lower value, such as `"10.9"`. To find out if this is the case, try compiling and running with a lower `MACOSX_DEPLOYMENT_TARGET`: if C++17 features are used that require a more recent deployment target, building the wheel should fail.
|
However, if only C++17 compiler and standard template library (STL) features are used (not needing a C++17 runtime) it might be possible to set `MACOSX_DEPLOYMENT_TARGET` to a lower value, such as `"10.9"`. To find out if this is the case, try compiling and running with a lower `MACOSX_DEPLOYMENT_TARGET`: if C++17 features are used that require a more recent deployment target, building the wheel should fail.
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ This requires setting this GitHub workflow in your project's PyPI settings (for
|
|||||||
|
|
||||||
You should use Dependabot to keep the publish action up to date. In the above
|
You should use Dependabot to keep the publish action up to date. In the above
|
||||||
example, the same name (the default, "artifact" is used for all upload-artifact
|
example, the same name (the default, "artifact" is used for all upload-artifact
|
||||||
runs, so we can just download all of the in one step into a common directory.
|
runs, so we can just download all of them in one step into a common directory.
|
||||||
|
|
||||||
See
|
See
|
||||||
[`examples/github-deploy.yml`](https://github.com/pypa/cibuildwheel/blob/main/examples/github-deploy.yml)
|
[`examples/github-deploy.yml`](https://github.com/pypa/cibuildwheel/blob/main/examples/github-deploy.yml)
|
||||||
|
|||||||
@@ -258,6 +258,16 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rst-content table.docutils td code,
|
||||||
|
.rst-content table.docutils th code,
|
||||||
|
.rst-content table.field-list td code,
|
||||||
|
.rst-content table.field-list th code,
|
||||||
|
.wy-table td code,
|
||||||
|
.wy-table th code {
|
||||||
|
/* table elements are already made smaller, the code styling on top of that makes the text too small */
|
||||||
|
font-size: 82.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* expand all the toctree entries */
|
/* expand all the toctree entries */
|
||||||
.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,
|
.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,
|
||||||
|
|||||||
+8
-8
@@ -10,7 +10,7 @@ title: Tips and tricks
|
|||||||
|
|
||||||
Linux wheels are built in [`manylinux`/`musllinux` containers](https://github.com/pypa/manylinux) to provide binary compatible wheels on Linux, according to [PEP 600](https://www.python.org/dev/peps/pep-0600/) / [PEP 656](https://www.python.org/dev/peps/pep-0656/). Because of this, when building with `cibuildwheel` on Linux, a few things should be taken into account:
|
Linux wheels are built in [`manylinux`/`musllinux` containers](https://github.com/pypa/manylinux) to provide binary compatible wheels on Linux, according to [PEP 600](https://www.python.org/dev/peps/pep-0600/) / [PEP 656](https://www.python.org/dev/peps/pep-0656/). Because of this, when building with `cibuildwheel` on Linux, a few things should be taken into account:
|
||||||
|
|
||||||
- Programs and libraries are not installed on the CI runner host, but rather should be installed inside the container - using `yum` for `manylinux2010` or `manylinux2014`, `apt-get` for `manylinux_2_24`, `dnf` for `manylinux_2_28` and `apk` for `musllinux_1_1` or `musllinux_1_2`, or manually. The same goes for environment variables that are potentially needed to customize the wheel building.
|
- Programs and libraries are not installed on the CI runner host, but rather should be installed inside the container - using `yum` for `manylinux2010` or `manylinux2014`, `apt-get` for `manylinux_2_24`/`manylinux_2_31`, `dnf` for `manylinux_2_28` and `apk` for `musllinux_1_1` or `musllinux_1_2`, or manually. The same goes for environment variables that are potentially needed to customize the wheel building.
|
||||||
|
|
||||||
`cibuildwheel` supports this by providing the [`CIBW_ENVIRONMENT`](options.md#environment) and [`CIBW_BEFORE_ALL`](options.md#before-all) options to setup the build environment inside the running container.
|
`cibuildwheel` supports this by providing the [`CIBW_ENVIRONMENT`](options.md#environment) and [`CIBW_BEFORE_ALL`](options.md#before-all) options to setup the build environment inside the running container.
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ See [GitHub issue 1333](https://github.com/pypa/cibuildwheel/issues/1333) for mo
|
|||||||
|
|
||||||
It's easiest to build `x86_64` wheels on `x86_64` runners, and `arm64` wheels on `arm64` runners.
|
It's easiest to build `x86_64` wheels on `x86_64` runners, and `arm64` wheels on `arm64` runners.
|
||||||
|
|
||||||
On GitHub Actions, `macos-14` runners are `arm64`, and `macos-13` runners are `x86_64`. So all you need to do is ensure both are in your build matrix.
|
On GitHub Actions, `macos-latest` runners are `arm64`, and `macos-15-intel` runners are `x86_64`. So all you need to do is ensure both are in your build matrix.
|
||||||
|
|
||||||
#### Cross-compiling
|
#### Cross-compiling
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ myextension = Extension(
|
|||||||
|
|
||||||
### Automatic updates using Dependabot {: #automatic-updates}
|
### Automatic updates using Dependabot {: #automatic-updates}
|
||||||
|
|
||||||
Selecting a moving target (like the latest release) is generally a bad idea in CI. If something breaks, you can't tell whether it was your code or an upstream update that caused the breakage, and in a worse-case scenario, it could occur during a release.
|
Selecting a moving target (like the latest release) is generally a bad idea in CI. If something breaks, you can't tell whether it was your code or an upstream update that caused the breakage, and in a worst-case scenario, it could occur during a release.
|
||||||
|
|
||||||
There are two suggested methods for keeping cibuildwheel up to date that instead involve scheduled pull requests using GitHub's Dependabot.
|
There are two suggested methods for keeping cibuildwheel up to date that instead involve scheduled pull requests using GitHub's Dependabot.
|
||||||
|
|
||||||
@@ -142,7 +142,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:
|
If you use GitHub Actions for builds, you can use cibuildwheel as an action:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: pypa/cibuildwheel@v2.20.0
|
uses: pypa/cibuildwheel@v2.23.4
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
||||||
@@ -164,7 +164,7 @@ The second option, and the only one that supports other CI systems, is using a `
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# requirements-cibw.txt
|
# requirements-cibw.txt
|
||||||
cibuildwheel==2.20.0
|
cibuildwheel==2.23.4
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
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:
|
||||||
@@ -184,7 +184,7 @@ This will also try to update other pins in all requirement files, so be sure you
|
|||||||
### Alternatives to cibuildwheel options {: #cibw-options-alternatives}
|
### Alternatives to cibuildwheel options {: #cibw-options-alternatives}
|
||||||
|
|
||||||
cibuildwheel provides lots of opportunities to configure the build
|
cibuildwheel provides lots of opportunities to configure the build
|
||||||
environment. However, you might consider adding this build configuration into
|
environment. However, you might consider adding this build configuration into
|
||||||
the package itself - in general, this is preferred, because users of your
|
the package itself - in general, this is preferred, because users of your
|
||||||
package 'sdist' will also benefit.
|
package 'sdist' will also benefit.
|
||||||
|
|
||||||
@@ -328,7 +328,7 @@ Solutions to this vary, but the simplest is to use pipx:
|
|||||||
# most runners have pipx preinstalled, but in case you don't
|
# most runners have pipx preinstalled, but in case you don't
|
||||||
python3 -m pip install pipx
|
python3 -m pip install pipx
|
||||||
|
|
||||||
pipx run cibuildwheel==2.20.0 --output-dir wheelhouse
|
pipx run cibuildwheel==2.23.4 --output-dir wheelhouse
|
||||||
pipx run twine upload wheelhouse/*.whl
|
pipx run twine upload wheelhouse/*.whl
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -363,7 +363,7 @@ If you're building on an arm64 runner, you might notice something strange about
|
|||||||
|
|
||||||
This is fine for simple C extensions, but for more complicated builds on arm64 it becomes an issue.
|
This is fine for simple C extensions, but for more complicated builds on arm64 it becomes an issue.
|
||||||
|
|
||||||
So, if you want to build macOS arm64 wheels on an arm64 runner (e.g., `macos-14`) on Python 3.8, before invoking cibuildwheel, you should install a native arm64 Python 3.8 interpreter on the runner:
|
So, if you want to build macOS arm64 wheels on an arm64 runner (e.g., `macos-latest`) on Python 3.8, before invoking cibuildwheel, you should install a native arm64 Python 3.8 interpreter on the runner:
|
||||||
|
|
||||||
|
|
||||||
!!! tab "GitHub Actions"
|
!!! tab "GitHub Actions"
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ from typing import Any
|
|||||||
def define_env(env: Any) -> None:
|
def define_env(env: Any) -> None:
|
||||||
"Hook function for mkdocs-macros"
|
"Hook function for mkdocs-macros"
|
||||||
|
|
||||||
@env.macro
|
@env.macro # type: ignore[misc]
|
||||||
def subprocess_run(*args: str) -> str:
|
def subprocess_run(*args: str) -> str:
|
||||||
"Run a subprocess and return the stdout"
|
"Run a subprocess and return the stdout"
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
|
|||||||
+167
-98
@@ -288,25 +288,36 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat
|
|||||||
|
|
||||||
<div class="build-id-table-marker"></div>
|
<div class="build-id-table-marker"></div>
|
||||||
|
|
||||||
| | macOS | Windows | Linux Intel | Linux Other |
|
| | 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.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-manylinux_armv7l<br/>cp36-musllinux_aarch64<br/>cp36-musllinux_ppc64le<br/>cp36-musllinux_s390x<br/>cp36-musllinux_armv7l |
|
||||||
| 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.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-manylinux_armv7l<br/>cp37-musllinux_aarch64<br/>cp37-musllinux_ppc64le<br/>cp37-musllinux_s390x<br/>cp37-musllinux_armv7l |
|
||||||
| 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.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-manylinux_armv7l<br/>cp38-musllinux_aarch64<br/>cp38-musllinux_ppc64le<br/>cp38-musllinux_s390x<br/>cp38-musllinux_armv7l |
|
||||||
| 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.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-manylinux_armv7l<br/>cp39-musllinux_aarch64<br/>cp39-musllinux_ppc64le<br/>cp39-musllinux_s390x<br/>cp39-musllinux_armv7l |
|
||||||
| 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.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-manylinux_armv7l<br/>cp310-musllinux_aarch64<br/>cp310-musllinux_ppc64le<br/>cp310-musllinux_s390x<br/>cp310-musllinux_armv7l |
|
||||||
| 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.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-manylinux_armv7l<br/>cp311-musllinux_aarch64<br/>cp311-musllinux_ppc64le<br/>cp311-musllinux_s390x<br/>cp311-musllinux_armv7l |
|
||||||
| 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 |
|
| 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_armv7l<br/>cp312-musllinux_ppc64le<br/>cp312-musllinux_s390x<br/>cp312-musllinux_armv7l |
|
||||||
| Python 3.13 | cp313-macosx_x86_64<br/>cp313-macosx_universal2<br/>cp313-macosx_arm64 | cp313-win_amd64<br/>cp313-win32<br/>cp313-win_arm64 | cp313-manylinux_x86_64<br/>cp313-manylinux_i686<br/>cp313-musllinux_x86_64<br/>cp313-musllinux_i686 | cp313-manylinux_aarch64<br/>cp313-manylinux_ppc64le<br/>cp313-manylinux_s390x<br/>cp313-musllinux_aarch64<br/>cp313-musllinux_ppc64le<br/>cp313-musllinux_s390x |
|
| Python 3.13 | cp313-macosx_x86_64<br/>cp313-macosx_universal2<br/>cp313-macosx_arm64 | cp313-win_amd64<br/>cp313-win32<br/>cp313-win_arm64 | cp313-manylinux_x86_64<br/>cp313-manylinux_i686<br/>cp313-musllinux_x86_64<br/>cp313-musllinux_i686 | cp313-manylinux_aarch64<br/>cp313-manylinux_ppc64le<br/>cp313-manylinux_s390x<br/>cp313-manylinux_armv7l<br/>cp313-musllinux_aarch64<br/>cp313-musllinux_ppc64le<br/>cp313-musllinux_s390x<br/>cp313-musllinux_armv7l |
|
||||||
| PyPy3.7 v7.3 | pp37-macosx_x86_64 | pp37-win_amd64 | pp37-manylinux_x86_64<br/>pp37-manylinux_i686 | pp37-manylinux_aarch64 |
|
| 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.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.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 |
|
| 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 |
|
||||||
|
| PyPy3.11 v7.3 | pp311-macosx_x86_64<br/>pp311-macosx_arm64 | pp311-win_amd64 | pp311-manylinux_x86_64<br/>pp311-manylinux_i686 | pp311-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 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).
|
The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details).
|
||||||
|
|
||||||
For CPython, the minimally supported macOS version is 10.9; for PyPy 3.7, macOS 10.13 or higher is required.
|
The lowest value you can set `MACOSX_DEPLOYMENT_TARGET` is as follows:
|
||||||
|
|
||||||
|
| Arch | Python version range | Minimum target |
|
||||||
|
|-------|----------------------|----------------|
|
||||||
|
| Intel | CPython 3.6-3.11 | 10.9 |
|
||||||
|
| Intel | CPython 3.12+ | 10.13 |
|
||||||
|
| AS | CPython or PyPy | 11 |
|
||||||
|
| Intel | PyPy 3.7-3.8 | 10.13 |
|
||||||
|
| Intel | PyPy 3.9+ | 10.15 |
|
||||||
|
|
||||||
|
If you set the value lower, cibuildwheel will cap it to the lowest supported value for each target as needed.
|
||||||
|
|
||||||
Windows arm64 platform support is experimental.
|
Windows arm64 platform support is experimental.
|
||||||
|
|
||||||
@@ -412,52 +423,6 @@ See the [cibuildwheel 1 documentation](https://cibuildwheel.pypa.io/en/1.x/) for
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
### `CIBW_FREE_THREADED_SUPPORT` {: #free-threaded-support}
|
|
||||||
|
|
||||||
> Choose whether free-threaded variants should be built
|
|
||||||
|
|
||||||
[PEP 703](https://www.python.org/dev/peps/pep-0703) introduced variants of CPython that can be built without the Global Interpreter Lock (GIL).
|
|
||||||
Those variants are also known as free-threaded / no-gil.
|
|
||||||
|
|
||||||
Building for free-threaded variants is disabled by default.
|
|
||||||
|
|
||||||
Building can be enabled by setting this option to `true`. The free-threaded compatible wheels will be built in addition to the standard wheels.
|
|
||||||
|
|
||||||
This option doesn't support overrides.
|
|
||||||
If you need to enable/disable it per platform or python version, set this option to `true` and use [`CIBW_BUILD`](#build-skip)/[`CIBW_SKIP`](#build-skip) options to filter the builds.
|
|
||||||
|
|
||||||
The build identifiers for those variants have a `t` suffix in their `python_tag` (e.g. `cp313t-manylinux_x86_64`)
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
This feature is experimental: [What’s New In Python 3.13](https://docs.python.org/3.13/whatsnew/3.13.html#free-threaded-cpython)
|
|
||||||
|
|
||||||
#### Examples
|
|
||||||
|
|
||||||
!!! tab examples "Environment variables"
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# Enable free-threaded support
|
|
||||||
CIBW_FREE_THREADED_SUPPORT: 1
|
|
||||||
|
|
||||||
# Skip building free-threaded compatible wheels on Windows
|
|
||||||
CIBW_FREE_THREADED_SUPPORT: 1
|
|
||||||
CIBW_SKIP: *t-win*
|
|
||||||
```
|
|
||||||
|
|
||||||
It is generally recommended to use `free-threaded-support` in a config file as you can statically declare that you
|
|
||||||
support free-threaded builds.
|
|
||||||
|
|
||||||
!!! tab examples "pyproject.toml"
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[tool.cibuildwheel]
|
|
||||||
# Enable free-threaded support
|
|
||||||
free-threaded-support = true
|
|
||||||
|
|
||||||
# Skip building free-threaded compatible wheels on Windows
|
|
||||||
free-threaded-support = true
|
|
||||||
skip = "*t-win*"
|
|
||||||
```
|
|
||||||
|
|
||||||
### `CIBW_ARCHS` {: #archs}
|
### `CIBW_ARCHS` {: #archs}
|
||||||
> Change the architectures built on your machine by default.
|
> Change the architectures built on your machine by default.
|
||||||
@@ -475,7 +440,7 @@ machine, provided the cross-compiling tools are installed.
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
- Linux: `x86_64` `i686` `aarch64` `ppc64le` `s390x`
|
- Linux: `x86_64` `i686` `aarch64` `ppc64le` `s390x` `armv7l`
|
||||||
- macOS: `x86_64` `arm64` `universal2`
|
- macOS: `x86_64` `arm64` `universal2`
|
||||||
- Windows: `AMD64` `x86` `ARM64`
|
- Windows: `AMD64` `x86` `ARM64`
|
||||||
- Pyodide: `wasm32`
|
- Pyodide: `wasm32`
|
||||||
@@ -593,24 +558,53 @@ the package is compatible with all versions of Python that it can build.
|
|||||||
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.6"
|
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.6"
|
||||||
```
|
```
|
||||||
|
|
||||||
### `CIBW_PRERELEASE_PYTHONS` {: #prerelease-pythons}
|
### `CIBW_ENABLE` {: #enable}
|
||||||
> Enable building with pre-release versions of Python if available
|
> Enable building with extra categories of selectors present.
|
||||||
|
|
||||||
|
This option lets you opt-in to non-default builds, like pre-releases and
|
||||||
|
free-threaded Python. These are not included by default to give a nice default
|
||||||
|
for new users, but can be added to the selectors available here. The allowed
|
||||||
|
values are:
|
||||||
|
|
||||||
|
|
||||||
|
- `cypython-prerelease`: Enables beta versions of Pythons if any are available
|
||||||
|
(May-July, approximately). For backward compatibility, `CIBW_PRERELEASE_PYTHONS`
|
||||||
|
is also supported until cibuildwheel 3.
|
||||||
|
- `cpython-freethreading`: [PEP 703](https://www.python.org/dev/peps/pep-0703)
|
||||||
|
introduced variants of CPython that can be built without the Global
|
||||||
|
Interpreter Lock (GIL). Those variants are also known as free-threaded /
|
||||||
|
no-gil. This will enable building these wheels while they are experimental.
|
||||||
|
The build identifiers for those variants have a `t` suffix in their
|
||||||
|
`python_tag` (e.g. `cp313t-manylinux_x86_64`). For backward compatibility,
|
||||||
|
`CIBW_FREE_THREADED_SUPPORT` is also supported until cibuildwheel 3.
|
||||||
|
- `pypy`: Enable PyPy. For backward compatibility, this is always enabled until
|
||||||
|
cibuildwheel 3 is released.
|
||||||
|
|
||||||
During the beta period, when new versions of Python are being tested,
|
|
||||||
cibuildwheel will often gain early support for beta releases. If you would
|
|
||||||
like to test wheel building with these versions, you can enable this flag.
|
|
||||||
|
|
||||||
!!! caution
|
!!! caution
|
||||||
This option is provided for testing purposes only. It is not
|
`cpython-prerelease` is provided for testing purposes only. It is not
|
||||||
recommended to distribute wheels built when `CIBW_PRERELEASE_PYTHONS` is
|
recommended to distribute wheels built with beta releases, such as
|
||||||
set, such as uploading to PyPI. Please _do not_ upload these wheels to
|
uploading to PyPI. Please _do not_ upload these wheels to PyPI, as they are
|
||||||
PyPI, as they are not guaranteed to work with the final Python release.
|
not guaranteed to work with the final Python release. Once Python is ABI
|
||||||
Once Python is ABI stable and enters the release candidate phase, that
|
stable and enters the release candidate phase, that version of Python will
|
||||||
version of Python will become available without this flag.
|
become available without this flag.
|
||||||
|
|
||||||
Default: Off (0) if Python is available in beta phase. No effect otherwise.
|
!!! note
|
||||||
|
Free threading is experimental: [What’s New In Python 3.13](https://docs.python.org/3.13/whatsnew/3.13.html#free-threaded-cpython)
|
||||||
|
|
||||||
|
Default: empty (`pypy` is always injected).
|
||||||
|
|
||||||
|
This option doesn't support overrides or platform specific variants; it is
|
||||||
|
intended as a way to acknowledge that a project is aware that these extra
|
||||||
|
selectors exist. If you need to enable/disable it per platform or python
|
||||||
|
version, set this option to `true` and use
|
||||||
|
[`CIBW_BUILD`](#build-skip)/[`CIBW_SKIP`](#build-skip) options to filter the
|
||||||
|
builds.
|
||||||
|
|
||||||
|
Unlike all other cibuildwheel options, the environment variable setting will
|
||||||
|
only add to the TOML config; you can't remove an enable by setting an empty or
|
||||||
|
partial list in environment variables; use `CIBW_SKIP` instead.
|
||||||
|
|
||||||
This option can also be set using the [command-line option](#command-line) `--prerelease-pythons`. This option is not available in the `pyproject.toml` config.
|
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
@@ -618,9 +612,38 @@ This option can also be set using the [command-line option](#command-line) `--pr
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Include latest Python beta
|
# Include latest Python beta
|
||||||
CIBW_PRERELEASE_PYTHONS: True
|
CIBW_ENABLE: cpython-prerelease
|
||||||
|
|
||||||
|
# Include free-threaded support
|
||||||
|
CIBW_ENABLE: cpython-freethreading
|
||||||
|
|
||||||
|
# Include both
|
||||||
|
CIBW_ENABLE: cpython-prerelease cpython-freethreading
|
||||||
|
|
||||||
|
# Skip building free-threaded compatible wheels on Windows
|
||||||
|
CIBW_ENABLE: cpython-freethreading
|
||||||
|
CIBW_SKIP: *t-win*
|
||||||
```
|
```
|
||||||
|
|
||||||
|
It is generally recommended to use `cpython-freethreading` in a config
|
||||||
|
file as you can statically declare that you support free-threaded builds.
|
||||||
|
|
||||||
|
!!! tab examples "pyproject.toml"
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.cibuildwheel]
|
||||||
|
# Enable free-threaded support
|
||||||
|
enable = ["cpython-freethreading"]
|
||||||
|
|
||||||
|
# Skip building free-threaded compatible wheels on Windows
|
||||||
|
enable = ["cpython-freethreading"]
|
||||||
|
skip = "*t-win*"
|
||||||
|
```
|
||||||
|
|
||||||
|
It is generally not recommended to use `cpython-prerelease` in a config file,
|
||||||
|
as it's intended for testing pre-releases for a 2-3 month period only.
|
||||||
|
|
||||||
|
|
||||||
### `CIBW_ALLOW_EMPTY` {: #allow-empty}
|
### `CIBW_ALLOW_EMPTY` {: #allow-empty}
|
||||||
> Suppress the error code if no wheels match the specified build identifiers
|
> Suppress the error code if no wheels match the specified build identifiers
|
||||||
|
|
||||||
@@ -953,9 +976,9 @@ Platform-specific environment variables also available:<br/>
|
|||||||
|
|
||||||
In configuration files, you can use a TOML array, and each line will be run sequentially - joined with `&&`.
|
In configuration files, you can use a TOML array, and each line will be run sequentially - joined with `&&`.
|
||||||
|
|
||||||
Note that manylinux_2_24 builds occur inside a Debian9 docker, where
|
Note that manylinux_2_24/manylinux_2_31 builds occur inside a debian derivative docker container, where
|
||||||
manylinux2010 and manylinux2014 builds occur inside a CentOS one. So for
|
manylinux2010 and manylinux2014 builds occur inside a CentOS one. So for
|
||||||
`manylinux_2_24` the `CIBW_BEFORE_ALL_LINUX` command must use `apt-get -y`
|
`manylinux_2_24`/`manylinux_2_31` the `CIBW_BEFORE_ALL_LINUX` command must use `apt-get -y`
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
### `CIBW_BEFORE_BUILD` {: #before-build}
|
### `CIBW_BEFORE_BUILD` {: #before-build}
|
||||||
@@ -1110,6 +1133,7 @@ Platform-specific environment variables are also available:<br/>
|
|||||||
delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} &&
|
delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} &&
|
||||||
pipx run abi3audit --strict --report {wheel}
|
pipx run abi3audit --strict --report {wheel}
|
||||||
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >
|
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: >
|
||||||
|
copy {wheel} {dest_dir} &&
|
||||||
pipx run abi3audit --strict --report {wheel}
|
pipx run abi3audit --strict --report {wheel}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1148,7 +1172,10 @@ Platform-specific environment variables are also available:<br/>
|
|||||||
"pipx run abi3audit --strict --report {wheel}",
|
"pipx run abi3audit --strict --report {wheel}",
|
||||||
]
|
]
|
||||||
[tool.cibuildwheel.windows]
|
[tool.cibuildwheel.windows]
|
||||||
repair-wheel-command = "pipx run abi3audit --strict --report {wheel}"
|
repair-wheel-command = [
|
||||||
|
"copy {wheel} {dest_dir}",
|
||||||
|
"pipx run abi3audit --strict --report {wheel}",
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
In configuration mode, you can use an inline array, and the items will be joined with `&&`.
|
In configuration mode, you can use an inline array, and the items will be joined with `&&`.
|
||||||
@@ -1157,28 +1184,36 @@ Platform-specific environment variables are also available:<br/>
|
|||||||
<div class="link-target" id="manylinux-image"></div>
|
<div class="link-target" id="manylinux-image"></div>
|
||||||
|
|
||||||
### `CIBW_MANYLINUX_*_IMAGE`, `CIBW_MUSLLINUX_*_IMAGE` {: #linux-image}
|
### `CIBW_MANYLINUX_*_IMAGE`, `CIBW_MUSLLINUX_*_IMAGE` {: #linux-image}
|
||||||
> Specify alternative manylinux / musllinux container images
|
|
||||||
|
|
||||||
The available options are (default value):
|
> Specify manylinux / musllinux container images
|
||||||
|
|
||||||
- `CIBW_MANYLINUX_X86_64_IMAGE` ([`quay.io/pypa/manylinux2014_x86_64`](https://quay.io/pypa/manylinux2014_x86_64))
|
The available options are:
|
||||||
- `CIBW_MANYLINUX_I686_IMAGE` ([`quay.io/pypa/manylinux2014_i686`](https://quay.io/pypa/manylinux2014_i686))
|
|
||||||
- `CIBW_MANYLINUX_PYPY_X86_64_IMAGE` ([`quay.io/pypa/manylinux2014_x86_64`](https://quay.io/pypa/manylinux2014_x86_64))
|
|
||||||
- `CIBW_MANYLINUX_AARCH64_IMAGE` ([`quay.io/pypa/manylinux2014_aarch64`](https://quay.io/pypa/manylinux2014_aarch64))
|
|
||||||
- `CIBW_MANYLINUX_PPC64LE_IMAGE` ([`quay.io/pypa/manylinux2014_ppc64le`](https://quay.io/pypa/manylinux2014_ppc64le))
|
|
||||||
- `CIBW_MANYLINUX_S390X_IMAGE` ([`quay.io/pypa/manylinux2014_s390x`](https://quay.io/pypa/manylinux2014_s390x))
|
|
||||||
- `CIBW_MANYLINUX_PYPY_AARCH64_IMAGE` ([`quay.io/pypa/manylinux2014_aarch64`](https://quay.io/pypa/manylinux2014_aarch64))
|
|
||||||
- `CIBW_MANYLINUX_PYPY_I686_IMAGE` ([`quay.io/pypa/manylinux2014_i686`](https://quay.io/pypa/manylinux2014_i686))
|
|
||||||
- `CIBW_MUSLLINUX_X86_64_IMAGE` ([`quay.io/pypa/musllinux_1_2_x86_64`](https://quay.io/pypa/musllinux_1_2_x86_64))
|
|
||||||
- `CIBW_MUSLLINUX_I686_IMAGE` ([`quay.io/pypa/musllinux_1_2_i686`](https://quay.io/pypa/musllinux_1_2_i686))
|
|
||||||
- `CIBW_MUSLLINUX_AARCH64_IMAGE` ([`quay.io/pypa/musllinux_1_2_aarch64`](https://quay.io/pypa/musllinux_1_2_aarch64))
|
|
||||||
- `CIBW_MUSLLINUX_PPC64LE_IMAGE` ([`quay.io/pypa/musllinux_1_2_ppc64le`](https://quay.io/pypa/musllinux_1_2_ppc64le))
|
|
||||||
- `CIBW_MUSLLINUX_S390X_IMAGE` ([`quay.io/pypa/musllinux_1_2_s390x`](https://quay.io/pypa/musllinux_1_2_s390x))
|
|
||||||
|
|
||||||
Set an alternative Docker image to be used for building [manylinux / musllinux](https://github.com/pypa/manylinux) wheels.
|
| Option | Default | Future default* |
|
||||||
|
|-----------------------------------|----------------------------------------------------------------|-----------------------------------------------------------------|
|
||||||
|
| CIBW_MANYLINUX_X86_64_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_x86_64) | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_x86_64) |
|
||||||
|
| CIBW_MANYLINUX_I686_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_i686) | |
|
||||||
|
| CIBW_MANYLINUX_PYPY_X86_64_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_x86_64) | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_x86_64) |
|
||||||
|
| CIBW_MANYLINUX_AARCH64_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_aarch64) | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_aarch64) |
|
||||||
|
| CIBW_MANYLINUX_PPC64LE_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_ppc64le) | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_ppc64le) |
|
||||||
|
| CIBW_MANYLINUX_S390X_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_s390x) | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_s390x) |
|
||||||
|
| CIBW_MANYLINUX_ARMV7L_IMAGE | [`manylinux_2_31`](https://quay.io/pypa/manylinux_2_31_armv7l) | |
|
||||||
|
| CIBW_MANYLINUX_PYPY_AARCH64_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_aarch64) | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_aarch64) |
|
||||||
|
| CIBW_MANYLINUX_PYPY_I686_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_i686) | |
|
||||||
|
| CIBW_MUSLLINUX_X86_64_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_x86_64) | |
|
||||||
|
| CIBW_MUSLLINUX_I686_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_i686) | |
|
||||||
|
| CIBW_MUSLLINUX_AARCH64_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_aarch64) | |
|
||||||
|
| CIBW_MUSLLINUX_PPC64LE_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_ppc64le) | |
|
||||||
|
| CIBW_MUSLLINUX_S390X_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_s390x) | |
|
||||||
|
| CIBW_MUSLLINUX_ARMV7L_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_armv7l) | |
|
||||||
|
|
||||||
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
|
<small>* The default is scheduled to change in a cibuildwheel release on or after 6th May 2025 - if you don't want the new default, you should set the value to `manylinux2014`.</small>
|
||||||
|
|
||||||
|
Set the Docker image to be used for building [manylinux / musllinux](https://github.com/pypa/manylinux) wheels.
|
||||||
|
|
||||||
|
For `CIBW_MANYLINUX_*_IMAGE`, except `CIBW_MANYLINUX_ARMV7L_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.
|
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_MANYLINUX_ARMV7L_IMAGE`, the value of this option can either be set to `manylinux_2_31` or a custom image. Support is experimental for now. The `manylinux_2_31` value is only available for `armv7`.
|
||||||
|
|
||||||
For `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.
|
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.
|
||||||
|
|
||||||
@@ -1584,6 +1619,40 @@ Platform-specific environment variables are also available:<br/>
|
|||||||
|
|
||||||
In configuration files, you can use an inline array, and the items will be joined with a comma.
|
In configuration files, you can use an inline array, and the items will be joined with a comma.
|
||||||
|
|
||||||
|
|
||||||
|
### `CIBW_TEST_GROUPS` {: #test-groups}
|
||||||
|
> Specify test dependencies from your project's `dependency-groups`
|
||||||
|
|
||||||
|
List of
|
||||||
|
[dependency-groups](https://peps.python.org/pep-0735)
|
||||||
|
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 `pyproject.toml`.
|
||||||
|
|
||||||
|
Platform-specific environment variables are also available:<br/>
|
||||||
|
`CIBW_TEST_GROUPS_MACOS` | `CIBW_TEST_GROUPS_WINDOWS` | `CIBW_TEST_GROUPS_LINUX` | `CIBW_TEST_GROUPS_PYODIDE`
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
!!! tab examples "Environment variables"
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Will cause the wheel to be installed with these groups of dependencies
|
||||||
|
CIBW_TEST_GROUPS: "test qt"
|
||||||
|
```
|
||||||
|
|
||||||
|
Separate multiple items with a space.
|
||||||
|
|
||||||
|
!!! tab examples "pyproject.toml"
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.cibuildwheel]
|
||||||
|
# Will cause the wheel to be installed with these groups of dependencies
|
||||||
|
test-groups = ["test", "qt"]
|
||||||
|
```
|
||||||
|
|
||||||
|
In configuration files, you can use an inline array, and the items will be joined with a space.
|
||||||
|
|
||||||
### `CIBW_TEST_SKIP` {: #test-skip}
|
### `CIBW_TEST_SKIP` {: #test-skip}
|
||||||
> Skip running tests on some builds
|
> Skip running tests on some builds
|
||||||
|
|
||||||
@@ -1599,7 +1668,7 @@ This option is not supported in the overrides section in `pyproject.toml`.
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Will avoid testing on emulated architectures
|
# Will avoid testing on emulated architectures
|
||||||
CIBW_TEST_SKIP: "*-*linux_{aarch64,ppc64le,s390x}"
|
CIBW_TEST_SKIP: "*-*linux_{aarch64,ppc64le,s390x,armv7l}"
|
||||||
|
|
||||||
# Skip trying to test arm64 builds on Intel Macs
|
# Skip trying to test arm64 builds on Intel Macs
|
||||||
CIBW_TEST_SKIP: "*-macosx_arm64 *-macosx_universal2:arm64"
|
CIBW_TEST_SKIP: "*-macosx_arm64 *-macosx_universal2:arm64"
|
||||||
@@ -1610,7 +1679,7 @@ This option is not supported in the overrides section in `pyproject.toml`.
|
|||||||
```toml
|
```toml
|
||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
# Will avoid testing on emulated architectures
|
# Will avoid testing on emulated architectures
|
||||||
test-skip = "*-*linux_{aarch64,ppc64le,s390x}"
|
test-skip = "*-*linux_{aarch64,ppc64le,s390x,armv7l}"
|
||||||
|
|
||||||
# Skip trying to test arm64 builds on Intel Macs
|
# Skip trying to test arm64 builds on Intel Macs
|
||||||
test-skip = "*-macosx_arm64 *-macosx_universal2:arm64"
|
test-skip = "*-macosx_arm64 *-macosx_universal2:arm64"
|
||||||
|
|||||||
+6
-6
@@ -154,14 +154,14 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# macos-13 is an intel runner, macos-14 is apple silicon
|
# macos-15-intel is an intel runner, macos-latest is apple silicon
|
||||||
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
|
os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
run: pipx run cibuildwheel==2.20.0
|
run: pipx run cibuildwheel==2.23.4
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -188,8 +188,8 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# macos-13 is an intel runner, macos-14 is apple silicon
|
# macos-15-intel is an intel runner, macos-latest is apple silicon
|
||||||
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
|
os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -198,7 +198,7 @@ To build Linux, Mac, and Windows wheels using GitHub Actions, create a `.github/
|
|||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v5
|
||||||
|
|
||||||
- name: Install cibuildwheel
|
- name: Install cibuildwheel
|
||||||
run: python -m pip install cibuildwheel==2.20.0
|
run: python -m pip install cibuildwheel==2.23.4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
run: python -m cibuildwheel --output-dir wheelhouse
|
run: python -m cibuildwheel --output-dir wheelhouse
|
||||||
|
|||||||
+24
-24
@@ -18,8 +18,8 @@ title: Working examples
|
|||||||
| [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. |
|
| [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. |
|
| [MyPy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | The compiled version of MyPy using MyPyC. |
|
||||||
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
|
| [Kivy][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS |
|
||||||
| [MemRay][] | ![github icon][] | ![linux icon][] | Memray is a memory profiler for Python |
|
|
||||||
| [Triton][] | ![github icon][] | ![linux icon][] | Self hosted runners |
|
| [Triton][] | ![github icon][] | ![linux icon][] | Self hosted runners |
|
||||||
|
| [MemRay][] | ![github icon][] | ![linux icon][] | Memray is a memory profiler for Python |
|
||||||
| [uvloop][] | ![github icon][] | ![apple icon][] ![linux icon][] | Ultra fast asyncio event loop. |
|
| [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 |
|
| [psutil][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Cross-platform lib for process and system monitoring in Python |
|
||||||
| [Google Benchmark][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A microbenchmark support library |
|
| [Google Benchmark][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A microbenchmark support library |
|
||||||
@@ -32,18 +32,18 @@ title: Working examples
|
|||||||
| [twisted-iocpsupport][] | ![github icon][] | ![windows icon][] | A submodule of Twisted that hooks into native C APIs using Cython. |
|
| [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 |
|
| [PyOxidizer][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A modern Python application packaging and distribution tool |
|
||||||
| [cvxpy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A Python-embedded modeling language for convex optimization problems. |
|
| [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. |
|
|
||||||
| [pedalboard][] | ![github icon][] | ![windows icon][] ![linux icon][] ![apple icon][] | A Python library for working with audio data and audio plugins by wrapping the [JUCE](https://github.com/juce-framework/JUCE/) C++ framework. Uses cibuildwheel to deploy on as many operating systems and Python versions as possible with only one dependency (any NumPy). |
|
| [pedalboard][] | ![github icon][] | ![windows icon][] ![linux icon][] ![apple icon][] | A Python library for working with audio data and audio plugins by wrapping the [JUCE](https://github.com/juce-framework/JUCE/) C++ framework. Uses cibuildwheel to deploy on as many operating systems and Python versions as possible with only one dependency (any NumPy). |
|
||||||
|
| [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 |
|
| [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 |
|
| [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. |
|
|
||||||
| [aiortc][] | ![github icon][] | ![apple icon][] ![linux icon][] | WebRTC and ORTC implementation for Python using asyncio. |
|
| [aiortc][] | ![github icon][] | ![apple icon][] ![linux icon][] | WebRTC and ORTC implementation for Python using asyncio. |
|
||||||
|
| [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. |
|
||||||
| [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
|
| [Dependency Injector][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Dependency injection framework for Python, uses Windows TravisCI |
|
||||||
| [pyzmq][] | ![github icon][] ![circleci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python bindings for zeromq, the networking library. Uses Cython on CPython and CFFI on PyPy. ARM wheels for linux are built natively on CircleCI. |
|
| [pyzmq][] | ![github icon][] ![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. |
|
||||||
| [Implicit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes GPU support for linux wheels |
|
| [Implicit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes GPU support for linux wheels |
|
||||||
| [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 |
|
|
||||||
| [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. |
|
| [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. |
|
||||||
|
| [tinyobjloader][] | ![azurepipelines icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Tiny but powerful single file wavefront obj loader |
|
||||||
|
| [vispy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Main repository for Vispy |
|
||||||
| [coverage.py][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The coverage tool for Python |
|
| [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 |
|
| [PyCryptodome][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | A self-contained cryptographic library for Python |
|
||||||
| [Line Profiler][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Line-by-line profiling for Python |
|
| [Line Profiler][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Line-by-line profiling for Python |
|
||||||
@@ -78,33 +78,33 @@ title: Working examples
|
|||||||
| [python-rapidjson][] | ![travisci icon][] ![gitlab icon][] ![appveyor icon][] | ![windows icon][] ![linux icon][] | Python wrapper around rapidjson |
|
| [python-rapidjson][] | ![travisci icon][] ![gitlab icon][] ![appveyor icon][] | ![windows icon][] ![linux icon][] | Python wrapper around rapidjson |
|
||||||
| [pybind11 python_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a Python-based build system |
|
| [pybind11 python_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Example pybind11 module built with a Python-based build system |
|
||||||
| [python-snappy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for the snappy google library |
|
| [python-snappy][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Python bindings for the snappy google library |
|
||||||
| [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. |
|
|
||||||
| [sourmash][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Quickly search, compare, and analyze genomic and metagenomic data sets. |
|
| [sourmash][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Quickly search, compare, and analyze genomic and metagenomic data sets. |
|
||||||
|
| [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. |
|
||||||
| [cyvcf2][] | ![github icon][] | ![apple icon][] ![linux icon][] | cython + htslib == fast VCF and BCF processing |
|
| [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. |
|
|
||||||
| [jq.py][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Python bindings for jq |
|
| [jq.py][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | Python bindings for jq |
|
||||||
|
| [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. |
|
||||||
| [iminuit][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Jupyter-friendly Python interface for C++ MINUIT2 |
|
| [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 |
|
| [Tokenizer][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast and customizable text tokenization library with BPE and SentencePiece support |
|
||||||
| [keyvi][] | ![github icon][] | ![linux icon][] ![apple icon][] | FST based key value index highly optimized for size and lookup performance, utilizes ccache action for improved runtime |
|
| [keyvi][] | ![github icon][] | ![linux icon][] ![apple icon][] | FST based key value index highly optimized for size and lookup performance, utilizes ccache action for improved runtime |
|
||||||
| [PyGLM][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Fast OpenGL Mathematics (GLM) for Python |
|
|
||||||
| [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. |
|
| [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. |
|
||||||
|
| [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. |
|
| [TgCrypto][] | ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Includes a Windows Travis build. |
|
||||||
| [iDynTree][] | ![github icon][] | ![linux icon][] | Uses manylinux_2_24 |
|
| [iDynTree][] | ![github icon][] | ![linux icon][] | Uses manylinux_2_24 |
|
||||||
| [streaming-form-data][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Streaming parser for multipart/form-data written in Cython |
|
| [streaming-form-data][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Streaming parser for multipart/form-data written in Cython |
|
||||||
| [bx-python][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | A library that includes Cython extensions. |
|
| [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. |
|
|
||||||
| [power-grid-model][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python/C++ library for distribution power system analysis |
|
| [power-grid-model][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Python/C++ library for distribution power system analysis |
|
||||||
| [Python-WebRTC][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | a Python extension that provides bindings to WebRTC M92 |
|
| [boost-histogram][] | ![github icon][] ![travisci icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Supports full range of wheels, including PyPy and alternate archs. |
|
||||||
| [pybase64][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast Base64 encoding/decoding in Python |
|
| [pybase64][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | Fast Base64 encoding/decoding in Python |
|
||||||
|
| [Python-WebRTC][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | a Python extension that provides bindings to WebRTC M92 |
|
||||||
|
| [Confluent client for Kafka][] | ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | setup in `tools/wheels/build-wheels.bat` |
|
||||||
| [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. |
|
| [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. |
|
||||||
| [fathon][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | python package for DFA (Detrended Fluctuation Analysis) and related algorithms |
|
| [fathon][] | ![travisci icon][] | ![apple icon][] ![linux icon][] | python package for DFA (Detrended Fluctuation Analysis) and related algorithms |
|
||||||
| [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. |
|
|
||||||
| [pybind11 scikit_build_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | An example combining scikit-build and pybind11 |
|
| [pybind11 scikit_build_example][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | An example combining scikit-build and pybind11 |
|
||||||
|
| [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. |
|
||||||
| [polaroid][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Full range of wheels for setuptools rust, with auto release and PyPI deploy. |
|
| [polaroid][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Full range of wheels for setuptools rust, with auto release and PyPI deploy. |
|
||||||
| [clang-format][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Scikit-build wrapper around LLVM's CMake, all platforms, generic wheels. |
|
| [clang-format][] | ![github icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Scikit-build wrapper around LLVM's CMake, all platforms, generic wheels. |
|
||||||
| [etebase-py][] | ![travisci icon][] | ![linux icon][] | Python bindings to a Rust library using `setuptools-rust`, and `sccache` for improved speed. |
|
| [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 |
|
| [cf-units][] | ![github icon][] | ![apple icon][] ![linux icon][] | Units of measure as required by the Climate and Forecast (CF) Metadata Conventions |
|
||||||
| [Confluent client for Kafka][] | ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | setup in `tools/wheels/build-wheels.bat` |
|
|
||||||
| [ninja][] | ![github icon][] ![travisci icon][] | ![apple icon][] ![linux icon][] ![windows icon][] | Multitagged binary builds for all supported platforms, using cibw 2 config configuration. |
|
| [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 |
|
| [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 |
|
| [pyjet][] | ![github icon][] | ![windows icon][] ![apple icon][] ![linux icon][] | The interface between FastJet and NumPy |
|
||||||
@@ -128,8 +128,8 @@ title: Working examples
|
|||||||
[Prophet]: https://github.com/facebook/prophet
|
[Prophet]: https://github.com/facebook/prophet
|
||||||
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
|
[MyPy]: https://github.com/mypyc/mypy_mypyc-wheels
|
||||||
[Kivy]: https://github.com/kivy/kivy
|
[Kivy]: https://github.com/kivy/kivy
|
||||||
[MemRay]: https://github.com/bloomberg/memray
|
|
||||||
[Triton]: https://github.com/openai/triton
|
[Triton]: https://github.com/openai/triton
|
||||||
|
[MemRay]: https://github.com/bloomberg/memray
|
||||||
[uvloop]: https://github.com/MagicStack/uvloop
|
[uvloop]: https://github.com/MagicStack/uvloop
|
||||||
[psutil]: https://github.com/giampaolo/psutil
|
[psutil]: https://github.com/giampaolo/psutil
|
||||||
[Google Benchmark]: https://github.com/google/benchmark
|
[Google Benchmark]: https://github.com/google/benchmark
|
||||||
@@ -142,18 +142,18 @@ title: Working examples
|
|||||||
[twisted-iocpsupport]: https://github.com/twisted/twisted-iocpsupport
|
[twisted-iocpsupport]: https://github.com/twisted/twisted-iocpsupport
|
||||||
[PyOxidizer]: https://github.com/indygreg/PyOxidizer
|
[PyOxidizer]: https://github.com/indygreg/PyOxidizer
|
||||||
[cvxpy]: https://github.com/cvxpy/cvxpy
|
[cvxpy]: https://github.com/cvxpy/cvxpy
|
||||||
[websockets]: https://github.com/python-websockets/websockets
|
|
||||||
[pedalboard]: https://github.com/spotify/pedalboard
|
[pedalboard]: https://github.com/spotify/pedalboard
|
||||||
|
[websockets]: https://github.com/python-websockets/websockets
|
||||||
[River]: https://github.com/online-ml/river
|
[River]: https://github.com/online-ml/river
|
||||||
[UltraJSON]: https://github.com/ultrajson/ultrajson
|
[UltraJSON]: https://github.com/ultrajson/ultrajson
|
||||||
[OpenSpiel]: https://github.com/google-deepmind/open_spiel
|
|
||||||
[aiortc]: https://github.com/aiortc/aiortc
|
[aiortc]: https://github.com/aiortc/aiortc
|
||||||
|
[OpenSpiel]: https://github.com/google-deepmind/open_spiel
|
||||||
[Dependency Injector]: https://github.com/ets-labs/python-dependency-injector
|
[Dependency Injector]: https://github.com/ets-labs/python-dependency-injector
|
||||||
[pyzmq]: https://github.com/zeromq/pyzmq
|
[pyzmq]: https://github.com/zeromq/pyzmq
|
||||||
[Implicit]: https://github.com/benfred/implicit
|
[Implicit]: https://github.com/benfred/implicit
|
||||||
[vispy]: https://github.com/vispy/vispy
|
|
||||||
[tinyobjloader]: https://github.com/tinyobjloader/tinyobjloader
|
|
||||||
[CTranslate2]: https://github.com/OpenNMT/CTranslate2
|
[CTranslate2]: https://github.com/OpenNMT/CTranslate2
|
||||||
|
[tinyobjloader]: https://github.com/tinyobjloader/tinyobjloader
|
||||||
|
[vispy]: https://github.com/vispy/vispy
|
||||||
[coverage.py]: https://github.com/nedbat/coveragepy
|
[coverage.py]: https://github.com/nedbat/coveragepy
|
||||||
[PyCryptodome]: https://github.com/Legrandin/pycryptodome
|
[PyCryptodome]: https://github.com/Legrandin/pycryptodome
|
||||||
[Line Profiler]: https://github.com/pyutils/line_profiler
|
[Line Profiler]: https://github.com/pyutils/line_profiler
|
||||||
@@ -188,33 +188,33 @@ title: Working examples
|
|||||||
[python-rapidjson]: https://github.com/python-rapidjson/python-rapidjson
|
[python-rapidjson]: https://github.com/python-rapidjson/python-rapidjson
|
||||||
[pybind11 python_example]: https://github.com/pybind/python_example
|
[pybind11 python_example]: https://github.com/pybind/python_example
|
||||||
[python-snappy]: https://github.com/intake/python-snappy
|
[python-snappy]: https://github.com/intake/python-snappy
|
||||||
[abess]: https://github.com/abess-team/abess
|
|
||||||
[sourmash]: https://github.com/sourmash-bio/sourmash
|
[sourmash]: https://github.com/sourmash-bio/sourmash
|
||||||
|
[abess]: https://github.com/abess-team/abess
|
||||||
[cyvcf2]: https://github.com/brentp/cyvcf2
|
[cyvcf2]: https://github.com/brentp/cyvcf2
|
||||||
[matrixprofile]: https://github.com/matrix-profile-foundation/matrixprofile
|
|
||||||
[jq.py]: https://github.com/mwilliamson/jq.py
|
[jq.py]: https://github.com/mwilliamson/jq.py
|
||||||
|
[matrixprofile]: https://github.com/matrix-profile-foundation/matrixprofile
|
||||||
[iminuit]: https://github.com/scikit-hep/iminuit
|
[iminuit]: https://github.com/scikit-hep/iminuit
|
||||||
[Tokenizer]: https://github.com/OpenNMT/Tokenizer
|
[Tokenizer]: https://github.com/OpenNMT/Tokenizer
|
||||||
[keyvi]: https://github.com/KeyviDev/keyvi
|
[keyvi]: https://github.com/KeyviDev/keyvi
|
||||||
[PyGLM]: https://github.com/Zuzu-Typ/PyGLM
|
|
||||||
[pillow-heif]: https://github.com/bigcat88/pillow_heif
|
[pillow-heif]: https://github.com/bigcat88/pillow_heif
|
||||||
|
[PyGLM]: https://github.com/Zuzu-Typ/PyGLM
|
||||||
[TgCrypto]: https://github.com/pyrogram/tgcrypto
|
[TgCrypto]: https://github.com/pyrogram/tgcrypto
|
||||||
[iDynTree]: https://github.com/robotology/idyntree
|
[iDynTree]: https://github.com/robotology/idyntree
|
||||||
[streaming-form-data]: https://github.com/siddhantgoel/streaming-form-data
|
[streaming-form-data]: https://github.com/siddhantgoel/streaming-form-data
|
||||||
[bx-python]: https://github.com/bxlab/bx-python
|
[bx-python]: https://github.com/bxlab/bx-python
|
||||||
[boost-histogram]: https://github.com/scikit-hep/boost-histogram
|
|
||||||
[power-grid-model]: https://github.com/PowerGridModel/power-grid-model
|
[power-grid-model]: https://github.com/PowerGridModel/power-grid-model
|
||||||
[Python-WebRTC]: https://github.com/MarshalX/python-webrtc
|
[boost-histogram]: https://github.com/scikit-hep/boost-histogram
|
||||||
[pybase64]: https://github.com/mayeut/pybase64
|
[pybase64]: https://github.com/mayeut/pybase64
|
||||||
|
[Python-WebRTC]: https://github.com/MarshalX/python-webrtc
|
||||||
|
[Confluent client for Kafka]: https://github.com/confluentinc/confluent-kafka-python
|
||||||
[Imagecodecs (fork)]: https://github.com/czaki/imagecodecs_build
|
[Imagecodecs (fork)]: https://github.com/czaki/imagecodecs_build
|
||||||
[fathon]: https://github.com/stfbnc/fathon
|
[fathon]: https://github.com/stfbnc/fathon
|
||||||
[Arbor]: https://github.com/arbor-sim/arbor
|
|
||||||
[pybind11 scikit_build_example]: https://github.com/pybind/scikit_build_example
|
[pybind11 scikit_build_example]: https://github.com/pybind/scikit_build_example
|
||||||
|
[Arbor]: https://github.com/arbor-sim/arbor
|
||||||
[polaroid]: https://github.com/daggy1234/polaroid
|
[polaroid]: https://github.com/daggy1234/polaroid
|
||||||
[clang-format]: https://github.com/ssciwr/clang-format-wheel
|
[clang-format]: https://github.com/ssciwr/clang-format-wheel
|
||||||
[etebase-py]: https://github.com/etesync/etebase-py
|
[etebase-py]: https://github.com/etesync/etebase-py
|
||||||
[cf-units]: https://github.com/SciTools/cf-units
|
[cf-units]: https://github.com/SciTools/cf-units
|
||||||
[Confluent client for Kafka]: https://github.com/confluentinc/confluent-kafka-python
|
|
||||||
[ninja]: https://github.com/scikit-build/ninja-python-distributions
|
[ninja]: https://github.com/scikit-build/ninja-python-distributions
|
||||||
[numpythia]: https://github.com/scikit-hep/numpythia
|
[numpythia]: https://github.com/scikit-hep/numpythia
|
||||||
[pyjet]: https://github.com/scikit-hep/pyjet
|
[pyjet]: https://github.com/scikit-hep/pyjet
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ environment:
|
|||||||
|
|
||||||
stack: python 3.12
|
stack: python 3.12
|
||||||
|
|
||||||
install: python -m pip install cibuildwheel==2.20.0
|
install: python -m pip install cibuildwheel==2.23.4
|
||||||
|
|
||||||
build_script: python -m cibuildwheel --output-dir wheelhouse
|
build_script: python -m cibuildwheel --output-dir wheelhouse
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ jobs:
|
|||||||
- bash: |
|
- bash: |
|
||||||
set -o errexit
|
set -o errexit
|
||||||
python3 -m pip install --upgrade pip
|
python3 -m pip install --upgrade pip
|
||||||
pip3 install cibuildwheel==2.20.0
|
pip3 install cibuildwheel==2.23.4
|
||||||
displayName: Install dependencies
|
displayName: Install dependencies
|
||||||
- bash: cibuildwheel --output-dir wheelhouse .
|
- bash: cibuildwheel --output-dir wheelhouse .
|
||||||
displayName: Build wheels
|
displayName: Build wheels
|
||||||
@@ -14,13 +14,13 @@ jobs:
|
|||||||
inputs: {pathtoPublish: 'wheelhouse'}
|
inputs: {pathtoPublish: 'wheelhouse'}
|
||||||
|
|
||||||
- job: macos
|
- job: macos
|
||||||
pool: {vmImage: 'macOS-12'}
|
pool: {vmImage: 'macOS-13'}
|
||||||
steps:
|
steps:
|
||||||
- task: UsePythonVersion@0
|
- task: UsePythonVersion@0
|
||||||
- bash: |
|
- bash: |
|
||||||
set -o errexit
|
set -o errexit
|
||||||
python3 -m pip install --upgrade pip
|
python3 -m pip install --upgrade pip
|
||||||
python3 -m pip install cibuildwheel==2.20.0
|
python3 -m pip install cibuildwheel==2.23.4
|
||||||
displayName: Install dependencies
|
displayName: Install dependencies
|
||||||
- bash: cibuildwheel --output-dir wheelhouse .
|
- bash: cibuildwheel --output-dir wheelhouse .
|
||||||
displayName: Build wheels
|
displayName: Build wheels
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
- bash: |
|
- bash: |
|
||||||
set -o errexit
|
set -o errexit
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install cibuildwheel==2.20.0
|
pip install cibuildwheel==2.23.4
|
||||||
displayName: Install dependencies
|
displayName: Install dependencies
|
||||||
- bash: cibuildwheel --output-dir wheelhouse .
|
- bash: cibuildwheel --output-dir wheelhouse .
|
||||||
displayName: Build wheels
|
displayName: Build wheels
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Build the Linux wheels.
|
name: Build the Linux wheels.
|
||||||
command: |
|
command: |
|
||||||
python3 -m pip install --user cibuildwheel==2.20.0
|
python3 -m pip install --user cibuildwheel==2.23.4
|
||||||
cibuildwheel --output-dir wheelhouse
|
cibuildwheel --output-dir wheelhouse
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: wheelhouse/
|
path: wheelhouse/
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Build the Linux aarch64 wheels.
|
name: Build the Linux aarch64 wheels.
|
||||||
command: |
|
command: |
|
||||||
python3 -m pip install --user cibuildwheel==2.20.0
|
python3 -m pip install --user cibuildwheel==2.23.4
|
||||||
python3 -m cibuildwheel --output-dir wheelhouse
|
python3 -m cibuildwheel --output-dir wheelhouse
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: wheelhouse/
|
path: wheelhouse/
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
name: Build the OS X wheels.
|
name: Build the OS X wheels.
|
||||||
command: |
|
command: |
|
||||||
sudo softwareupdate --install-rosetta --agree-to-license # for python<=3.8 or x86_64/universal2 tests
|
sudo softwareupdate --install-rosetta --agree-to-license # for python<=3.8 or x86_64/universal2 tests
|
||||||
pip3 install cibuildwheel==2.20.0
|
pip3 install cibuildwheel==2.23.4
|
||||||
cibuildwheel --output-dir wheelhouse
|
cibuildwheel --output-dir wheelhouse
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: wheelhouse/
|
path: wheelhouse/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
||||||
install_cibuildwheel_script:
|
install_cibuildwheel_script:
|
||||||
- python -m pip install cibuildwheel==2.20.0
|
- python -m pip install cibuildwheel==2.23.4
|
||||||
run_cibuildwheel_script:
|
run_cibuildwheel_script:
|
||||||
- cibuildwheel
|
- cibuildwheel
|
||||||
wheels_artifacts:
|
wheels_artifacts:
|
||||||
@@ -10,7 +10,7 @@ build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
|||||||
macos_task:
|
macos_task:
|
||||||
name: Build macOS x86_64 and arm64 wheels.
|
name: Build macOS x86_64 and arm64 wheels.
|
||||||
macos_instance:
|
macos_instance:
|
||||||
image: ghcr.io/cirruslabs/macos-sonoma-xcode
|
image: ghcr.io/cirruslabs/macos-runner:sonoma
|
||||||
env:
|
env:
|
||||||
VENV_ROOT: ${HOME}/venv-cibuildwheel
|
VENV_ROOT: ${HOME}/venv-cibuildwheel
|
||||||
PATH: ${VENV_ROOT}/bin:${PATH}
|
PATH: ${VENV_ROOT}/bin:${PATH}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
build_and_store_wheels: &BUILD_AND_STORE_WHEELS
|
||||||
install_cibuildwheel_script:
|
install_cibuildwheel_script:
|
||||||
- python -m pip install cibuildwheel==2.20.0
|
- python -m pip install cibuildwheel==2.23.4
|
||||||
run_cibuildwheel_script:
|
run_cibuildwheel_script:
|
||||||
- cibuildwheel
|
- cibuildwheel
|
||||||
wheels_artifacts:
|
wheels_artifacts:
|
||||||
@@ -60,7 +60,7 @@ windows_x86_task:
|
|||||||
macos_arm64_task:
|
macos_arm64_task:
|
||||||
name: Build macOS arm64 wheels.
|
name: Build macOS arm64 wheels.
|
||||||
macos_instance:
|
macos_instance:
|
||||||
image: ghcr.io/cirruslabs/macos-sonoma-xcode
|
image: ghcr.io/cirruslabs/macos-runner:sonoma
|
||||||
env:
|
env:
|
||||||
VENV_ROOT: ${HOME}/venv-cibuildwheel
|
VENV_ROOT: ${HOME}/venv-cibuildwheel
|
||||||
PATH: ${VENV_ROOT}/bin:${PATH}
|
PATH: ${VENV_ROOT}/bin:${PATH}
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# macos-13 is an intel runner, macos-14 is apple silicon
|
# macos-15-intel is an intel runner, macos-latest is apple silicon
|
||||||
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
|
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-15-intel, macos-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.20.0
|
uses: pypa/cibuildwheel@v2.23.4
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# macos-13 is an intel runner, macos-14 is apple silicon
|
# macos-15-intel is an intel runner, macos-latest is apple silicon
|
||||||
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
|
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-15-intel, macos-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.20.0
|
uses: pypa/cibuildwheel@v2.23.4
|
||||||
# env:
|
# env:
|
||||||
# CIBW_SOME_OPTION: value
|
# CIBW_SOME_OPTION: value
|
||||||
# ...
|
# ...
|
||||||
|
|||||||
@@ -8,24 +8,28 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# macos-13 is an intel runner, macos-14 is apple silicon
|
# macos-15-intel is an intel runner, macos-latest is apple silicon
|
||||||
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
|
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-15-intel, macos-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux' && runner.arch == 'X64'
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
with:
|
with:
|
||||||
platforms: all
|
platforms: all
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: pypa/cibuildwheel@v2.20.0
|
uses: pypa/cibuildwheel@v2.23.4
|
||||||
env:
|
env:
|
||||||
# configure cibuildwheel to build native archs ('auto'), and some
|
# configure cibuildwheel on Linux to build native archs ('auto'),
|
||||||
# emulated ones
|
# and to split the remaining architectures between the x86_64 and
|
||||||
CIBW_ARCHS_LINUX: auto aarch64 ppc64le s390x
|
# ARM runners
|
||||||
|
# armv7l can be built without QEMU on GitHub Actions ARM runners but that's
|
||||||
|
# not the case on all ARM64 hardware hence 'auto armv7l' for native archs
|
||||||
|
# on the GHA ARM64 runner
|
||||||
|
CIBW_ARCHS_LINUX: ${{ runner.arch == 'X64' && 'auto ppc64le s390x' || 'auto armv7l' }}
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ linux:
|
|||||||
DOCKER_TLS_CERTDIR: ""
|
DOCKER_TLS_CERTDIR: ""
|
||||||
script:
|
script:
|
||||||
- curl -sSL https://get.docker.com/ | sh
|
- curl -sSL https://get.docker.com/ | sh
|
||||||
- python -m pip install cibuildwheel==2.20.0
|
- python -m pip install cibuildwheel==2.23.4
|
||||||
- cibuildwheel --output-dir wheelhouse
|
- cibuildwheel --output-dir wheelhouse
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
@@ -23,7 +23,7 @@ windows:
|
|||||||
before_script:
|
before_script:
|
||||||
- choco install python -y --version 3.12.4
|
- choco install python -y --version 3.12.4
|
||||||
- choco install git.install -y
|
- choco install git.install -y
|
||||||
- py -m pip install cibuildwheel==2.20.0
|
- py -m pip install cibuildwheel==2.23.4
|
||||||
script:
|
script:
|
||||||
- py -m cibuildwheel --output-dir wheelhouse --platform windows
|
- py -m cibuildwheel --output-dir wheelhouse --platform windows
|
||||||
artifacts:
|
artifacts:
|
||||||
@@ -33,9 +33,9 @@ windows:
|
|||||||
- saas-windows-medium-amd64
|
- saas-windows-medium-amd64
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
image: macos-14-xcode-15
|
image: macos-latest-xcode-15
|
||||||
before_script:
|
before_script:
|
||||||
- python3 -m pip install cibuildwheel==2.20.0
|
- python3 -m pip install cibuildwheel==2.23.4
|
||||||
script:
|
script:
|
||||||
- python3 -m cibuildwheel --output-dir wheelhouse
|
- python3 -m cibuildwheel --output-dir wheelhouse
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ linux:
|
|||||||
- curl -sSL https://get.docker.com/ | sh
|
- curl -sSL https://get.docker.com/ | sh
|
||||||
# Warning: This is extremely slow, be careful with how many wheels you build
|
# Warning: This is extremely slow, be careful with how many wheels you build
|
||||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
- python -m pip install cibuildwheel==2.20.0
|
- python -m pip install cibuildwheel==2.23.4
|
||||||
# Assuming your CI runner's default architecture is x86_64...
|
# Assuming your CI runner's default architecture is x86_64...
|
||||||
- cibuildwheel --output-dir wheelhouse --platform linux --archs aarch64
|
- cibuildwheel --output-dir wheelhouse --platform linux --archs aarch64
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
|
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- python3 -m pip install cibuildwheel==2.20.0
|
- python3 -m pip install cibuildwheel==2.23.4
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# build the wheels, put them into './dist'
|
# build the wheels, put them into './dist'
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
|
- ln -s /c/Python312/python.exe /c/Python312/python3.exe
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- python3 -m pip install cibuildwheel==2.20.0
|
- python3 -m pip install cibuildwheel==2.23.4
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# build the wheels, put them into './wheelhouse'
|
# build the wheels, put them into './wheelhouse'
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
- stage: deploy
|
- stage: deploy
|
||||||
name: Build and deploy Linux wheels
|
name: Build and deploy Linux wheels
|
||||||
services: docker
|
services: docker
|
||||||
install: python3 -m pip install cibuildwheel==2.20.0 twine
|
install: python3 -m pip install cibuildwheel==2.23.4 twine
|
||||||
script: python3 -m cibuildwheel --output-dir wheelhouse
|
script: python3 -m cibuildwheel --output-dir wheelhouse
|
||||||
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
||||||
# Deploy on windows
|
# Deploy on windows
|
||||||
@@ -60,7 +60,7 @@ jobs:
|
|||||||
name: Build and deploy Windows wheels
|
name: Build and deploy Windows wheels
|
||||||
os: windows
|
os: windows
|
||||||
language: shell
|
language: shell
|
||||||
install: python3 -m pip install cibuildwheel==2.20.0 twine
|
install: python3 -m pip install cibuildwheel==2.23.4 twine
|
||||||
script: python3 -m cibuildwheel --output-dir wheelhouse
|
script: python3 -m cibuildwheel --output-dir wheelhouse
|
||||||
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
after_success: python3 -m twine upload --skip-existing wheelhouse/*.whl
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -15,18 +15,22 @@ nox.options.default_venv_backend = "uv|virtualenv"
|
|||||||
DIR = Path(__file__).parent.resolve()
|
DIR = Path(__file__).parent.resolve()
|
||||||
|
|
||||||
|
|
||||||
def install_and_run(session: nox.Session, script: str, *args: str, **kwargs: Any) -> str | None:
|
def install_and_run(session: nox.Session, script: str, *args: str, **kwargs: Any) -> Any:
|
||||||
deps = nox.project.load_toml(script)["dependencies"]
|
deps = nox.project.load_toml(script)["dependencies"]
|
||||||
session.install(*deps)
|
session.install(*deps)
|
||||||
return session.run("python", script, *args, **kwargs)
|
return session.run("python", script, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def dep_group(group: str) -> list[str]:
|
||||||
|
return nox.project.load_toml("pyproject.toml")["dependency-groups"][group] # type: ignore[no-any-return]
|
||||||
|
|
||||||
|
|
||||||
@nox.session
|
@nox.session
|
||||||
def tests(session: nox.Session) -> None:
|
def tests(session: nox.Session) -> None:
|
||||||
"""
|
"""
|
||||||
Run the unit and regular tests.
|
Run the unit and regular tests.
|
||||||
"""
|
"""
|
||||||
session.install("-e.[test]")
|
session.install("-e.", *dep_group("test"))
|
||||||
if session.posargs:
|
if session.posargs:
|
||||||
session.run("pytest", *session.posargs)
|
session.run("pytest", *session.posargs)
|
||||||
else:
|
else:
|
||||||
@@ -102,10 +106,10 @@ def update_constraints(session: nox.Session) -> None:
|
|||||||
pyodides = build_platforms["pyodide"]["python_configurations"]
|
pyodides = build_platforms["pyodide"]["python_configurations"]
|
||||||
for pyodide in pyodides:
|
for pyodide in pyodides:
|
||||||
python_version = ".".join(pyodide["version"].split(".")[:2])
|
python_version = ".".join(pyodide["version"].split(".")[:2])
|
||||||
pyodide_version = pyodide["pyodide_version"]
|
pyodide_build_version = pyodide["pyodide_build_version"]
|
||||||
output_file = resources / f"constraints-pyodide{python_version.replace('.', '')}.txt"
|
output_file = resources / f"constraints-pyodide{python_version.replace('.', '')}.txt"
|
||||||
tmp_file = Path(session.create_tmp()) / "constraints-pyodide.in"
|
tmp_file = Path(session.create_tmp()) / "constraints-pyodide.in"
|
||||||
tmp_file.write_text(f"pip\nbuild[virtualenv]\npyodide-build=={pyodide_version}")
|
tmp_file.write_text(f"pip\nbuild[virtualenv]\npyodide-build=={pyodide_build_version}")
|
||||||
session.run(
|
session.run(
|
||||||
"uv",
|
"uv",
|
||||||
"pip",
|
"pip",
|
||||||
@@ -123,7 +127,7 @@ def update_pins(session: nox.Session) -> None:
|
|||||||
"""
|
"""
|
||||||
Update the python, docker and virtualenv pins version inplace.
|
Update the python, docker and virtualenv pins version inplace.
|
||||||
"""
|
"""
|
||||||
session.install("-e.[bin]")
|
session.install("-e.", *dep_group("bin"))
|
||||||
session.run("python", "bin/update_pythons.py", "--force")
|
session.run("python", "bin/update_pythons.py", "--force")
|
||||||
session.run("python", "bin/update_docker.py")
|
session.run("python", "bin/update_docker.py")
|
||||||
session.run("python", "bin/update_virtualenv.py", "--force")
|
session.run("python", "bin/update_virtualenv.py", "--force")
|
||||||
@@ -166,7 +170,7 @@ def docs(session: nox.Session) -> None:
|
|||||||
"""
|
"""
|
||||||
Build the docs. Will serve unless --non-interactive
|
Build the docs. Will serve unless --non-interactive
|
||||||
"""
|
"""
|
||||||
session.install("-e.[docs]")
|
session.install("-e.", *dep_group("docs"))
|
||||||
session.run("mkdocs", "serve" if session.interactive else "build", "--strict", *session.posargs)
|
session.run("mkdocs", "serve" if session.interactive else "build", "--strict", *session.posargs)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+44
-47
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "cibuildwheel"
|
name = "cibuildwheel"
|
||||||
version = "2.20.0"
|
version = "2.23.4"
|
||||||
description = "Build Python wheels on CI with minimal configuration."
|
description = "Build Python wheels on CI with minimal configuration."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "BSD-2-Clause"
|
license = "BSD-2-Clause"
|
||||||
@@ -35,6 +35,7 @@ classifiers = [
|
|||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
"Programming Language :: Python :: 3.12",
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
"Topic :: Software Development :: Build Tools",
|
"Topic :: Software Development :: Build Tools",
|
||||||
]
|
]
|
||||||
@@ -42,6 +43,7 @@ dependencies = [
|
|||||||
"bashlex!=0.13",
|
"bashlex!=0.13",
|
||||||
"bracex",
|
"bracex",
|
||||||
"certifi",
|
"certifi",
|
||||||
|
"dependency-groups>=1.2",
|
||||||
"filelock",
|
"filelock",
|
||||||
"packaging>=20.9",
|
"packaging>=20.9",
|
||||||
"platformdirs",
|
"platformdirs",
|
||||||
@@ -50,35 +52,6 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
bin = [
|
|
||||||
"click",
|
|
||||||
"packaging>=21.0",
|
|
||||||
"pip-tools",
|
|
||||||
"pygithub",
|
|
||||||
"pyyaml",
|
|
||||||
"requests",
|
|
||||||
"rich>=9.6",
|
|
||||||
]
|
|
||||||
dev = [
|
|
||||||
"cibuildwheel[test,bin]",
|
|
||||||
]
|
|
||||||
docs = [
|
|
||||||
"jinja2>=3.1.2",
|
|
||||||
"mkdocs-include-markdown-plugin==2.8.0",
|
|
||||||
"mkdocs-macros-plugin",
|
|
||||||
"mkdocs==1.3.1",
|
|
||||||
"pymdown-extensions",
|
|
||||||
]
|
|
||||||
test = [
|
|
||||||
"build",
|
|
||||||
"jinja2",
|
|
||||||
"pytest-timeout",
|
|
||||||
"pytest-xdist",
|
|
||||||
"pytest>=6",
|
|
||||||
"setuptools",
|
|
||||||
"tomli_w",
|
|
||||||
"validate-pyproject",
|
|
||||||
]
|
|
||||||
uv = ["uv"]
|
uv = ["uv"]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
@@ -92,6 +65,41 @@ Changelog = "https://github.com/pypa/cibuildwheel#changelog"
|
|||||||
Documentation = "https://cibuildwheel.pypa.io"
|
Documentation = "https://cibuildwheel.pypa.io"
|
||||||
Homepage = "https://github.com/pypa/cibuildwheel"
|
Homepage = "https://github.com/pypa/cibuildwheel"
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
bin = [
|
||||||
|
"click",
|
||||||
|
"packaging>=21.0",
|
||||||
|
"pip-tools",
|
||||||
|
"pygithub",
|
||||||
|
"pyyaml",
|
||||||
|
"requests",
|
||||||
|
"rich>=9.6",
|
||||||
|
]
|
||||||
|
docs = [
|
||||||
|
"jinja2>=3.1.2",
|
||||||
|
"mkdocs-include-markdown-plugin==6.2.2",
|
||||||
|
"mkdocs-macros-plugin",
|
||||||
|
"mkdocs==1.6.1",
|
||||||
|
"pymdown-extensions",
|
||||||
|
]
|
||||||
|
test = [
|
||||||
|
"build",
|
||||||
|
"jinja2",
|
||||||
|
"pytest-timeout",
|
||||||
|
"pytest-xdist",
|
||||||
|
"pytest-rerunfailures!=16.0",
|
||||||
|
"pytest>=6",
|
||||||
|
"setuptools",
|
||||||
|
"tomli_w",
|
||||||
|
"validate-pyproject",
|
||||||
|
]
|
||||||
|
dev = [
|
||||||
|
{include-group = "bin"},
|
||||||
|
{include-group = "docs"},
|
||||||
|
{include-group = "test"},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
minversion = "6.0"
|
minversion = "6.0"
|
||||||
addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"]
|
addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"]
|
||||||
@@ -112,33 +120,20 @@ files = [
|
|||||||
]
|
]
|
||||||
warn_unused_configs = true
|
warn_unused_configs = true
|
||||||
|
|
||||||
warn_redundant_casts = true
|
strict = true
|
||||||
no_implicit_reexport = true
|
disallow_untyped_defs = false
|
||||||
strict_equality = true
|
|
||||||
warn_unused_ignores = true
|
|
||||||
check_untyped_defs = true
|
|
||||||
|
|
||||||
disallow_subclassing_any = true
|
|
||||||
disallow_any_generics = true
|
|
||||||
warn_return_any = true
|
|
||||||
no_implicit_optional = true
|
|
||||||
|
|
||||||
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
||||||
warn_unreachable = true
|
warn_unreachable = false
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
[[tool.mypy.overrides]]
|
||||||
module = "cibuildwheel.*"
|
module = "cibuildwheel.*"
|
||||||
disallow_untyped_defs = true
|
disallow_untyped_defs = true
|
||||||
disallow_untyped_calls = true
|
|
||||||
disallow_incomplete_defs = true
|
|
||||||
disallow_untyped_decorators = true
|
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
[[tool.mypy.overrides]]
|
||||||
module = [
|
module = [
|
||||||
"setuptools",
|
|
||||||
"setuptools._distutils", # needed even if only directly import setuptools._distutils.util
|
"setuptools._distutils", # needed even if only directly import setuptools._distutils.util
|
||||||
"setuptools._distutils.util",
|
"setuptools._distutils.util",
|
||||||
"pytest", # ignored in pre-commit to speed up check
|
|
||||||
"bashlex",
|
"bashlex",
|
||||||
"bashlex.*",
|
"bashlex.*",
|
||||||
"importlib_resources",
|
"importlib_resources",
|
||||||
@@ -213,7 +208,6 @@ ignore = [
|
|||||||
"PLR", # Design related pylint codes
|
"PLR", # Design related pylint codes
|
||||||
"E501", # Line too long
|
"E501", # Line too long
|
||||||
"RET504", "RET505", "RET508", # else after control flow
|
"RET504", "RET505", "RET508", # else after control flow
|
||||||
"PT004", # Rename suggested for returnless fixtures
|
|
||||||
"PT007", # False positive
|
"PT007", # False positive
|
||||||
"PYI025", # Set as AbstractSet
|
"PYI025", # Set as AbstractSet
|
||||||
"ISC001", # Conflicts with formatter
|
"ISC001", # Conflicts with formatter
|
||||||
@@ -239,3 +233,6 @@ flake8-unused-arguments.ignore-variadic-names = true
|
|||||||
|
|
||||||
[tool.repo-review]
|
[tool.repo-review]
|
||||||
ignore = ["PC170", "PP303"]
|
ignore = ["PC170", "PP303"]
|
||||||
|
|
||||||
|
[tool.check-wheel-contents]
|
||||||
|
ignore = ["W002"] # requirements-*.txt are allowed to be duplicates of one another
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
-e .[dev,docs]
|
|
||||||
+1
-1
@@ -11,7 +11,7 @@ from cibuildwheel.util import detect_ci_provider, find_uv
|
|||||||
from .utils import EMULATED_ARCHS, platform
|
from .utils import EMULATED_ARCHS, platform
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser) -> None:
|
def pytest_addoption(parser: pytest.Parser) -> None:
|
||||||
parser.addoption(
|
parser.addoption(
|
||||||
"--run-emulation",
|
"--run-emulation",
|
||||||
action="store",
|
action="store",
|
||||||
|
|||||||
@@ -18,27 +18,16 @@ limited_api_project = test_projects.new_c_project(
|
|||||||
IS_CPYTHON = sys.implementation.name == "cpython"
|
IS_CPYTHON = sys.implementation.name == "cpython"
|
||||||
Py_GIL_DISABLED = sysconfig.get_config_var("Py_GIL_DISABLED")
|
Py_GIL_DISABLED = sysconfig.get_config_var("Py_GIL_DISABLED")
|
||||||
CAN_USE_ABI3 = IS_CPYTHON and not Py_GIL_DISABLED
|
CAN_USE_ABI3 = IS_CPYTHON and not Py_GIL_DISABLED
|
||||||
cmdclass = {}
|
setup_options = {}
|
||||||
extension_kwargs = {}
|
extension_kwargs = {}
|
||||||
if CAN_USE_ABI3 and sys.version_info[:2] >= (3, 10):
|
if CAN_USE_ABI3 and sys.version_info[:2] >= (3, 10):
|
||||||
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
|
|
||||||
|
|
||||||
class bdist_wheel_abi3(_bdist_wheel):
|
|
||||||
def finalize_options(self):
|
|
||||||
_bdist_wheel.finalize_options(self)
|
|
||||||
self.root_is_pure = False
|
|
||||||
|
|
||||||
def get_tag(self):
|
|
||||||
python, abi, plat = _bdist_wheel.get_tag(self)
|
|
||||||
return python, "abi3", plat
|
|
||||||
|
|
||||||
cmdclass["bdist_wheel"] = bdist_wheel_abi3
|
|
||||||
extension_kwargs["define_macros"] = [("Py_LIMITED_API", "0x030A0000")]
|
extension_kwargs["define_macros"] = [("Py_LIMITED_API", "0x030A0000")]
|
||||||
extension_kwargs["py_limited_api"] = True
|
extension_kwargs["py_limited_api"] = True
|
||||||
|
setup_options = {"bdist_wheel": {"py_limited_api": "cp310"}}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
setup_py_extension_args_add="**extension_kwargs",
|
setup_py_extension_args_add="**extension_kwargs",
|
||||||
setup_py_setup_args_add="cmdclass=cmdclass",
|
setup_py_setup_args_add="options=setup_options",
|
||||||
)
|
)
|
||||||
|
|
||||||
limited_api_project.files["pyproject.toml"] = pyproject_toml
|
limited_api_project.files["pyproject.toml"] = pyproject_toml
|
||||||
@@ -65,7 +54,7 @@ def test_abi3(tmp_path):
|
|||||||
if utils.platform == "pyodide":
|
if utils.platform == "pyodide":
|
||||||
# there's only 1 possible configuration for pyodide, the single_python_tag one
|
# there's only 1 possible configuration for pyodide, the single_python_tag one
|
||||||
expected_wheels = [
|
expected_wheels = [
|
||||||
w.replace(f"{single_python_tag}-{single_python_tag}", f"{single_python_tag}-abi3")
|
w.replace(f"{single_python_tag}-{single_python_tag}", "cp310-abi3")
|
||||||
for w in expected_wheels
|
for w in expected_wheels
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ def test_podman(tmp_path, capfd, request):
|
|||||||
actual_wheels = utils.cibuildwheel_run(
|
actual_wheels = utils.cibuildwheel_run(
|
||||||
project_dir,
|
project_dir,
|
||||||
add_env={
|
add_env={
|
||||||
"CIBW_ARCHS": "x86_64",
|
"CIBW_ARCHS": "native",
|
||||||
"CIBW_BEFORE_ALL": "echo 'test log statement from before-all'",
|
"CIBW_BEFORE_ALL": "echo 'test log statement from before-all'",
|
||||||
"CIBW_CONTAINER_ENGINE": "podman",
|
"CIBW_CONTAINER_ENGINE": "podman",
|
||||||
},
|
},
|
||||||
@@ -29,9 +29,7 @@ def test_podman(tmp_path, capfd, request):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# check that the expected wheels are produced
|
# check that the expected wheels are produced
|
||||||
expected_wheels = [
|
expected_wheels = utils.expected_wheels("spam", "0.1.0", single_python=True, single_arch=True)
|
||||||
w for w in utils.expected_wheels("spam", "0.1.0", single_python=True) if "x86_64" in w
|
|
||||||
]
|
|
||||||
assert set(actual_wheels) == set(expected_wheels)
|
assert set(actual_wheels) == set(expected_wheels)
|
||||||
|
|
||||||
# check that stdout is bring passed-though from container correctly
|
# check that stdout is bring passed-though from container correctly
|
||||||
|
|||||||
@@ -33,10 +33,9 @@ def test(tmp_path, capfd):
|
|||||||
basic_project.generate(project_dir)
|
basic_project.generate(project_dir)
|
||||||
|
|
||||||
num_builds = len(utils.cibuildwheel_get_build_identifiers(project_dir))
|
num_builds = len(utils.cibuildwheel_get_build_identifiers(project_dir))
|
||||||
if num_builds > 1:
|
expectation = (
|
||||||
expectation = pytest.raises(subprocess.CalledProcessError)
|
pytest.raises(subprocess.CalledProcessError) if num_builds > 1 else does_not_raise()
|
||||||
else:
|
)
|
||||||
expectation = does_not_raise()
|
|
||||||
|
|
||||||
with expectation as exc_info:
|
with expectation as exc_info:
|
||||||
result = utils.cibuildwheel_run(
|
result = utils.cibuildwheel_run(
|
||||||
@@ -48,6 +47,7 @@ def test(tmp_path, capfd):
|
|||||||
|
|
||||||
captured = capfd.readouterr()
|
captured = capfd.readouterr()
|
||||||
if num_builds > 1:
|
if num_builds > 1:
|
||||||
|
assert exc_info is not None
|
||||||
assert "Build failed because a wheel named" in captured.err
|
assert "Build failed because a wheel named" in captured.err
|
||||||
assert exc_info.value.returncode == 6
|
assert exc_info.value.returncode == 6
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import textwrap
|
import textwrap
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@@ -46,8 +47,8 @@ build-backend = "setuptools.build_meta"
|
|||||||
VERSION_REGEX = r"([\w-]+)==([^\s]+)"
|
VERSION_REGEX = r"([\w-]+)==([^\s]+)"
|
||||||
|
|
||||||
|
|
||||||
def get_versions_from_constraint_file(constraint_file):
|
def get_versions_from_constraint_file(constraint_file: Path) -> dict[str, str]:
|
||||||
constraint_file_text = constraint_file.read_text(encoding="utf8")
|
constraint_file_text = constraint_file.read_text(encoding="utf-8")
|
||||||
|
|
||||||
return dict(re.findall(VERSION_REGEX, constraint_file_text))
|
return dict(re.findall(VERSION_REGEX, constraint_file_text))
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from pyodide.code import run_js
|
|||||||
|
|
||||||
def check_node():
|
def check_node():
|
||||||
# cibuildwheel adds a pinned node version to the PATH
|
# cibuildwheel adds a pinned node version to the PATH
|
||||||
# check it's in the PATH then, check it's the one that runs pyoodide
|
# check it's in the PATH then, check it's the one that runs Pyodide
|
||||||
cibw_cache_path = Path(sys.argv[1]).resolve(strict=True)
|
cibw_cache_path = Path(sys.argv[1]).resolve(strict=True)
|
||||||
# find the node executable in PATH
|
# find the node executable in PATH
|
||||||
node = shutil.which("node")
|
node = shutil.which("node")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
from collections.abc import Mapping
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
|
||||||
@@ -28,7 +29,11 @@ def make_sdist(project: TestProject, working_dir: Path) -> Path:
|
|||||||
return next(sdist_dir.glob("*.tar.gz"))
|
return next(sdist_dir.glob("*.tar.gz"))
|
||||||
|
|
||||||
|
|
||||||
def cibuildwheel_from_sdist_run(sdist_path, add_env=None, config_file=None):
|
def cibuildwheel_from_sdist_run(
|
||||||
|
sdist_path: Path | str,
|
||||||
|
add_env: Mapping[str, str] | None = None,
|
||||||
|
config_file: str | None = None,
|
||||||
|
) -> list[str]:
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
|
|
||||||
if add_env:
|
if add_env:
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from argparse import ArgumentParser
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
parser = ArgumentParser(
|
parser = ArgumentParser(
|
||||||
prog="python -m test.test_projects", description="Generate a test project to check it out"
|
prog="python -m test.test_projects", description="Generate a test project to check it out"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ class TestProject:
|
|||||||
files: FilesDict
|
files: FilesDict
|
||||||
template_context: TemplateContext
|
template_context: TemplateContext
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
self.files = {}
|
self.files = {}
|
||||||
self.template_context = {}
|
self.template_context = {}
|
||||||
|
|
||||||
def generate(self, path: Path):
|
def generate(self, path: Path) -> None:
|
||||||
for filename, content in self.files.items():
|
for filename, content in self.files.items():
|
||||||
file_path = path / filename
|
file_path = path / filename
|
||||||
file_path.parent.mkdir(parents=True, exist_ok=True)
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -37,7 +37,7 @@ class TestProject:
|
|||||||
|
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
def copy(self):
|
def copy(self) -> TestProject:
|
||||||
other = TestProject()
|
other = TestProject()
|
||||||
other.files = self.files.copy()
|
other.files = self.files.copy()
|
||||||
other.template_context = self.template_context.copy()
|
other.template_context = self.template_context.copy()
|
||||||
|
|||||||
@@ -78,13 +78,13 @@ version = 0.1.0
|
|||||||
|
|
||||||
def new_c_project(
|
def new_c_project(
|
||||||
*,
|
*,
|
||||||
spam_c_top_level_add="",
|
spam_c_top_level_add: str = "",
|
||||||
spam_c_function_add="",
|
spam_c_function_add: str = "",
|
||||||
setup_py_add="",
|
setup_py_add: str = "",
|
||||||
setup_py_extension_args_add="",
|
setup_py_extension_args_add: str = "",
|
||||||
setup_py_setup_args_add="",
|
setup_py_setup_args_add: str = "",
|
||||||
setup_cfg_add="",
|
setup_cfg_add: str = "",
|
||||||
):
|
) -> TestProject:
|
||||||
project = TestProject()
|
project = TestProject()
|
||||||
|
|
||||||
project.files.update(
|
project.files.update(
|
||||||
|
|||||||
+20
-8
@@ -1,25 +1,37 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from . import test_projects, utils
|
from . import test_projects, utils
|
||||||
|
|
||||||
project_with_ssl_tests = test_projects.new_c_project(
|
project_with_ssl_tests = test_projects.new_c_project(
|
||||||
setup_py_add=textwrap.dedent(
|
setup_py_add=textwrap.dedent(
|
||||||
r"""
|
r"""
|
||||||
import ssl
|
import ssl, time, urllib.request, urllib.error
|
||||||
|
|
||||||
from urllib.request import urlopen
|
def check_https(context=None):
|
||||||
|
# google hosts this endpoint that returns a 204 No Content, it's used for
|
||||||
|
# connectivity checks in Android & Chrome
|
||||||
|
url = "https://google.com/generate_204"
|
||||||
|
|
||||||
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
|
for i in range(5):
|
||||||
data = urlopen("https://www.nist.gov", context=context)
|
try:
|
||||||
data = urlopen("https://raw.githubusercontent.com/pypa/cibuildwheel/main/CI.md", context=context)
|
urllib.request.urlopen(url, context=context, timeout=5)
|
||||||
data = urlopen("https://raw.githubusercontent.com/pypa/cibuildwheel/main/CI.md")
|
return
|
||||||
|
except (OSError, urllib.error.URLError) as e:
|
||||||
|
print(f"Attempt {i+1}: Could not connect to {url}: {e}")
|
||||||
|
time.sleep(2 ** i) # Backoff: 1s, 2s, 4s, 8s...
|
||||||
|
|
||||||
|
raise ConnectionError(f"Could not connect to {url} after retries.")
|
||||||
|
|
||||||
|
check_https()
|
||||||
|
check_https(context=ssl.SSLContext(ssl.PROTOCOL_TLSv1_2))
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.flaky(reruns=2)
|
||||||
def test(tmp_path):
|
def test(tmp_path):
|
||||||
# this test checks that SSL is working in the build environment using
|
# this test checks that SSL is working in the build environment using
|
||||||
# some checks in setup.py.
|
# some checks in setup.py.
|
||||||
|
|||||||
+34
-1
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import inspect
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import textwrap
|
import textwrap
|
||||||
@@ -114,6 +115,38 @@ def test_extras_require(tmp_path):
|
|||||||
assert set(actual_wheels) == set(expected_wheels)
|
assert set(actual_wheels) == set(expected_wheels)
|
||||||
|
|
||||||
|
|
||||||
|
def test_dependency_groups(tmp_path):
|
||||||
|
group_project = project_with_a_test.copy()
|
||||||
|
group_project.files["pyproject.toml"] = inspect.cleandoc("""
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
dev = ["pytest"]
|
||||||
|
""")
|
||||||
|
|
||||||
|
project_dir = tmp_path / "project"
|
||||||
|
group_project.generate(project_dir)
|
||||||
|
|
||||||
|
# build and test the wheels
|
||||||
|
actual_wheels = utils.cibuildwheel_run(
|
||||||
|
project_dir,
|
||||||
|
add_env={
|
||||||
|
"CIBW_TEST_GROUPS": "dev",
|
||||||
|
# the 'false ||' bit is to ensure this command runs in a shell on
|
||||||
|
# mac/linux.
|
||||||
|
"CIBW_TEST_COMMAND": f"false || {utils.invoke_pytest()} {{project}}/test",
|
||||||
|
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || pytest {project}/test",
|
||||||
|
},
|
||||||
|
single_python=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# also check that we got the right wheels
|
||||||
|
expected_wheels = utils.expected_wheels("spam", "0.1.0", single_python=True)
|
||||||
|
assert set(actual_wheels) == set(expected_wheels)
|
||||||
|
|
||||||
|
|
||||||
project_with_a_failing_test = test_projects.new_c_project()
|
project_with_a_failing_test = test_projects.new_c_project()
|
||||||
project_with_a_failing_test.files["test/spam_test.py"] = r"""
|
project_with_a_failing_test.files["test/spam_test.py"] = r"""
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
@@ -155,7 +188,7 @@ def test_failing_test(tmp_path):
|
|||||||
@pytest.mark.parametrize("test_runner", ["pytest", "unittest"])
|
@pytest.mark.parametrize("test_runner", ["pytest", "unittest"])
|
||||||
def test_bare_pytest_invocation(
|
def test_bare_pytest_invocation(
|
||||||
tmp_path: Path, capfd: pytest.CaptureFixture[str], test_runner: str
|
tmp_path: Path, capfd: pytest.CaptureFixture[str], test_runner: str
|
||||||
):
|
) -> None:
|
||||||
"""Check that if a user runs pytest in the the test cwd, it raises a helpful error"""
|
"""Check that if a user runs pytest in the the test cwd, it raises a helpful error"""
|
||||||
project_dir = tmp_path / "project"
|
project_dir = tmp_path / "project"
|
||||||
output_dir = tmp_path / "output"
|
output_dir = tmp_path / "output"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from . import test_projects, utils
|
|||||||
basic_project = test_projects.new_c_project()
|
basic_project = test_projects.new_c_project()
|
||||||
|
|
||||||
|
|
||||||
def skip_if_no_msvc(arm64=False):
|
def skip_if_no_msvc(arm64: bool = False) -> None:
|
||||||
programfiles = os.getenv("PROGRAMFILES(X86)", "") or os.getenv("PROGRAMFILES", "")
|
programfiles = os.getenv("PROGRAMFILES(X86)", "") or os.getenv("PROGRAMFILES", "")
|
||||||
if not programfiles:
|
if not programfiles:
|
||||||
pytest.skip("Requires %PROGRAMFILES(X86)% variable to be set")
|
pytest.skip("Requires %PROGRAMFILES(X86)% variable to be set")
|
||||||
|
|||||||
+50
-40
@@ -10,8 +10,10 @@ import os
|
|||||||
import platform as pm
|
import platform as pm
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from collections.abc import Mapping, Sequence
|
||||||
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
from typing import Final
|
from typing import Any, Final
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@@ -37,7 +39,9 @@ else:
|
|||||||
raise Exception(msg)
|
raise Exception(msg)
|
||||||
|
|
||||||
|
|
||||||
def cibuildwheel_get_build_identifiers(project_path, env=None, *, prerelease_pythons=False):
|
def cibuildwheel_get_build_identifiers(
|
||||||
|
project_path: Path, env: dict[str, str] | None = None, *, prerelease_pythons: bool = False
|
||||||
|
) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Returns the list of build identifiers that cibuildwheel will try to build
|
Returns the list of build identifiers that cibuildwheel will try to build
|
||||||
for the current platform.
|
for the current platform.
|
||||||
@@ -75,14 +79,14 @@ def _update_pip_cache_dir(env: dict[str, str]) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def cibuildwheel_run(
|
def cibuildwheel_run(
|
||||||
project_path,
|
project_path: str | Path,
|
||||||
package_dir=".",
|
package_dir: str | Path = ".",
|
||||||
env=None,
|
env: dict[str, str] | None = None,
|
||||||
add_env=None,
|
add_env: Mapping[str, str] | None = None,
|
||||||
output_dir=None,
|
output_dir: Path | None = None,
|
||||||
add_args=None,
|
add_args: Sequence[str] | None = None,
|
||||||
single_python=False,
|
single_python: bool = False,
|
||||||
):
|
) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Runs cibuildwheel as a subprocess, building the project at project_path.
|
Runs cibuildwheel as a subprocess, building the project at project_path.
|
||||||
|
|
||||||
@@ -144,17 +148,17 @@ def _floor_macosx(*args: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def expected_wheels(
|
def expected_wheels(
|
||||||
package_name,
|
package_name: str,
|
||||||
package_version,
|
package_version: str,
|
||||||
manylinux_versions=None,
|
manylinux_versions: list[str] | None = None,
|
||||||
musllinux_versions=None,
|
musllinux_versions: list[str] | None = None,
|
||||||
macosx_deployment_target="10.9",
|
macosx_deployment_target: str = "10.9",
|
||||||
machine_arch=None,
|
machine_arch: str | None = None,
|
||||||
python_abi_tags=None,
|
python_abi_tags: list[str] | None = None,
|
||||||
include_universal2=False,
|
include_universal2: bool = False,
|
||||||
single_python=False,
|
single_python: bool = False,
|
||||||
single_arch=False,
|
single_arch: bool = False,
|
||||||
):
|
) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Returns a list of expected wheels from a run of cibuildwheel.
|
Returns a list of expected wheels from a run of cibuildwheel.
|
||||||
"""
|
"""
|
||||||
@@ -170,7 +174,9 @@ def expected_wheels(
|
|||||||
machine_arch = "aarch64"
|
machine_arch = "aarch64"
|
||||||
|
|
||||||
if manylinux_versions is None:
|
if manylinux_versions is None:
|
||||||
if machine_arch == "x86_64":
|
if machine_arch == "armv7l":
|
||||||
|
manylinux_versions = ["manylinux_2_17", "manylinux2014", "manylinux_2_31"]
|
||||||
|
elif machine_arch == "x86_64":
|
||||||
manylinux_versions = [
|
manylinux_versions = [
|
||||||
"manylinux_2_5",
|
"manylinux_2_5",
|
||||||
"manylinux1",
|
"manylinux1",
|
||||||
@@ -204,6 +210,7 @@ def expected_wheels(
|
|||||||
"pp38-pypy38_pp73",
|
"pp38-pypy38_pp73",
|
||||||
"pp39-pypy39_pp73",
|
"pp39-pypy39_pp73",
|
||||||
"pp310-pypy310_pp73",
|
"pp310-pypy310_pp73",
|
||||||
|
"pp311-pypy311_pp73",
|
||||||
]
|
]
|
||||||
|
|
||||||
if platform == "macos" and machine_arch == "arm64":
|
if platform == "macos" and machine_arch == "arm64":
|
||||||
@@ -219,6 +226,7 @@ def expected_wheels(
|
|||||||
"pp38-pypy38_pp73",
|
"pp38-pypy38_pp73",
|
||||||
"pp39-pypy39_pp73",
|
"pp39-pypy39_pp73",
|
||||||
"pp310-pypy310_pp73",
|
"pp310-pypy310_pp73",
|
||||||
|
"pp311-pypy311_pp73",
|
||||||
]
|
]
|
||||||
|
|
||||||
if single_python:
|
if single_python:
|
||||||
@@ -274,25 +282,27 @@ def expected_wheels(
|
|||||||
platform_tags = ["win32", "win_amd64"]
|
platform_tags = ["win32", "win_amd64"]
|
||||||
|
|
||||||
elif platform == "macos":
|
elif platform == "macos":
|
||||||
|
if python_abi_tag.startswith("pp"):
|
||||||
|
if python_abi_tag.startswith(("pp37", "pp38")):
|
||||||
|
min_macosx = macosx_deployment_target
|
||||||
|
else:
|
||||||
|
min_macosx = _floor_macosx(macosx_deployment_target, "10.15")
|
||||||
|
elif python_abi_tag.startswith("cp"):
|
||||||
|
if python_abi_tag.startswith(("cp36", "cp37", "cp38", "cp39", "cp310", "cp311")):
|
||||||
|
min_macosx = macosx_deployment_target
|
||||||
|
else:
|
||||||
|
min_macosx = _floor_macosx(macosx_deployment_target, "10.13")
|
||||||
|
else:
|
||||||
|
min_macosx = macosx_deployment_target
|
||||||
|
|
||||||
if machine_arch == "arm64":
|
if machine_arch == "arm64":
|
||||||
arm64_macosx = _floor_macosx(macosx_deployment_target, "11.0")
|
arm64_macosx = _floor_macosx(min_macosx, "11.0")
|
||||||
platform_tags = [f'macosx_{arm64_macosx.replace(".", "_")}_arm64']
|
platform_tags = [f'macosx_{arm64_macosx.replace(".", "_")}_arm64']
|
||||||
else:
|
else:
|
||||||
if python_abi_tag.startswith("pp") and not python_abi_tag.startswith(
|
platform_tags = [f'macosx_{min_macosx.replace(".", "_")}_x86_64']
|
||||||
("pp37", "pp38")
|
|
||||||
):
|
|
||||||
pypy_macosx = _floor_macosx(macosx_deployment_target, "10.15")
|
|
||||||
platform_tags = [f'macosx_{pypy_macosx.replace(".", "_")}_x86_64']
|
|
||||||
elif python_abi_tag.startswith("cp313"):
|
|
||||||
pypy_macosx = _floor_macosx(macosx_deployment_target, "10.13")
|
|
||||||
platform_tags = [f'macosx_{pypy_macosx.replace(".", "_")}_x86_64']
|
|
||||||
else:
|
|
||||||
platform_tags = [f'macosx_{macosx_deployment_target.replace(".", "_")}_x86_64']
|
|
||||||
|
|
||||||
if include_universal2:
|
if include_universal2:
|
||||||
platform_tags.append(
|
platform_tags.append(f'macosx_{min_macosx.replace(".", "_")}_universal2')
|
||||||
f'macosx_{macosx_deployment_target.replace(".", "_")}_universal2',
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
msg = f"Unsupported platform {platform!r}"
|
msg = f"Unsupported platform {platform!r}"
|
||||||
raise Exception(msg)
|
raise Exception(msg)
|
||||||
@@ -303,7 +313,7 @@ def expected_wheels(
|
|||||||
return wheels
|
return wheels
|
||||||
|
|
||||||
|
|
||||||
def get_macos_version():
|
def get_macos_version() -> tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
Returns the macOS major/minor version, as a tuple, e.g. (10, 15) or (11, 0)
|
Returns the macOS major/minor version, as a tuple, e.g. (10, 15) or (11, 0)
|
||||||
|
|
||||||
@@ -312,10 +322,10 @@ def get_macos_version():
|
|||||||
(11, 2) <= (11, 0) != True
|
(11, 2) <= (11, 0) != True
|
||||||
"""
|
"""
|
||||||
version_str, _, _ = pm.mac_ver()
|
version_str, _, _ = pm.mac_ver()
|
||||||
return tuple(map(int, version_str.split(".")[:2]))
|
return tuple(map(int, version_str.split(".")[:2])) # type: ignore[return-value]
|
||||||
|
|
||||||
|
|
||||||
def skip_if_pyodide(reason: str):
|
def skip_if_pyodide(reason: str) -> Any:
|
||||||
return pytest.mark.skipif(platform == "pyodide", reason=reason)
|
return pytest.mark.skipif(platform == "pyodide", reason=reason)
|
||||||
|
|
||||||
|
|
||||||
@@ -326,7 +336,7 @@ def invoke_pytest() -> str:
|
|||||||
return "pytest"
|
return "pytest"
|
||||||
|
|
||||||
|
|
||||||
def arch_name_for_linux(arch: str):
|
def arch_name_for_linux(arch: str) -> str:
|
||||||
"""
|
"""
|
||||||
Archs have different names on different platforms, but it's useful to be
|
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
|
able to run linux tests on dev machines. This function translates between
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from packaging.specifiers import SpecifierSet
|
from packaging.specifiers import SpecifierSet
|
||||||
|
|
||||||
from cibuildwheel.util import BuildSelector
|
from cibuildwheel.util import BuildSelector, EnableGroups
|
||||||
|
|
||||||
|
|
||||||
def test_build():
|
def test_build():
|
||||||
build_selector = BuildSelector(build_config="cp3*-* *-manylinux*", skip_config="")
|
build_selector = BuildSelector(
|
||||||
|
build_config="cp3*-* *-manylinux*", skip_config="", enable=frozenset([EnableGroups.PyPy])
|
||||||
|
)
|
||||||
|
|
||||||
assert build_selector("cp36-manylinux_x86_64")
|
assert build_selector("cp36-manylinux_x86_64")
|
||||||
assert build_selector("cp37-manylinux_x86_64")
|
assert build_selector("cp37-manylinux_x86_64")
|
||||||
@@ -43,7 +45,7 @@ def test_build_filter_pre():
|
|||||||
build_selector = BuildSelector(
|
build_selector = BuildSelector(
|
||||||
build_config="cp3*-* *-manylinux*",
|
build_config="cp3*-* *-manylinux*",
|
||||||
skip_config="",
|
skip_config="",
|
||||||
prerelease_pythons=True,
|
enable=frozenset([EnableGroups.CPythonPrerelease, EnableGroups.PyPy]),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert build_selector("cp37-manylinux_x86_64")
|
assert build_selector("cp37-manylinux_x86_64")
|
||||||
@@ -55,7 +57,9 @@ def test_build_filter_pre():
|
|||||||
|
|
||||||
def test_skip():
|
def test_skip():
|
||||||
build_selector = BuildSelector(
|
build_selector = BuildSelector(
|
||||||
build_config="*", skip_config="pp36-* cp3?-manylinux_i686 cp36-win* *-win32"
|
build_config="*",
|
||||||
|
skip_config="pp36-* cp3?-manylinux_i686 cp36-win* *-win32",
|
||||||
|
enable=frozenset([EnableGroups.PyPy]),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not build_selector("pp36-manylinux_x86_64")
|
assert not build_selector("pp36-manylinux_x86_64")
|
||||||
@@ -79,7 +83,9 @@ def test_skip():
|
|||||||
|
|
||||||
def test_build_and_skip():
|
def test_build_and_skip():
|
||||||
build_selector = BuildSelector(
|
build_selector = BuildSelector(
|
||||||
build_config="cp36-* cp37-macosx* *-manylinux*", skip_config="pp37-* cp37-manylinux_i686"
|
build_config="cp36-* cp37-macosx* *-manylinux*",
|
||||||
|
skip_config="pp37-* cp37-manylinux_i686",
|
||||||
|
enable=frozenset([EnableGroups.PyPy]),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not build_selector("pp37-manylinux_x86_64")
|
assert not build_selector("pp37-manylinux_x86_64")
|
||||||
@@ -110,7 +116,10 @@ def test_build_braces():
|
|||||||
|
|
||||||
def test_build_limited_python():
|
def test_build_limited_python():
|
||||||
build_selector = BuildSelector(
|
build_selector = BuildSelector(
|
||||||
build_config="*", skip_config="", requires_python=SpecifierSet(">=3.7")
|
build_config="*",
|
||||||
|
skip_config="",
|
||||||
|
requires_python=SpecifierSet(">=3.7"),
|
||||||
|
enable=frozenset([EnableGroups.PyPy]),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not build_selector("cp36-manylinux_x86_64")
|
assert not build_selector("cp36-manylinux_x86_64")
|
||||||
@@ -146,9 +155,7 @@ def test_build_limited_python_patch():
|
|||||||
|
|
||||||
|
|
||||||
def test_build_free_threaded_python():
|
def test_build_free_threaded_python():
|
||||||
build_selector = BuildSelector(
|
build_selector = BuildSelector(build_config="*", skip_config="", enable=frozenset(EnableGroups))
|
||||||
build_config="*", skip_config="", prerelease_pythons=True, free_threaded_support=True
|
|
||||||
)
|
|
||||||
|
|
||||||
assert build_selector("cp313t-manylinux_x86_64")
|
assert build_selector("cp313t-manylinux_x86_64")
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import textwrap
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import cibuildwheel.linux
|
import cibuildwheel.linux
|
||||||
from cibuildwheel.oci_container import OCIContainerEngineConfig
|
from cibuildwheel.oci_container import OCIContainerEngineConfig
|
||||||
from cibuildwheel.options import CommandLineArguments, Options
|
from cibuildwheel.options import CommandLineArguments, Options
|
||||||
|
|
||||||
|
|
||||||
def test_linux_container_split(tmp_path: Path, monkeypatch):
|
def test_linux_container_split(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
"""
|
"""
|
||||||
Tests splitting linux builds by container image, container engine, and before_all
|
Tests splitting linux builds by container image, container engine, and before_all
|
||||||
"""
|
"""
|
||||||
@@ -53,13 +55,13 @@ def test_linux_container_split(tmp_path: Path, monkeypatch):
|
|||||||
build_steps = list(cibuildwheel.linux.get_build_steps(options, python_configurations))
|
build_steps = list(cibuildwheel.linux.get_build_steps(options, python_configurations))
|
||||||
|
|
||||||
# helper functions to extract test info
|
# helper functions to extract test info
|
||||||
def identifiers(step):
|
def identifiers(step: cibuildwheel.linux.BuildStep) -> list[str]:
|
||||||
return [c.identifier for c in step.platform_configs]
|
return [c.identifier for c in step.platform_configs]
|
||||||
|
|
||||||
def before_alls(step):
|
def before_alls(step: cibuildwheel.linux.BuildStep) -> list[str]:
|
||||||
return [options.build_options(c.identifier).before_all for c in step.platform_configs]
|
return [options.build_options(c.identifier).before_all for c in step.platform_configs]
|
||||||
|
|
||||||
def container_engines(step):
|
def container_engines(step: cibuildwheel.linux.BuildStep) -> list[OCIContainerEngineConfig]:
|
||||||
return [options.build_options(c.identifier).container_engine for c in step.platform_configs]
|
return [options.build_options(c.identifier).container_engine for c in step.platform_configs]
|
||||||
|
|
||||||
pprint(build_steps)
|
pprint(build_steps)
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ from cibuildwheel import linux, macos, util, windows
|
|||||||
|
|
||||||
|
|
||||||
class ArgsInterceptor:
|
class ArgsInterceptor:
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
self.call_count = 0
|
self.call_count = 0
|
||||||
self.args = None
|
self.args: tuple[object, ...] | None = None
|
||||||
self.kwargs = None
|
self.kwargs: dict[str, object] | None = None
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args: object, **kwargs: object) -> None:
|
||||||
self.call_count += 1
|
self.call_count += 1
|
||||||
self.args = args
|
self.args = args
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ def test_manylinux_images(
|
|||||||
assert build_options.manylinux_images is None
|
assert build_options.manylinux_images is None
|
||||||
|
|
||||||
|
|
||||||
def get_default_repair_command(platform):
|
def get_default_repair_command(platform: str) -> str:
|
||||||
if platform == "linux":
|
if platform == "linux":
|
||||||
return "auditwheel repair -w {dest_dir} {wheel}"
|
return "auditwheel repair -w {dest_dir} {wheel}"
|
||||||
elif platform == "macos":
|
elif platform == "macos":
|
||||||
@@ -270,7 +270,7 @@ def test_config_settings(platform_specific, platform, intercepted_build_args, mo
|
|||||||
config_settings = 'setting=value setting=value2 other="something else"'
|
config_settings = 'setting=value setting=value2 other="something else"'
|
||||||
if platform_specific:
|
if platform_specific:
|
||||||
monkeypatch.setenv("CIBW_CONFIG_SETTINGS_" + platform.upper(), config_settings)
|
monkeypatch.setenv("CIBW_CONFIG_SETTINGS_" + platform.upper(), config_settings)
|
||||||
monkeypatch.setenv("CIBW_CONFIG_SETTIGNS", "a=b")
|
monkeypatch.setenv("CIBW_CONFIG_SETTINGS", "a=b")
|
||||||
else:
|
else:
|
||||||
monkeypatch.setenv("CIBW_CONFIG_SETTINGS", config_settings)
|
monkeypatch.setenv("CIBW_CONFIG_SETTINGS", config_settings)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import pytest
|
|||||||
|
|
||||||
from cibuildwheel.__main__ import main
|
from cibuildwheel.__main__ import main
|
||||||
from cibuildwheel.architecture import Architecture
|
from cibuildwheel.architecture import Architecture
|
||||||
|
from cibuildwheel.util import EnableGroups
|
||||||
|
|
||||||
from ..conftest import MOCK_PACKAGE_DIR
|
from ..conftest import MOCK_PACKAGE_DIR
|
||||||
|
|
||||||
@@ -179,6 +180,7 @@ def test_archs_platform_all(platform, intercepted_build_args, monkeypatch):
|
|||||||
Architecture.aarch64,
|
Architecture.aarch64,
|
||||||
Architecture.ppc64le,
|
Architecture.ppc64le,
|
||||||
Architecture.s390x,
|
Architecture.s390x,
|
||||||
|
Architecture.armv7l,
|
||||||
}
|
}
|
||||||
elif platform == "windows":
|
elif platform == "windows":
|
||||||
assert options.globals.architectures == {
|
assert options.globals.architectures == {
|
||||||
@@ -215,7 +217,7 @@ def test_only_argument(intercepted_build_args, monkeypatch, only, plat):
|
|||||||
assert options.globals.build_selector.skip_config == ""
|
assert options.globals.build_selector.skip_config == ""
|
||||||
assert options.platform == plat
|
assert options.platform == plat
|
||||||
assert options.globals.architectures == Architecture.all_archs(plat)
|
assert options.globals.architectures == Architecture.all_archs(plat)
|
||||||
assert options.globals.build_selector.prerelease_pythons is True
|
assert EnableGroups.PyPy in options.globals.build_selector.enable
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("only", ("cp311-manylxinux_x86_64", "some_linux_thing"))
|
@pytest.mark.parametrize("only", ("cp311-manylxinux_x86_64", "some_linux_thing"))
|
||||||
|
|||||||
+279
-44
@@ -6,14 +6,24 @@ import platform
|
|||||||
import random
|
import random
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
import time
|
||||||
|
from contextlib import nullcontext
|
||||||
from pathlib import Path, PurePath, PurePosixPath
|
from pathlib import Path, PurePath, PurePosixPath
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import tomli_w
|
import tomli_w
|
||||||
|
|
||||||
|
import cibuildwheel.oci_container
|
||||||
from cibuildwheel.environment import EnvironmentAssignmentBash
|
from cibuildwheel.environment import EnvironmentAssignmentBash
|
||||||
from cibuildwheel.oci_container import OCIContainer, OCIContainerEngineConfig
|
from cibuildwheel.errors import OCIEngineTooOldError
|
||||||
|
from cibuildwheel.oci_container import (
|
||||||
|
OCIContainer,
|
||||||
|
OCIContainerEngineConfig,
|
||||||
|
OCIPlatform,
|
||||||
|
_check_engine_version,
|
||||||
|
)
|
||||||
from cibuildwheel.util import CIProvider, detect_ci_provider
|
from cibuildwheel.util import CIProvider, detect_ci_provider
|
||||||
|
|
||||||
# Test utilities
|
# Test utilities
|
||||||
@@ -28,6 +38,14 @@ elif pm in {"aarch64", "arm64"}:
|
|||||||
DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine="aarch64")
|
DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine="aarch64")
|
||||||
else:
|
else:
|
||||||
DEFAULT_IMAGE = ""
|
DEFAULT_IMAGE = ""
|
||||||
|
DEFAULT_OCI_PLATFORM = {
|
||||||
|
"AMD64": OCIPlatform.AMD64,
|
||||||
|
"x86_64": OCIPlatform.AMD64,
|
||||||
|
"ppc64le": OCIPlatform.PPC64LE,
|
||||||
|
"s390x": OCIPlatform.S390X,
|
||||||
|
"aarch64": OCIPlatform.ARM64,
|
||||||
|
"arm64": OCIPlatform.ARM64,
|
||||||
|
}[pm]
|
||||||
|
|
||||||
PODMAN = OCIContainerEngineConfig(name="podman")
|
PODMAN = OCIContainerEngineConfig(name="podman")
|
||||||
|
|
||||||
@@ -63,24 +81,32 @@ def container_engine(request):
|
|||||||
|
|
||||||
|
|
||||||
def test_simple(container_engine):
|
def test_simple(container_engine):
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
assert container.call(["echo", "hello"], capture_output=True) == "hello\n"
|
assert container.call(["echo", "hello"], capture_output=True) == "hello\n"
|
||||||
|
|
||||||
|
|
||||||
def test_no_lf(container_engine):
|
def test_no_lf(container_engine):
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
assert container.call(["printf", "hello"], capture_output=True) == "hello"
|
assert container.call(["printf", "hello"], capture_output=True) == "hello"
|
||||||
|
|
||||||
|
|
||||||
def test_debug_info(container_engine):
|
def test_debug_info(container_engine):
|
||||||
container = OCIContainer(engine=container_engine, image=DEFAULT_IMAGE)
|
container = OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
)
|
||||||
print(container.debug_info())
|
print(container.debug_info())
|
||||||
with container:
|
with container:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_environment(container_engine):
|
def test_environment(container_engine):
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
assert (
|
assert (
|
||||||
container.call(
|
container.call(
|
||||||
["sh", "-c", "echo $TEST_VAR"], env={"TEST_VAR": "1"}, capture_output=True
|
["sh", "-c", "echo $TEST_VAR"], env={"TEST_VAR": "1"}, capture_output=True
|
||||||
@@ -92,7 +118,9 @@ def test_environment(container_engine):
|
|||||||
def test_environment_pass(container_engine, monkeypatch):
|
def test_environment_pass(container_engine, monkeypatch):
|
||||||
monkeypatch.setenv("CIBUILDWHEEL", "1")
|
monkeypatch.setenv("CIBUILDWHEEL", "1")
|
||||||
monkeypatch.setenv("SOURCE_DATE_EPOCH", "1489957071")
|
monkeypatch.setenv("SOURCE_DATE_EPOCH", "1489957071")
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
assert container.call(["sh", "-c", "echo $CIBUILDWHEEL"], capture_output=True) == "1\n"
|
assert container.call(["sh", "-c", "echo $CIBUILDWHEEL"], capture_output=True) == "1\n"
|
||||||
assert (
|
assert (
|
||||||
container.call(["sh", "-c", "echo $SOURCE_DATE_EPOCH"], capture_output=True)
|
container.call(["sh", "-c", "echo $SOURCE_DATE_EPOCH"], capture_output=True)
|
||||||
@@ -102,14 +130,37 @@ def test_environment_pass(container_engine, monkeypatch):
|
|||||||
|
|
||||||
def test_cwd(container_engine):
|
def test_cwd(container_engine):
|
||||||
with OCIContainer(
|
with OCIContainer(
|
||||||
engine=container_engine, image=DEFAULT_IMAGE, cwd="/cibuildwheel/working_directory"
|
engine=container_engine,
|
||||||
|
image=DEFAULT_IMAGE,
|
||||||
|
oci_platform=DEFAULT_OCI_PLATFORM,
|
||||||
|
cwd="/cibuildwheel/working_directory",
|
||||||
) as container:
|
) as container:
|
||||||
assert container.call(["pwd"], capture_output=True) == "/cibuildwheel/working_directory\n"
|
assert container.call(["pwd"], capture_output=True) == "/cibuildwheel/working_directory\n"
|
||||||
assert container.call(["pwd"], capture_output=True, cwd="/opt") == "/opt\n"
|
assert container.call(["pwd"], capture_output=True, cwd="/opt") == "/opt\n"
|
||||||
|
|
||||||
|
|
||||||
def test_container_removed(container_engine):
|
def test_container_removed(container_engine):
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
# test is flaky on some platforms, implement retry for 5 second
|
||||||
|
timeout = 50 # * 100 ms = 5s
|
||||||
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
|
assert container.name is not None
|
||||||
|
container_name = container.name
|
||||||
|
for _ in range(timeout):
|
||||||
|
docker_containers_listing = subprocess.run(
|
||||||
|
f"{container.engine.name} container ls",
|
||||||
|
shell=True,
|
||||||
|
check=True,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
).stdout
|
||||||
|
if container_name in docker_containers_listing:
|
||||||
|
break
|
||||||
|
time.sleep(0.1)
|
||||||
|
assert container_name in docker_containers_listing
|
||||||
|
|
||||||
|
for _ in range(timeout):
|
||||||
docker_containers_listing = subprocess.run(
|
docker_containers_listing = subprocess.run(
|
||||||
f"{container.engine.name} container ls",
|
f"{container.engine.name} container ls",
|
||||||
shell=True,
|
shell=True,
|
||||||
@@ -117,18 +168,10 @@ def test_container_removed(container_engine):
|
|||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
text=True,
|
text=True,
|
||||||
).stdout
|
).stdout
|
||||||
assert container.name is not None
|
if container_name not in docker_containers_listing:
|
||||||
assert container.name in docker_containers_listing
|
break
|
||||||
old_container_name = container.name
|
time.sleep(0.1)
|
||||||
|
assert container_name not in docker_containers_listing
|
||||||
docker_containers_listing = subprocess.run(
|
|
||||||
f"{container.engine.name} container ls",
|
|
||||||
shell=True,
|
|
||||||
check=True,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
text=True,
|
|
||||||
).stdout
|
|
||||||
assert old_container_name not in docker_containers_listing
|
|
||||||
|
|
||||||
|
|
||||||
def test_large_environment(container_engine):
|
def test_large_environment(container_engine):
|
||||||
@@ -141,7 +184,9 @@ def test_large_environment(container_engine):
|
|||||||
"d": "0" * long_env_var_length,
|
"d": "0" * long_env_var_length,
|
||||||
}
|
}
|
||||||
|
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
# check the length of d
|
# check the length of d
|
||||||
assert (
|
assert (
|
||||||
container.call(["sh", "-c", "echo ${#d}"], env=large_environment, capture_output=True)
|
container.call(["sh", "-c", "echo ${#d}"], env=large_environment, capture_output=True)
|
||||||
@@ -150,7 +195,9 @@ def test_large_environment(container_engine):
|
|||||||
|
|
||||||
|
|
||||||
def test_binary_output(container_engine):
|
def test_binary_output(container_engine):
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
# note: the below embedded snippets are in python2
|
# note: the below embedded snippets are in python2
|
||||||
|
|
||||||
# check that we can pass though arbitrary binary data without erroring
|
# check that we can pass though arbitrary binary data without erroring
|
||||||
@@ -199,8 +246,10 @@ def test_binary_output(container_engine):
|
|||||||
assert output == binary_data_string
|
assert output == binary_data_string
|
||||||
|
|
||||||
|
|
||||||
def test_file_operation(tmp_path: Path, container_engine):
|
def test_file_operation(tmp_path: Path, container_engine: OCIContainerEngineConfig) -> None:
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
# test copying a file in
|
# test copying a file in
|
||||||
test_binary_data = bytes(random.randrange(256) for _ in range(1000))
|
test_binary_data = bytes(random.randrange(256) for _ in range(1000))
|
||||||
original_test_file = tmp_path / "test.dat"
|
original_test_file = tmp_path / "test.dat"
|
||||||
@@ -210,12 +259,17 @@ def test_file_operation(tmp_path: Path, container_engine):
|
|||||||
|
|
||||||
container.copy_into(original_test_file, dst_file)
|
container.copy_into(original_test_file, dst_file)
|
||||||
|
|
||||||
|
owner = container.call(["stat", "-c", "%u:%g", dst_file], capture_output=True).strip()
|
||||||
|
assert owner == "0:0"
|
||||||
|
|
||||||
output = container.call(["cat", dst_file], capture_output=True)
|
output = container.call(["cat", dst_file], capture_output=True)
|
||||||
assert test_binary_data == bytes(output, encoding="utf8", errors="surrogateescape")
|
assert test_binary_data == bytes(output, encoding="utf8", errors="surrogateescape")
|
||||||
|
|
||||||
|
|
||||||
def test_dir_operations(tmp_path: Path, container_engine):
|
def test_dir_operations(tmp_path: Path, container_engine: OCIContainerEngineConfig) -> None:
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
test_binary_data = bytes(random.randrange(256) for _ in range(1000))
|
test_binary_data = bytes(random.randrange(256) for _ in range(1000))
|
||||||
original_test_file = tmp_path / "test.dat"
|
original_test_file = tmp_path / "test.dat"
|
||||||
original_test_file.write_bytes(test_binary_data)
|
original_test_file.write_bytes(test_binary_data)
|
||||||
@@ -230,6 +284,12 @@ def test_dir_operations(tmp_path: Path, container_engine):
|
|||||||
dst_file = dst_dir / "test.dat"
|
dst_file = dst_dir / "test.dat"
|
||||||
container.copy_into(test_dir, dst_dir)
|
container.copy_into(test_dir, dst_dir)
|
||||||
|
|
||||||
|
owner = container.call(["stat", "-c", "%u:%g", dst_dir], capture_output=True).strip()
|
||||||
|
assert owner == "0:0"
|
||||||
|
|
||||||
|
owner = container.call(["stat", "-c", "%u:%g", dst_file], capture_output=True).strip()
|
||||||
|
assert owner == "0:0"
|
||||||
|
|
||||||
output = container.call(["cat", dst_file], capture_output=True)
|
output = container.call(["cat", dst_file], capture_output=True)
|
||||||
assert test_binary_data == bytes(output, encoding="utf8", errors="surrogateescape")
|
assert test_binary_data == bytes(output, encoding="utf8", errors="surrogateescape")
|
||||||
|
|
||||||
@@ -240,18 +300,29 @@ def test_dir_operations(tmp_path: Path, container_engine):
|
|||||||
new_test_dir = tmp_path / "test_dir_new"
|
new_test_dir = tmp_path / "test_dir_new"
|
||||||
container.copy_out(dst_dir, new_test_dir)
|
container.copy_out(dst_dir, new_test_dir)
|
||||||
|
|
||||||
|
assert os.getuid() == new_test_dir.stat().st_uid
|
||||||
|
assert os.getgid() == new_test_dir.stat().st_gid
|
||||||
|
assert os.getuid() == (new_test_dir / "test.dat").stat().st_uid
|
||||||
|
assert os.getgid() == (new_test_dir / "test.dat").stat().st_gid
|
||||||
|
|
||||||
assert test_binary_data == (new_test_dir / "test.dat").read_bytes()
|
assert test_binary_data == (new_test_dir / "test.dat").read_bytes()
|
||||||
|
|
||||||
|
|
||||||
def test_environment_executor(container_engine):
|
def test_environment_executor(container_engine: OCIContainerEngineConfig) -> None:
|
||||||
with OCIContainer(engine=container_engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
assignment = EnvironmentAssignmentBash("TEST=$(echo 42)")
|
assignment = EnvironmentAssignmentBash("TEST=$(echo 42)")
|
||||||
assert assignment.evaluated_value({}, container.environment_executor) == "42"
|
assert assignment.evaluated_value({}, container.environment_executor) == "42"
|
||||||
|
|
||||||
|
|
||||||
def test_podman_vfs(tmp_path: Path, monkeypatch, container_engine):
|
def test_podman_vfs(
|
||||||
|
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, container_engine: OCIContainerEngineConfig
|
||||||
|
) -> None:
|
||||||
if container_engine.name != "podman":
|
if container_engine.name != "podman":
|
||||||
pytest.skip("only runs with podman")
|
pytest.skip("only runs with podman")
|
||||||
|
if sys.platform.startswith("darwin"):
|
||||||
|
pytest.skip("Skipping test because podman on this platform does not support vfs")
|
||||||
|
|
||||||
# create the VFS configuration
|
# create the VFS configuration
|
||||||
vfs_path = tmp_path / "podman_vfs"
|
vfs_path = tmp_path / "podman_vfs"
|
||||||
@@ -309,7 +380,9 @@ def test_podman_vfs(tmp_path: Path, monkeypatch, container_engine):
|
|||||||
monkeypatch.setenv("CONTAINERS_CONF", str(vfs_containers_conf_fpath))
|
monkeypatch.setenv("CONTAINERS_CONF", str(vfs_containers_conf_fpath))
|
||||||
monkeypatch.setenv("CONTAINERS_STORAGE_CONF", str(vfs_containers_storage_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, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
# test running a command
|
# test running a command
|
||||||
assert container.call(["echo", "hello"], capture_output=True) == "hello\n"
|
assert container.call(["echo", "hello"], capture_output=True) == "hello\n"
|
||||||
|
|
||||||
@@ -327,7 +400,7 @@ def test_podman_vfs(tmp_path: Path, monkeypatch, container_engine):
|
|||||||
subprocess.run(["podman", "unshare", "rm", "-rf", vfs_path], check=True)
|
subprocess.run(["podman", "unshare", "rm", "-rf", vfs_path], check=True)
|
||||||
|
|
||||||
|
|
||||||
def test_create_args_volume(tmp_path: Path, container_engine):
|
def test_create_args_volume(tmp_path: Path, container_engine: OCIContainerEngineConfig) -> None:
|
||||||
if container_engine.name != "docker":
|
if container_engine.name != "docker":
|
||||||
pytest.skip("only runs with docker")
|
pytest.skip("only runs with docker")
|
||||||
|
|
||||||
@@ -346,6 +419,7 @@ def test_create_args_volume(tmp_path: Path, container_engine):
|
|||||||
with OCIContainer(
|
with OCIContainer(
|
||||||
engine=container_engine,
|
engine=container_engine,
|
||||||
image=DEFAULT_IMAGE,
|
image=DEFAULT_IMAGE,
|
||||||
|
oci_platform=DEFAULT_OCI_PLATFORM,
|
||||||
) as container:
|
) as container:
|
||||||
assert container.call(["cat", "/test_mount/test_file.txt"], capture_output=True) == "1234"
|
assert container.call(["cat", "/test_mount/test_file.txt"], capture_output=True) == "1234"
|
||||||
|
|
||||||
@@ -388,24 +462,47 @@ def test_create_args_volume(tmp_path: Path, container_engine):
|
|||||||
"docker",
|
"docker",
|
||||||
("--some-option=value; with; semicolons", "--another-option"),
|
("--some-option=value; with; semicolons", "--another-option"),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"docker; create_args: --platform=linux/amd64",
|
||||||
|
"docker",
|
||||||
|
(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"podman; create_args: --platform=linux/amd64",
|
||||||
|
"podman",
|
||||||
|
(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"docker; create_args: --platform linux/amd64",
|
||||||
|
"docker",
|
||||||
|
(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"podman; create_args: --platform linux/amd64",
|
||||||
|
"podman",
|
||||||
|
(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_parse_engine_config(config, name, create_args):
|
def test_parse_engine_config(config, name, create_args, capsys):
|
||||||
engine_config = OCIContainerEngineConfig.from_config_string(config)
|
engine_config = OCIContainerEngineConfig.from_config_string(config)
|
||||||
assert engine_config.name == name
|
assert engine_config.name == name
|
||||||
assert engine_config.create_args == create_args
|
assert engine_config.create_args == create_args
|
||||||
|
if "--platform" in config:
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert (
|
||||||
|
"Using '--platform' in 'container-engine::create_args' is deprecated. It will be ignored."
|
||||||
|
in captured.err
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(pm != "x86_64", reason="Only runs on x86_64")
|
@pytest.mark.skipif(pm != "x86_64", reason="Only runs on x86_64")
|
||||||
@pytest.mark.parametrize(
|
def test_enforce_32_bit(container_engine):
|
||||||
("image", "shell_args"),
|
with OCIContainer(
|
||||||
[
|
engine=container_engine,
|
||||||
(DEFAULT_IMAGE_TEMPLATE.format(machine="i686"), ["/bin/bash"]),
|
image=DEFAULT_IMAGE_TEMPLATE.format(machine="i686"),
|
||||||
(DEFAULT_IMAGE_TEMPLATE.format(machine="x86_64"), ["linux32", "/bin/bash"]),
|
oci_platform=OCIPlatform.i386,
|
||||||
],
|
) as container:
|
||||||
)
|
|
||||||
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"
|
assert container.call(["uname", "-m"], capture_output=True).strip() == "i686"
|
||||||
container_args = subprocess.run(
|
container_args = subprocess.run(
|
||||||
f"{container.engine.name} inspect -f '{{{{json .Args }}}}' {container.name}",
|
f"{container.engine.name} inspect -f '{{{{json .Args }}}}' {container.name}",
|
||||||
@@ -414,7 +511,7 @@ def test_enforce_32_bit(container_engine, image, shell_args):
|
|||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
text=True,
|
text=True,
|
||||||
).stdout
|
).stdout
|
||||||
assert json.loads(container_args) == shell_args
|
assert json.loads(container_args) == ["/bin/bash"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -425,19 +522,157 @@ def test_enforce_32_bit(container_engine, image, shell_args):
|
|||||||
("{name}; disable_host_mount: true", False),
|
("{name}; disable_host_mount: true", False),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_disable_host_mount(tmp_path: Path, container_engine, config, should_have_host_mount):
|
def test_disable_host_mount(
|
||||||
|
tmp_path: Path,
|
||||||
|
container_engine: OCIContainerEngineConfig,
|
||||||
|
config: str,
|
||||||
|
should_have_host_mount: bool,
|
||||||
|
) -> None:
|
||||||
if detect_ci_provider() in {CIProvider.circle_ci, CIProvider.gitlab}:
|
if detect_ci_provider() in {CIProvider.circle_ci, CIProvider.gitlab}:
|
||||||
pytest.skip("Skipping test because docker on this platform does not support host mounts")
|
pytest.skip("Skipping test because docker on this platform does not support host mounts")
|
||||||
|
if sys.platform.startswith("darwin"):
|
||||||
|
pytest.skip("Skipping test because docker on this platform does not support host mounts")
|
||||||
|
|
||||||
engine = OCIContainerEngineConfig.from_config_string(config.format(name=container_engine.name))
|
engine = OCIContainerEngineConfig.from_config_string(config.format(name=container_engine.name))
|
||||||
|
|
||||||
sentinel_file = tmp_path / "sentinel"
|
sentinel_file = tmp_path / "sentinel"
|
||||||
sentinel_file.write_text("12345")
|
sentinel_file.write_text("12345")
|
||||||
|
|
||||||
with OCIContainer(engine=engine, image=DEFAULT_IMAGE) as container:
|
with OCIContainer(
|
||||||
|
engine=engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
|
||||||
|
) as container:
|
||||||
host_mount_path = "/host" + str(sentinel_file)
|
host_mount_path = "/host" + str(sentinel_file)
|
||||||
if should_have_host_mount:
|
if should_have_host_mount:
|
||||||
assert container.call(["cat", host_mount_path], capture_output=True) == "12345"
|
assert container.call(["cat", host_mount_path], capture_output=True) == "12345"
|
||||||
else:
|
else:
|
||||||
with pytest.raises(subprocess.CalledProcessError):
|
with pytest.raises(subprocess.CalledProcessError):
|
||||||
container.call(["cat", host_mount_path], capture_output=True)
|
container.call(["cat", host_mount_path], capture_output=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("platform", list(OCIPlatform))
|
||||||
|
def test_local_image(
|
||||||
|
container_engine: OCIContainerEngineConfig, platform: OCIPlatform, tmp_path: Path
|
||||||
|
) -> None:
|
||||||
|
if (
|
||||||
|
detect_ci_provider() in {CIProvider.travis_ci}
|
||||||
|
and pm in {"s390x", "ppc64le"}
|
||||||
|
and platform != DEFAULT_OCI_PLATFORM
|
||||||
|
):
|
||||||
|
pytest.skip("Skipping test because docker on this platform does not support QEMU")
|
||||||
|
if container_engine.name == "podman" and platform == OCIPlatform.ARMV7:
|
||||||
|
# both GHA & local macOS arm64 podman desktop are failing
|
||||||
|
pytest.xfail("podman fails with armv7l images")
|
||||||
|
|
||||||
|
remote_image = "debian:12-slim"
|
||||||
|
platform_name = platform.value.replace("/", "_")
|
||||||
|
local_image = f"cibw_{container_engine.name}_{platform_name}_local:latest"
|
||||||
|
dockerfile = tmp_path / "Dockerfile"
|
||||||
|
dockerfile.write_text(f"FROM {remote_image}")
|
||||||
|
subprocess.run(
|
||||||
|
[container_engine.name, "pull", f"--platform={platform.value}", remote_image],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
subprocess.run(
|
||||||
|
[container_engine.name, "build", f"--platform={platform.value}", "-t", local_image, "."],
|
||||||
|
check=True,
|
||||||
|
cwd=tmp_path,
|
||||||
|
)
|
||||||
|
with OCIContainer(engine=container_engine, image=local_image, oci_platform=platform):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("platform", list(OCIPlatform))
|
||||||
|
def test_multiarch_image(container_engine, platform):
|
||||||
|
if (
|
||||||
|
detect_ci_provider() in {CIProvider.travis_ci}
|
||||||
|
and pm in {"s390x", "ppc64le"}
|
||||||
|
and platform != DEFAULT_OCI_PLATFORM
|
||||||
|
):
|
||||||
|
pytest.skip("Skipping test because docker on this platform does not support QEMU")
|
||||||
|
if container_engine.name == "podman" and platform == OCIPlatform.ARMV7:
|
||||||
|
# both GHA & local macOS arm64 podman desktop are failing
|
||||||
|
pytest.xfail("podman fails with armv7l images")
|
||||||
|
with OCIContainer(
|
||||||
|
engine=container_engine, image="debian:12-slim", oci_platform=platform
|
||||||
|
) as container:
|
||||||
|
output = container.call(["uname", "-m"], capture_output=True)
|
||||||
|
output_map_kernel = {
|
||||||
|
OCIPlatform.i386: ("i686",),
|
||||||
|
OCIPlatform.AMD64: ("x86_64",),
|
||||||
|
OCIPlatform.ARMV7: ("armv7l", "armv8l"),
|
||||||
|
OCIPlatform.ARM64: ("aarch64",),
|
||||||
|
OCIPlatform.PPC64LE: ("ppc64le",),
|
||||||
|
OCIPlatform.S390X: ("s390x",),
|
||||||
|
}
|
||||||
|
assert output.strip() in output_map_kernel[platform]
|
||||||
|
output = container.call(["dpkg", "--print-architecture"], capture_output=True)
|
||||||
|
output_map_dpkg = {
|
||||||
|
OCIPlatform.i386: "i386",
|
||||||
|
OCIPlatform.AMD64: "amd64",
|
||||||
|
OCIPlatform.ARMV7: "armhf",
|
||||||
|
OCIPlatform.ARM64: "arm64",
|
||||||
|
OCIPlatform.PPC64LE: "ppc64el",
|
||||||
|
OCIPlatform.S390X: "s390x",
|
||||||
|
}
|
||||||
|
assert output_map_dpkg[platform] == output.strip()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("engine_name", "version", "context"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"docker",
|
||||||
|
None, # 17.12.1-ce does supports "docker version --format '{{json . }}'" so a version before that
|
||||||
|
pytest.raises(OCIEngineTooOldError),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"docker",
|
||||||
|
'{"Client":{"Version":"19.03.15","ApiVersion": "1.40"},"Server":{"ApiVersion": "1.40"}}',
|
||||||
|
pytest.raises(OCIEngineTooOldError),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"docker",
|
||||||
|
'{"Client":{"Version":"20.10.0","ApiVersion":"1.41"},"Server":{"ApiVersion":"1.41"}}',
|
||||||
|
nullcontext(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"docker",
|
||||||
|
'{"Client":{"Version":"24.0.0","ApiVersion":"1.43"},"Server":{"ApiVersion":"1.43"}}',
|
||||||
|
nullcontext(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"docker",
|
||||||
|
'{"Client":{"ApiVersion":"1.43"},"Server":{"ApiVersion":"1.30"}}',
|
||||||
|
pytest.raises(OCIEngineTooOldError),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"docker",
|
||||||
|
'{"Client":{"ApiVersion":"1.30"},"Server":{"ApiVersion":"1.43"}}',
|
||||||
|
pytest.raises(OCIEngineTooOldError),
|
||||||
|
),
|
||||||
|
("podman", '{"Client":{"Version":"5.2.0"},"Server":{"Version":"5.1.2"}}', nullcontext()),
|
||||||
|
("podman", '{"Client":{"Version":"4.9.4-rhel"}}', nullcontext()),
|
||||||
|
(
|
||||||
|
"podman",
|
||||||
|
'{"Client":{"Version":"5.2.0"},"Server":{"Version":"2.1.2"}}',
|
||||||
|
pytest.raises(OCIEngineTooOldError),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"podman",
|
||||||
|
'{"Client":{"Version":"2.2.0"},"Server":{"Version":"5.1.2"}}',
|
||||||
|
pytest.raises(OCIEngineTooOldError),
|
||||||
|
),
|
||||||
|
("podman", '{"Client":{"Version":"3.0~rc1-rhel"}}', nullcontext()),
|
||||||
|
("podman", '{"Client":{"Version":"2.1.0~rc1"}}', pytest.raises(OCIEngineTooOldError)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_engine_version(engine_name, version, context, monkeypatch):
|
||||||
|
def mockcall(*args, **kwargs):
|
||||||
|
if version is None:
|
||||||
|
raise subprocess.CalledProcessError(1, " ".join(str(arg) for arg in args))
|
||||||
|
return version
|
||||||
|
|
||||||
|
monkeypatch.setattr(cibuildwheel.oci_container, "call", mockcall)
|
||||||
|
engine = OCIContainerEngineConfig.from_config_string(engine_name)
|
||||||
|
with context:
|
||||||
|
_check_engine_version(engine)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import pytest
|
|||||||
|
|
||||||
from cibuildwheel import linux, util
|
from cibuildwheel import linux, util
|
||||||
from cibuildwheel.__main__ import main
|
from cibuildwheel.__main__ import main
|
||||||
|
from cibuildwheel.oci_container import OCIPlatform
|
||||||
|
|
||||||
ALL_IDS = {
|
ALL_IDS = {
|
||||||
"cp36",
|
"cp36",
|
||||||
@@ -26,6 +27,7 @@ ALL_IDS = {
|
|||||||
"pp38",
|
"pp38",
|
||||||
"pp39",
|
"pp39",
|
||||||
"pp310",
|
"pp310",
|
||||||
|
"pp311",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[0][1]
|
kwargs = build_in_container.call_args_list[0][1]
|
||||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-manylinux_x86_64" for x in ALL_IDS}
|
assert identifiers == {f"{x}-manylinux_x86_64" for x in ALL_IDS}
|
||||||
@@ -81,7 +83,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[1][1]
|
kwargs = build_in_container.call_args_list[1][1]
|
||||||
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
||||||
@@ -89,7 +91,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[2][1]
|
kwargs = build_in_container.call_args_list[2][1]
|
||||||
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
@@ -99,7 +101,7 @@ def test_build_default_launches(monkeypatch):
|
|||||||
kwargs = build_in_container.call_args_list[3][1]
|
kwargs = build_in_container.call_args_list[3][1]
|
||||||
assert "quay.io/pypa/musllinux_1_2_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_2_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
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}
|
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
||||||
@@ -142,7 +144,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[0][1]
|
kwargs = build_in_container.call_args_list[0][1]
|
||||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {"cp36-manylinux_x86_64"}
|
assert identifiers == {"cp36-manylinux_x86_64"}
|
||||||
@@ -151,30 +153,30 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[1][1]
|
kwargs = build_in_container.call_args_list[1][1]
|
||||||
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
f"{x}-manylinux_x86_64"
|
f"{x}-manylinux_x86_64"
|
||||||
for x in ALL_IDS
|
for x in ALL_IDS
|
||||||
- {"cp36", "cp310", "cp311", "cp312", "cp313", "pp37", "pp38", "pp39", "pp310"}
|
- {"cp36", "cp310", "cp311", "cp312", "cp313", "pp37", "pp38", "pp39", "pp310", "pp311"}
|
||||||
}
|
}
|
||||||
assert kwargs["options"].build_options("cp37-manylinux_x86_64").before_all == ""
|
assert kwargs["options"].build_options("cp37-manylinux_x86_64").before_all == ""
|
||||||
|
|
||||||
kwargs = build_in_container.call_args_list[2][1]
|
kwargs = build_in_container.call_args_list[2][1]
|
||||||
assert "quay.io/pypa/manylinux_2_28_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 kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
f"{x}-manylinux_x86_64"
|
f"{x}-manylinux_x86_64"
|
||||||
for x in ["cp310", "cp311", "cp312", "cp313", "pp37", "pp38", "pp39", "pp310"]
|
for x in ["cp310", "cp311", "cp312", "cp313", "pp37", "pp38", "pp39", "pp310", "pp311"]
|
||||||
}
|
}
|
||||||
|
|
||||||
kwargs = build_in_container.call_args_list[3][1]
|
kwargs = build_in_container.call_args_list[3][1]
|
||||||
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS}
|
||||||
@@ -182,7 +184,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[4][1]
|
kwargs = build_in_container.call_args_list[4][1]
|
||||||
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
@@ -192,7 +194,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[5][1]
|
kwargs = build_in_container.call_args_list[5][1]
|
||||||
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert not kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
||||||
assert identifiers == {
|
assert identifiers == {
|
||||||
f"{x}-musllinux_x86_64" for x in ALL_IDS - {"cp36", "cp37", "cp38", "cp39"} if "pp" not in x
|
f"{x}-musllinux_x86_64" for x in ALL_IDS - {"cp36", "cp37", "cp38", "cp39"} if "pp" not in x
|
||||||
@@ -201,7 +203,7 @@ before-all = "true"
|
|||||||
kwargs = build_in_container.call_args_list[6][1]
|
kwargs = build_in_container.call_args_list[6][1]
|
||||||
assert "quay.io/pypa/musllinux_1_2_i686" in kwargs["container"]["image"]
|
assert "quay.io/pypa/musllinux_1_2_i686" in kwargs["container"]["image"]
|
||||||
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
|
||||||
assert kwargs["container"]["enforce_32_bit"]
|
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
|
||||||
|
|
||||||
identifiers = {x.identifier for x in kwargs["platform_configs"]}
|
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}
|
assert identifiers == {f"{x}-musllinux_i686" for x in ALL_IDS if "pp" not in x}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from cibuildwheel.options import (
|
|||||||
Options,
|
Options,
|
||||||
_get_pinned_container_images,
|
_get_pinned_container_images,
|
||||||
)
|
)
|
||||||
|
from cibuildwheel.util import EnableGroups
|
||||||
|
|
||||||
PYPROJECT_1 = """
|
PYPROJECT_1 = """
|
||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
@@ -178,7 +179,7 @@ def test_toml_environment_evil(tmp_path, env_var_value):
|
|||||||
(r'TEST_VAR="before\\$after"', "before$after"),
|
(r'TEST_VAR="before\\$after"', "before$after"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_toml_environment_quoting(tmp_path: Path, toml_assignment, result_value):
|
def test_toml_environment_quoting(tmp_path: Path, toml_assignment: str, result_value: str) -> None:
|
||||||
args = CommandLineArguments.defaults()
|
args = CommandLineArguments.defaults()
|
||||||
args.package_dir = tmp_path
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
@@ -255,8 +256,12 @@ def test_toml_environment_quoting(tmp_path: Path, toml_assignment, result_value)
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_container_engine_option(
|
def test_container_engine_option(
|
||||||
tmp_path: Path, toml_assignment, result_name, result_create_args, result_disable_host_mount
|
tmp_path: Path,
|
||||||
):
|
toml_assignment: str,
|
||||||
|
result_name: str,
|
||||||
|
result_create_args: tuple[str, ...],
|
||||||
|
result_disable_host_mount: bool,
|
||||||
|
) -> None:
|
||||||
args = CommandLineArguments.defaults()
|
args = CommandLineArguments.defaults()
|
||||||
args.package_dir = tmp_path
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
@@ -326,7 +331,9 @@ def test_environment_pass_references():
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_build_frontend_option(tmp_path: Path, toml_assignment, result_name, result_args):
|
def test_build_frontend_option(
|
||||||
|
tmp_path: Path, toml_assignment: str, result_name: str, result_args: list[str]
|
||||||
|
) -> None:
|
||||||
args = CommandLineArguments.defaults()
|
args = CommandLineArguments.defaults()
|
||||||
args.package_dir = tmp_path
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
@@ -350,7 +357,7 @@ def test_build_frontend_option(tmp_path: Path, toml_assignment, result_name, res
|
|||||||
assert parsed_build_frontend is None
|
assert parsed_build_frontend is None
|
||||||
|
|
||||||
|
|
||||||
def test_override_inherit_environment(tmp_path: Path):
|
def test_override_inherit_environment(tmp_path: Path) -> None:
|
||||||
args = CommandLineArguments.defaults()
|
args = CommandLineArguments.defaults()
|
||||||
args.package_dir = tmp_path
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
@@ -385,7 +392,7 @@ def test_override_inherit_environment(tmp_path: Path):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_override_inherit_environment_with_references(tmp_path: Path):
|
def test_override_inherit_environment_with_references(tmp_path: Path) -> None:
|
||||||
args = CommandLineArguments.defaults()
|
args = CommandLineArguments.defaults()
|
||||||
args.package_dir = tmp_path
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
@@ -434,7 +441,7 @@ def test_override_inherit_environment_with_references(tmp_path: Path):
|
|||||||
)
|
)
|
||||||
def test_free_threaded_support(
|
def test_free_threaded_support(
|
||||||
tmp_path: Path, toml_assignment: str, env: dict[str, str], expected_result: bool
|
tmp_path: Path, toml_assignment: str, env: dict[str, str], expected_result: bool
|
||||||
):
|
) -> None:
|
||||||
args = CommandLineArguments.defaults()
|
args = CommandLineArguments.defaults()
|
||||||
args.package_dir = tmp_path
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
@@ -448,4 +455,40 @@ def test_free_threaded_support(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
options = Options(platform="linux", command_line_arguments=args, env=env)
|
options = Options(platform="linux", command_line_arguments=args, env=env)
|
||||||
assert options.globals.build_selector.free_threaded_support is expected_result
|
if expected_result:
|
||||||
|
assert EnableGroups.CPythonFreeThreading in options.globals.build_selector.enable
|
||||||
|
else:
|
||||||
|
assert EnableGroups.CPythonFreeThreading not in options.globals.build_selector.enable
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("image", "deprecated"),
|
||||||
|
[
|
||||||
|
("manylinux1", True),
|
||||||
|
("manylinux2010", True),
|
||||||
|
("manylinux2014", False),
|
||||||
|
("manylinux_2_24", True),
|
||||||
|
("manylinux_2_28", False),
|
||||||
|
("manylinux_2_34", False),
|
||||||
|
("musllinux_1_1", True),
|
||||||
|
("musllinux_1_2", False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_deprecated_image(image: str, deprecated: bool, capsys: pytest.CaptureFixture[str]) -> None:
|
||||||
|
args = CommandLineArguments.defaults()
|
||||||
|
env = {
|
||||||
|
"CIBW_ARCHS": "x86_64",
|
||||||
|
"CIBW_MANYLINUX_X86_64_IMAGE": image if image.startswith("manylinux") else "",
|
||||||
|
"CIBW_MUSLLINUX_X86_64_IMAGE": image if image.startswith("musllinux") else "",
|
||||||
|
}
|
||||||
|
options = Options(platform="linux", command_line_arguments=args, env=env)
|
||||||
|
bo = options.build_options(None)
|
||||||
|
images = bo.manylinux_images if image.startswith("manylinux") else bo.musllinux_images
|
||||||
|
assert images is not None
|
||||||
|
resolved_image = images["x86_64"]
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
if deprecated:
|
||||||
|
assert f"Deprecated image {image!r}" in captured.err
|
||||||
|
assert f"{resolved_image!r}" in captured.err
|
||||||
|
else:
|
||||||
|
assert "Deprecated image" not in captured.err
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user