Test enable groups as specified by PR labels (#2357)

* Allow CIBW_ENABLE to control the wheels built in testing

* Set CIBW_ENABLE using PR labels

* Add docs

* Build everything on the main branch

* Add CIBW_ENABLE=all option

This was mostly for use in the `main` building case, because otherwise it's maybe a bit too easy to forget to update this file when adding an enable group

* Remove dead code

* Make unit tests robust to the value of CIBW_ENABLE

* Fix tests that explicitly choose pypy

* Fix test expectation

* Don't expect impossible wheels in expected_wheels

* Simplify logic in expected_wheels

* CircleCI- run with CIBW_ENABLE=all only on the main branch

* Azure pipelines - run with CIBW_ENABLE=all on main branch

* Update gitlab to run CIBW_ENABLE=all on main

* Set CIBW_ENABLE=all on travis - it only runs on main anyway

* Fix job name error on CircleCI

* Fix tests for graalpy

* Update the test configuration to use the label

* Remove duplication of default value. Make it affect sample build too

* Move the action to after deps are installed

* GraalPy workaround for this assumption

* Make unit test resilient to changing CIBW_ENABLE
This commit is contained in:
Joe Rickerby
2025-05-08 12:27:05 +01:00
committed by GitHub
parent edbd234b82
commit 04c9427a20
15 changed files with 204 additions and 82 deletions
+34 -29
View File
@@ -1,7 +1,30 @@
version: 2 version: 2.1
commands:
cibw_prepare_environment:
description: "Prepare the environment for testing."
steps:
- run:
name: Prepare the environment.
command: bash .circleci/prepare.sh
cibw_run_tests:
description: "Runs tests, with CIBW_ENABLE=all on the main branch"
steps:
- run:
name: Test
command: |
if [ "${CIRCLE_BRANCH}" == "main" ]; then
echo "INFO: Exporting CIBW_ENABLE=all for main branch test run."
export CIBW_ENABLE=all
else
echo "INFO: CIBW_ENABLE not set for this branch test run."
fi
venv/bin/python ./bin/run_tests.py
no_output_timeout: 30m
jobs: jobs:
osx-python3.12: osx-python312:
macos: macos:
xcode: 15.4.0 xcode: 15.4.0
resource_class: macos.m1.medium.gen1 resource_class: macos.m1.medium.gen1
@@ -9,16 +32,10 @@ jobs:
PYTHON: python3 PYTHON: python3
steps: steps:
- checkout - checkout
- cibw_prepare_environment
- cibw_run_tests
- run: linux-python312:
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
no_output_timeout: 30m
linux-python3.12:
docker: docker:
- image: cimg/python:3.12 - image: cimg/python:3.12
environment: environment:
@@ -29,14 +46,8 @@ jobs:
steps: steps:
- checkout - checkout
- setup_remote_docker - setup_remote_docker
- cibw_prepare_environment
- run: - cibw_run_tests
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
no_output_timeout: 30m
linux-aarch64: linux-aarch64:
machine: machine:
@@ -49,19 +60,13 @@ jobs:
PYTEST_ADDOPTS: -k "unit_test or main_tests or test_0_basic or test_docker_images" PYTEST_ADDOPTS: -k "unit_test or main_tests or test_0_basic or test_docker_images"
steps: steps:
- checkout - checkout
- cibw_prepare_environment
- run: - cibw_run_tests
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
no_output_timeout: 30m
workflows: workflows:
version: 2 version: 2
all-tests: all-tests:
jobs: jobs:
- osx-python3.12 - osx-python312
- linux-python3.12 - linux-python312
- linux-aarch64 - linux-aarch64
+25 -1
View File
@@ -6,6 +6,11 @@ on:
- main - main
- 2.x - 2.x
pull_request: pull_request:
types:
- opened
- synchronize
- reopened
- labeled
paths-ignore: paths-ignore:
- 'docs/**' - 'docs/**'
- .pre-commit-config.yaml - .pre-commit-config.yaml
@@ -68,6 +73,26 @@ jobs:
run: | run: |
uv sync --no-dev --group test uv sync --no-dev --group test
- uses: joerick/pr-labels-action@v1.0.9
- name: Set CIBW_ENABLE
shell: bash
run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then
CIBW_ENABLE=all
else
# get the default CIBW_ENABLE value from the test module
CIBW_ENABLE=$(uv run --no-sync python -c 'import sys, test.conftest as c; sys.stdout.write(c.DEFAULT_CIBW_ENABLE)')
# if this is a PR, check for labels
if [[ -n "$GITHUB_PR_LABEL_CI_PYPY" ]]; then
CIBW_ENABLE+=" pypy"
fi
if [[ -n "$GITHUB_PR_LABEL_CI_GRAALPY" ]]; then
CIBW_ENABLE+=" graalpy"
fi
fi
echo "CIBW_ENABLE=${CIBW_ENABLE}" >> $GITHUB_ENV
- name: Generate a sample project - name: Generate a sample project
run: | run: |
uv run --no-sync -m test.test_projects test.test_0_basic.basic_project sample_proj uv run --no-sync -m test.test_projects test.test_0_basic.basic_project sample_proj
@@ -80,7 +105,6 @@ jobs:
env: env:
CIBW_ARCHS_MACOS: x86_64 universal2 arm64 CIBW_ARCHS_MACOS: x86_64 universal2 arm64
CIBW_BUILD_FRONTEND: 'build[uv]' CIBW_BUILD_FRONTEND: 'build[uv]'
CIBW_ENABLE: "cpython-prerelease cpython-freethreading pypy graalpy"
- name: Run a sample build (GitHub Action, only) - name: Run a sample build (GitHub Action, only)
uses: ./ uses: ./
+12
View File
@@ -13,6 +13,10 @@ linux:
# skip all but the basic tests # skip all but the basic tests
# (comment the below line in a PR to debug a Gitlab-specific issue) # (comment the below line in a PR to debug a Gitlab-specific issue)
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
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
variables:
CIBW_ENABLE: "all"
script: script:
- curl -sSL https://get.docker.com/ | sh - curl -sSL https://get.docker.com/ | sh
- docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all - docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
@@ -26,6 +30,10 @@ windows:
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
before_script: before_script:
- choco install python -y --version 3.12.4 - choco install python -y --version 3.12.4
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
variables:
CIBW_ENABLE: "all"
script: script:
- py -m pip install dependency-groups - py -m pip install dependency-groups
- py -m pip install -e. pytest-custom-exit-code $(py -m dependency_groups test) - py -m pip install -e. pytest-custom-exit-code $(py -m dependency_groups test)
@@ -37,6 +45,10 @@ macos:
image: macos-14-xcode-15 image: macos-14-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
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
variables:
CIBW_ENABLE: "all"
script: script:
- python3 -m pip install dependency-groups - python3 -m pip install dependency-groups
- python3 -m dependency_groups test | xargs python3 -m pip install -e. pytest-custom-exit-code - python3 -m dependency_groups test | xargs python3 -m pip install -e. pytest-custom-exit-code
+11 -3
View File
@@ -14,13 +14,17 @@ jobs:
- name: Linux | x86_64 + i686 | Python 3.12 - name: Linux | x86_64 + i686 | Python 3.12
python: 3.12 python: 3.12
services: docker services: docker
env: PYTHON=python env:
- PYTHON=python
- CIBW_ENABLE=all
- name: Linux | arm64 | Python 3.12 - name: Linux | arm64 | Python 3.12
python: 3.12 python: 3.12
services: docker services: docker
arch: arm64 arch: arm64
env: PYTHON=python env:
- PYTHON=python
- CIBW_ENABLE=all
- name: Linux | ppc64le | Python 3.12 - name: Linux | ppc64le | Python 3.12
python: 3.12 python: 3.12
@@ -32,6 +36,7 @@ jobs:
# skip test_manylinuxXXXX_only, it uses too much disk space # skip test_manylinuxXXXX_only, it uses too much disk space
# c.f. https://travis-ci.community/t/running-out-of-disk-space-quota-when-using-docker-on-ppc64le/11634 # c.f. https://travis-ci.community/t/running-out-of-disk-space-quota-when-using-docker-on-ppc64le/11634
- PYTEST_ADDOPTS='-k "not test_manylinuxXXXX_only"' - PYTEST_ADDOPTS='-k "not test_manylinuxXXXX_only"'
- CIBW_ENABLE=all
- name: Windows | x86_64 | Python 3.12 - name: Windows | x86_64 | Python 3.12
os: windows os: windows
@@ -40,13 +45,16 @@ jobs:
- choco upgrade python3 -y --version 3.12.8 --limit-output --params "/InstallDir:C:\\Python312" - choco upgrade python3 -y --version 3.12.8 --limit-output --params "/InstallDir:C:\\Python312"
env: env:
- PYTHON=C:\\Python312\\python - PYTHON=C:\\Python312\\python
- CIBW_ENABLE=all
- name: Linux | s390x | Python 3.12 - name: Linux | s390x | Python 3.12
python: 3.12 python: 3.12
services: docker services: docker
arch: s390x arch: s390x
allow_failure: True allow_failure: True
env: PYTHON=python env:
- PYTHON=python
- CIBW_ENABLE=all
install: install:
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all; fi - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all; fi
+18
View File
@@ -16,6 +16,12 @@ jobs:
docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all docker run --rm --privileged docker.io/tonistiigi/binfmt:latest --install all
python -m pip install dependency-groups python -m pip install dependency-groups
python -m dependency_groups test | xargs python -m pip install -e. python -m dependency_groups test | xargs python -m pip install -e.
if [ "$(Build.SourceBranch)" = "refs/heads/main" ]; then
echo "INFO: Exporting CIBW_ENABLE=all for main branch test run."
export CIBW_ENABLE=all
else
echo "INFO: CIBW_ENABLE not set for this branch ($(Build.SourceBranch))."
fi
python ./bin/run_tests.py python ./bin/run_tests.py
- job: macos_311 - job: macos_311
@@ -28,6 +34,12 @@ jobs:
- bash: | - bash: |
python -m pip install dependency-groups python -m pip install dependency-groups
python -m dependency_groups test | xargs python -m pip install -e. python -m dependency_groups test | xargs python -m pip install -e.
if [ "$(Build.SourceBranch)" = "refs/heads/main" ]; then
echo "INFO: Exporting CIBW_ENABLE=all for main branch test run."
export CIBW_ENABLE=all
else
echo "INFO: CIBW_ENABLE not set for this branch ($(Build.SourceBranch))."
fi
python ./bin/run_tests.py python ./bin/run_tests.py
- job: windows_311 - job: windows_311
@@ -40,4 +52,10 @@ jobs:
- bash: | - bash: |
python -m pip install dependency-groups python -m pip install dependency-groups
python -m dependency_groups test | xargs python -m pip install -e. python -m dependency_groups test | xargs python -m pip install -e.
if [ "$(Build.SourceBranch)" = "refs/heads/main" ]; then
echo "INFO: Exporting CIBW_ENABLE=all for main branch test run."
export CIBW_ENABLE=all
else
echo "INFO: CIBW_ENABLE not set for this branch ($(Build.SourceBranch))."
fi
python ./bin/run_tests.py python ./bin/run_tests.py
+4 -2
View File
@@ -634,8 +634,10 @@ class Options:
"enable", env_plat=False, option_format=ListFormat(sep=" "), env_rule=InheritRule.APPEND "enable", env_plat=False, option_format=ListFormat(sep=" "), env_rule=InheritRule.APPEND
) )
try: try:
enable = {EnableGroup(group) for group in enable_groups.split()} enable = {
enable.update(EnableGroup(command_line_group) for command_line_group in args.enable) *EnableGroup.parse_option_value(enable_groups),
*EnableGroup.parse_option_value(" ".join(args.enable)),
}
except ValueError as e: except ValueError as e:
msg = f"Failed to parse enable group. {e}. Valid group names are: {', '.join(g.value for g in EnableGroup)}" msg = f"Failed to parse enable group. {e}. Valid group names are: {', '.join(g.value for g in EnableGroup)}"
raise errors.ConfigurationError(msg) from e raise errors.ConfigurationError(msg) from e
+17
View File
@@ -39,6 +39,23 @@ class EnableGroup(StrEnum):
def all_groups(cls) -> frozenset["EnableGroup"]: def all_groups(cls) -> frozenset["EnableGroup"]:
return frozenset(cls) return frozenset(cls)
@classmethod
def parse_option_value(cls, value: str) -> frozenset["EnableGroup"]:
"""
Parses a string of space-separated values into a set of EnableGroup
members. The string may contain group names or "all".
"""
result = set()
for group in value.strip().split():
if group == "all":
return cls.all_groups()
try:
result.add(cls(group))
except ValueError:
msg = f"Unknown enable group: {group}"
raise ValueError(msg) from None
return frozenset(result)
@dataclass(frozen=True, kw_only=True) @dataclass(frozen=True, kw_only=True)
class BuildSelector: class BuildSelector:
+2
View File
@@ -82,6 +82,8 @@ 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.
- The 'enable groups' run by default are just 'cpython-prerelease' and 'cpython-freethreading'. You can add other groups like pypy or graalpy by setting the [CIBW_ENABLE](options.md#enable) environment variable. On GitHub PRs, you can add a label to the PR to enable these groups.
#### Running pytest directly #### Running pytest directly
More advanced users might prefer to invoke pytest directly. Set up a [dev environment](#setting-up-a-dev-environment), then, More advanced users might prefer to invoke pytest directly. Set up a [dev environment](#setting-up-a-dev-environment), then,
+1 -1
View File
@@ -324,7 +324,7 @@ values are:
are disabled by default as they can't be uploaded to PyPI and a PEP will most likely are disabled by default as they can't be uploaded to PyPI and a PEP will most likely
be required before this can happen. be required before this can happen.
- `graalpy`: Enable GraalPy. - `graalpy`: Enable GraalPy.
- `all`: Enable all of the above.
!!! caution !!! caution
`cpython-prerelease` is provided for testing purposes only. It is not `cpython-prerelease` is provided for testing purposes only. It is not
+6
View File
@@ -1,4 +1,5 @@
import json import json
import os
import subprocess import subprocess
from collections.abc import Generator from collections.abc import Generator
@@ -12,6 +13,9 @@ from cibuildwheel.venv import find_uv
from .utils import EMULATED_ARCHS, platform from .utils import EMULATED_ARCHS, platform
# default to just cpython
DEFAULT_CIBW_ENABLE = "cpython-freethreading cpython-prerelease cpython-experimental-riscv64"
def pytest_addoption(parser: pytest.Parser) -> None: def pytest_addoption(parser: pytest.Parser) -> None:
parser.addoption( parser.addoption(
@@ -29,6 +33,8 @@ def pytest_addoption(parser: pytest.Parser) -> None:
help="macOS cp38 uses the universal2 installer", help="macOS cp38 uses the universal2 installer",
) )
os.environ.setdefault("CIBW_ENABLE", DEFAULT_CIBW_ENABLE)
def docker_warmup(request: pytest.FixtureRequest) -> None: def docker_warmup(request: pytest.FixtureRequest) -> None:
machine = request.config.getoption("--run-emulation", default=None) machine = request.config.getoption("--run-emulation", default=None)
+16 -9
View File
@@ -1,8 +1,10 @@
import os
import textwrap import textwrap
import pytest import pytest
from cibuildwheel.logger import Logger from cibuildwheel.logger import Logger
from cibuildwheel.selector import EnableGroup
from . import test_projects, utils from . import test_projects, utils
@@ -38,11 +40,13 @@ def test(tmp_path, build_frontend_env, capfd):
expected_wheels = utils.expected_wheels("spam", "0.1.0") expected_wheels = utils.expected_wheels("spam", "0.1.0")
assert set(actual_wheels) == set(expected_wheels) assert set(actual_wheels) == set(expected_wheels)
# Verify pip warning not shown enable_groups = EnableGroup.parse_option_value(os.environ.get("CIBW_ENABLE", ""))
captured = capfd.readouterr() if EnableGroup.GraalPy not in enable_groups:
for stream in (captured.err, captured.out): # Verify pip warning not shown
assert "WARNING: Running pip as the 'root' user can result" not in stream captured = capfd.readouterr()
assert "A new release of pip available" not in stream for stream in (captured.err, captured.out):
assert "WARNING: Running pip as the 'root' user can result" not in stream
assert "A new release of pip available" not in stream
@pytest.mark.skip(reason="to keep test output clean") @pytest.mark.skip(reason="to keep test output clean")
@@ -61,16 +65,19 @@ def test_sample_build(tmp_path, capfd):
logger.step_end() logger.step_end()
def test_build_identifiers(tmp_path): @pytest.mark.parametrize(
"enable_setting", ["", "cpython-prerelease", "pypy", "cpython-freethreading"]
)
def test_build_identifiers(tmp_path, enable_setting, monkeypatch):
project_dir = tmp_path / "project" project_dir = tmp_path / "project"
basic_project.generate(project_dir) basic_project.generate(project_dir)
monkeypatch.setenv("CIBW_ENABLE", enable_setting)
# check that the number of expected wheels matches the number of build # check that the number of expected wheels matches the number of build
# identifiers # identifiers
expected_wheels = utils.expected_wheels("spam", "0.1.0") expected_wheels = utils.expected_wheels("spam", "0.1.0")
build_identifiers = utils.cibuildwheel_get_build_identifiers( build_identifiers = utils.cibuildwheel_get_build_identifiers(project_dir)
project_dir, prerelease_pythons=True
)
assert len(expected_wheels) == len(build_identifiers), ( assert len(expected_wheels) == len(build_identifiers), (
f"{expected_wheels} vs {build_identifiers}" f"{expected_wheels} vs {build_identifiers}"
) )
+17 -18
View File
@@ -35,36 +35,34 @@ def test_abi3(tmp_path):
project_dir = tmp_path / "project" project_dir = tmp_path / "project"
limited_api_project.generate(project_dir) limited_api_project.generate(project_dir)
single_python_tag = "cp{}{}".format(*utils.SINGLE_PYTHON_VERSION)
# build the wheels # build the wheels
actual_wheels = utils.cibuildwheel_run( actual_wheels = utils.cibuildwheel_run(
project_dir, project_dir,
add_env={ add_env={
# free_threaded, GraalPy, and PyPy do not have a Py_LIMITED_API equivalent, just build one of those # free_threaded, GraalPy, and PyPy do not have a Py_LIMITED_API equivalent, just build one of those
# also limit the number of builds for test performance reasons # also limit the number of builds for test performance reasons
"CIBW_BUILD": f"cp39-* cp310-* pp310-* gp242-* {single_python_tag}-* cp313t-*" "CIBW_BUILD": "cp39-* cp310-* pp310-* gp242-* cp312-* cp313t-*",
"CIBW_ENABLE": "all",
}, },
) )
# check that the expected wheels are produced # check that the expected wheels are produced
expected_wheels = utils.expected_wheels("spam", "0.1.0")
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, cp312
expected_wheels = [ expected_wheels = utils.expected_wheels("spam", "0.1.0", python_abi_tags=["cp310-abi3"])
w.replace(f"{single_python_tag}-{single_python_tag}", "cp310-abi3")
for w in expected_wheels
]
else: else:
expected_wheels = [ expected_wheels = utils.expected_wheels(
w.replace("cp310-cp310", "cp310-abi3") "spam",
for w in expected_wheels "0.1.0",
if "-cp39" in w python_abi_tags=[
or "-cp310" in w "cp39-cp39",
or "-pp310" in w "cp310-abi3", # <-- ABI3, works with 3.10 and 3.12
or "-graalpy242" in w "cp313-cp313t",
or "-cp313t" in w "pp310-pypy310_pp73",
] "graalpy311-graalpy242_311_native",
],
)
assert set(actual_wheels) == set(expected_wheels) assert set(actual_wheels) == set(expected_wheels)
@@ -187,6 +185,7 @@ def test_abi_none(tmp_path, capfd):
"CIBW_TEST_COMMAND": f"{utils.invoke_pytest()} ./test", "CIBW_TEST_COMMAND": f"{utils.invoke_pytest()} ./test",
# limit the number of builds for test performance reasons # limit the number of builds for test performance reasons
"CIBW_BUILD": "cp38-* cp{}{}-* cp313t-* pp310-*".format(*utils.SINGLE_PYTHON_VERSION), "CIBW_BUILD": "cp38-* cp{}{}-* cp313t-* pp310-*".format(*utils.SINGLE_PYTHON_VERSION),
"CIBW_ENABLE": "all",
}, },
) )
+28 -19
View File
@@ -23,6 +23,9 @@ from cibuildwheel.util.file import CIBW_CACHE_PATH
EMULATED_ARCHS: Final[list[str]] = sorted( EMULATED_ARCHS: Final[list[str]] = sorted(
arch.value for arch in (Architecture.all_archs("linux") - Architecture.auto_archs("linux")) arch.value for arch in (Architecture.all_archs("linux") - Architecture.auto_archs("linux"))
) )
PYPY_ARCHS = ["x86_64", "i686", "AMD64", "aarch64", "arm64"]
GRAALPY_ARCHS = ["x86_64", "AMD64", "aarch64", "arm64"]
SINGLE_PYTHON_VERSION: Final[tuple[int, int]] = (3, 12) SINGLE_PYTHON_VERSION: Final[tuple[int, int]] = (3, 12)
_AARCH64_CAN_RUN_ARMV7: Final[bool] = Architecture.aarch64.value not in EMULATED_ARCHS and { _AARCH64_CAN_RUN_ARMV7: Final[bool] = Architecture.aarch64.value not in EMULATED_ARCHS and {
@@ -46,7 +49,8 @@ else:
def cibuildwheel_get_build_identifiers( def cibuildwheel_get_build_identifiers(
project_path: Path, env: dict[str, str] | None = None, *, prerelease_pythons: bool = False project_path: Path,
env: dict[str, str] | None = None,
) -> list[str]: ) -> 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
@@ -55,9 +59,6 @@ def cibuildwheel_get_build_identifiers(
cmd = [sys.executable, "-m", "cibuildwheel", "--print-build-identifiers", str(project_path)] cmd = [sys.executable, "-m", "cibuildwheel", "--print-build-identifiers", str(project_path)]
if env is None: if env is None:
env = os.environ.copy() env = os.environ.copy()
env["CIBW_ENABLE"] = "cpython-freethreading pypy graalpy"
if prerelease_pythons:
env["CIBW_ENABLE"] += " cpython-prerelease"
cmd_output = subprocess.run( cmd_output = subprocess.run(
cmd, cmd,
@@ -121,8 +122,6 @@ def cibuildwheel_run(
_update_pip_cache_dir(env) _update_pip_cache_dir(env)
env["CIBW_ENABLE"] = " ".join(EnableGroup.all_groups())
if single_python: if single_python:
env["CIBW_BUILD"] = "cp{}{}-*".format(*SINGLE_PYTHON_VERSION) env["CIBW_BUILD"] = "cp{}{}-*".format(*SINGLE_PYTHON_VERSION)
@@ -222,6 +221,8 @@ def _expected_wheels(
# {python tag} and {abi tag} are closely related to the python interpreter used to build the wheel # {python tag} and {abi tag} are closely related to the python interpreter used to build the wheel
# so we'll merge them below as python_abi_tag # so we'll merge them below as python_abi_tag
enable_groups = EnableGroup.parse_option_value(os.environ.get("CIBW_ENABLE", ""))
if manylinux_versions is None: if manylinux_versions is None:
manylinux_versions = { manylinux_versions = {
"armv7l": ["manylinux_2_17", "manylinux2014", "manylinux_2_31"], "armv7l": ["manylinux_2_17", "manylinux2014", "manylinux_2_31"],
@@ -243,25 +244,36 @@ def _expected_wheels(
"cp311-cp311", "cp311-cp311",
"cp312-cp312", "cp312-cp312",
"cp313-cp313", "cp313-cp313",
"cp313-cp313t",
] ]
if machine_arch == "ARM64": if EnableGroup.CPythonFreeThreading in enable_groups:
# no CPython 3.8 on Windows ARM64 python_abi_tags += [
python_abi_tags.pop(0) "cp313-cp313t",
]
if machine_arch in ["x86_64", "i686", "AMD64", "aarch64", "arm64"]: if EnableGroup.PyPy in enable_groups:
python_abi_tags += [ python_abi_tags += [
"pp38-pypy38_pp73", "pp38-pypy38_pp73",
"pp39-pypy39_pp73", "pp39-pypy39_pp73",
"pp310-pypy310_pp73", "pp310-pypy310_pp73",
"pp311-pypy311_pp73", "pp311-pypy311_pp73",
] ]
if machine_arch in ["x86_64", "AMD64", "aarch64", "arm64"]:
if EnableGroup.GraalPy in enable_groups:
python_abi_tags += [ python_abi_tags += [
"graalpy311-graalpy242_311_native", "graalpy311-graalpy242_311_native",
] ]
if machine_arch == "ARM64" and platform == "windows":
# no CPython 3.8 on Windows ARM64
python_abi_tags = [t for t in python_abi_tags if not t.startswith("cp38")]
if machine_arch not in PYPY_ARCHS:
python_abi_tags = [tag for tag in python_abi_tags if not tag.startswith("pp")]
if machine_arch not in GRAALPY_ARCHS:
python_abi_tags = [tag for tag in python_abi_tags if not tag.startswith("graalpy")]
if single_python: if single_python:
python_tag = "cp{}{}-".format(*SINGLE_PYTHON_VERSION) python_tag = "cp{}{}-".format(*SINGLE_PYTHON_VERSION)
python_abi_tags = [ python_abi_tags = [
@@ -272,13 +284,6 @@ def _expected_wheels(
) )
] ]
if platform == "pyodide":
assert len(python_abi_tags) == 1
python_abi_tag = python_abi_tags[0]
platform_tag = "pyodide_2024_0_wasm32"
yield f"{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl"
return
for python_abi_tag in python_abi_tags: for python_abi_tag in python_abi_tags:
platform_tags = [] platform_tags = []
@@ -327,6 +332,10 @@ def _expected_wheels(
if include_universal2: if include_universal2:
platform_tags.append(f"macosx_{min_macosx.replace('.', '_')}_universal2") platform_tags.append(f"macosx_{min_macosx.replace('.', '_')}_universal2")
elif platform == "pyodide":
platform_tags = ["pyodide_2024_0_wasm32"]
else: else:
msg = f"Unsupported platform {platform!r}" msg = f"Unsupported platform {platform!r}"
raise Exception(msg) raise Exception(msg)
+12
View File
@@ -329,6 +329,7 @@ def test_config_settings(platform_specific, platform, intercepted_build_args, mo
@pytest.mark.usefixtures("platform", "intercepted_build_args", "allow_empty") @pytest.mark.usefixtures("platform", "intercepted_build_args", "allow_empty")
def test_build_selector_deprecated_error(monkeypatch, selector, pattern, capsys): def test_build_selector_deprecated_error(monkeypatch, selector, pattern, capsys):
monkeypatch.setenv(selector, pattern) monkeypatch.setenv(selector, pattern)
monkeypatch.delenv("CIBW_ENABLE", raising=False)
if selector == "CIBW_BUILD": if selector == "CIBW_BUILD":
with pytest.raises(SystemExit) as ex: with pytest.raises(SystemExit) as ex:
@@ -422,6 +423,8 @@ def test_debug_traceback(monkeypatch, method, capfd):
@pytest.mark.parametrize("method", ["unset", "command_line", "env_var"]) @pytest.mark.parametrize("method", ["unset", "command_line", "env_var"])
def test_enable(method, intercepted_build_args, monkeypatch): def test_enable(method, intercepted_build_args, monkeypatch):
monkeypatch.delenv("CIBW_ENABLE", raising=False)
if method == "command_line": if method == "command_line":
monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "pypy", "--enable", "graalpy"]) monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "pypy", "--enable", "graalpy"])
elif method == "env_var": elif method == "env_var":
@@ -437,6 +440,15 @@ def test_enable(method, intercepted_build_args, monkeypatch):
assert enable_groups == frozenset([EnableGroup.PyPy, EnableGroup.GraalPy]) assert enable_groups == frozenset([EnableGroup.PyPy, EnableGroup.GraalPy])
def test_enable_all(intercepted_build_args, monkeypatch):
monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "all"])
main()
enable_groups = intercepted_build_args.args[0].globals.build_selector.enable
assert enable_groups == EnableGroup.all_groups()
def test_enable_arg_inherits(intercepted_build_args, monkeypatch): def test_enable_arg_inherits(intercepted_build_args, monkeypatch):
monkeypatch.setenv("CIBW_ENABLE", "pypy graalpy") monkeypatch.setenv("CIBW_ENABLE", "pypy graalpy")
monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "cpython-prerelease"]) monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "cpython-prerelease"])
+1
View File
@@ -51,6 +51,7 @@ def mock_build_container(monkeypatch):
@pytest.mark.usefixtures("mock_build_container", "fake_package_dir") @pytest.mark.usefixtures("mock_build_container", "fake_package_dir")
def test_build_default_launches(monkeypatch): def test_build_default_launches(monkeypatch):
monkeypatch.setattr(sys, "argv", [*sys.argv, "--platform=linux"]) monkeypatch.setattr(sys, "argv", [*sys.argv, "--platform=linux"])
monkeypatch.delenv("CIBW_ENABLE", raising=False)
main() main()