Files
cibuildwheel/unit_test/option_prepare_test.py
T

224 lines
8.4 KiB
Python

import platform as platform_module
import subprocess
import sys
import typing
from contextlib import contextmanager
from pathlib import Path, PurePosixPath
from unittest import mock
import pytest
from cibuildwheel import platforms
from cibuildwheel.__main__ import main
from cibuildwheel.oci_container import OCIPlatform
from cibuildwheel.util import file
DEFAULT_IDS = {"cp39", "cp310", "cp311", "cp312", "cp313", "cp314", "cp314t", "cp315", "cp315t"}
ALL_IDS = DEFAULT_IDS | {"pp39", "pp310", "pp311", "gp312_250"}
@pytest.fixture
def mock_build_container(monkeypatch: pytest.MonkeyPatch) -> None:
def fail_on_call(*args: object, **kwargs: object) -> None:
msg = "This should never be called"
raise RuntimeError(msg)
def ignore_call(*args: object, **kwargs: object) -> None:
pass
@contextmanager
def nullcontext(enter_result: object = None) -> typing.Generator[object, None, None]:
yield enter_result
def ignore_context_call(*args: object, **kwargs: object) -> typing.ContextManager[object]:
return nullcontext(kwargs)
monkeypatch.setenv("CIBW_PLATFORM", "linux")
monkeypatch.setattr(platform_module, "machine", lambda: "x86_64")
monkeypatch.setattr(subprocess, "Popen", fail_on_call)
monkeypatch.setattr(subprocess, "run", ignore_call)
monkeypatch.setattr(file, "download", fail_on_call)
monkeypatch.setattr("cibuildwheel.platforms.linux.OCIContainer", ignore_context_call)
monkeypatch.setattr(
"cibuildwheel.platforms.linux.build_in_container",
mock.Mock(spec=platforms.linux.build_in_container),
)
monkeypatch.setattr("cibuildwheel.logger.Logger.print_summary", ignore_context_call)
@pytest.mark.usefixtures("mock_build_container", "fake_package_dir")
def test_build_default_launches(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(sys, "argv", [*sys.argv, "--platform=linux"])
monkeypatch.setenv("CIBW_ARCHS", "auto64 auto32")
monkeypatch.delenv("CIBW_ENABLE", raising=False)
main()
build_in_container = typing.cast("mock.Mock", platforms.linux.build_in_container)
assert build_in_container.call_count == 4
# In Python 3.8+, this can be simplified to [0].kwargs
kwargs = build_in_container.call_args_list[0][1]
assert "quay.io/pypa/manylinux_2_28_x86_64" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {f"{x}-manylinux_x86_64" for x in DEFAULT_IDS}
kwargs = build_in_container.call_args_list[1][1]
assert "quay.io/pypa/manylinux_2_28_i686" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {f"{x}-manylinux_i686" for x in DEFAULT_IDS}
kwargs = build_in_container.call_args_list[2][1]
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {f"{x}-musllinux_x86_64" for x in DEFAULT_IDS}
kwargs = build_in_container.call_args_list[3][1]
assert "quay.io/pypa/musllinux_1_2_i686" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {f"{x}-musllinux_i686" for x in DEFAULT_IDS}
@pytest.mark.usefixtures("mock_build_container")
def test_build_with_override_launches(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
pkg_dir = tmp_path / "cibw_package"
pkg_dir.mkdir()
cibw_toml = pkg_dir / "pyproject.toml"
cibw_toml.write_text(
"""
[tool.cibuildwheel]
manylinux-x86_64-image = "manylinux_2_28"
musllinux-x86_64-image = "musllinux_1_2"
enable = ["pypy", "pypy-eol", "graalpy"]
archs = ["auto64", "auto32"]
# Before Python 3.10, use manylinux2014
[[tool.cibuildwheel.overrides]]
select = "cp3?-* cp310-*"
manylinux-x86_64-image = "manylinux2014"
manylinux-i686-image = "manylinux2014"
[[tool.cibuildwheel.overrides]]
select = "cp39-manylinux_x86_64"
before-all = "true"
"""
)
monkeypatch.chdir(pkg_dir)
monkeypatch.setattr(sys, "argv", ["cibuildwheel", "--platform=linux"])
monkeypatch.delenv("CIBW_ENABLE", raising=False)
main()
build_in_container = typing.cast("mock.Mock", platforms.linux.build_in_container)
assert build_in_container.call_count == 7
kwargs = build_in_container.call_args_list[0][1]
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {"cp39-manylinux_x86_64"}
assert kwargs["options"].build_options("cp39-manylinux_x86_64").before_all == "true"
kwargs = build_in_container.call_args_list[1][1]
assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {
f"{x}-manylinux_x86_64"
for x in ALL_IDS
- {
"cp39",
"cp311",
"cp312",
"cp313",
"cp314",
"cp314t",
"cp315",
"cp315t",
"pp39",
"pp310",
"pp311",
"gp312_250",
}
}
assert kwargs["options"].build_options("cp310-manylinux_x86_64").before_all == ""
kwargs = build_in_container.call_args_list[2][1]
assert "quay.io/pypa/manylinux_2_28_x86_64" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {
f"{x}-manylinux_x86_64"
for x in [
"cp311",
"cp312",
"cp313",
"cp314",
"cp314t",
"cp315",
"cp315t",
"pp39",
"pp310",
"pp311",
"gp312_250",
]
}
kwargs = build_in_container.call_args_list[3][1]
assert "quay.io/pypa/manylinux2014_i686" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {"cp39-manylinux_i686", "cp310-manylinux_i686"}
kwargs = build_in_container.call_args_list[4][1]
assert "quay.io/pypa/manylinux_2_28_i686" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {
f"{x}-manylinux_i686" for x in ALL_IDS - {"cp39", "cp310"} if "gp" not in x
}
kwargs = build_in_container.call_args_list[5][1]
assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64
identifiers = {x.identifier for x in kwargs["platform_configs"]}
assert identifiers == {
f"{x}-musllinux_x86_64" for x in ALL_IDS if "pp" not in x and "gp" not in x
}
kwargs = build_in_container.call_args_list[6][1]
assert "quay.io/pypa/musllinux_1_2_i686" in kwargs["container"]["image"]
assert kwargs["container"]["cwd"] == PurePosixPath("/project")
assert kwargs["container"]["oci_platform"] == OCIPlatform.i386
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 and "gp" not in x
}