* WIP - initial punt at audit command * Add `abi3audit` as a dependency * Add helper functions to check stable ABI wheels * Run `abi3audit` for macOS and Windows wheels * Copy out of container for repairing? * Add some notes that `cibuildwheel` runs `abi3audit` * Add basic unit tests * Add a basic C extension with `Py_LIMITED_API` * Add a test project that violates Stable ABI * Fix linux test * Skip abi3 wheel tests for Pyodide * Patch the correct subprocess module * wrap cleanup of abi3audit dir * Write the docs for the new options * Move to above testing in docs * Implement audit-requires and audit-command * Some cleanups after self-review * Add default value * fix type errors * the key is `audit-command`, not `audit` * Add a variety of tests for audit requires options * Add `test_audit_requires` similar to `test_test_requires` * Add some configurability-related audit tests * Fix parsing error with options docs leaving out commands * Better way to extract version (maybe helps Pyodide?) * Fix a case of unbound `use_uv` * Standardise: rename to `abi3_wheel` * Fix audit command run message * Simplify custom audit command a bit * Remove unnecessary skip for Pyodide * Pyodide should have no default audit command * More accurate skip messages for Pyodide skips * Wheels are audited after they are repaired * Regenerate constraints to include `abi3audit` * Fix typos * Some attempts for Windows fixes * Check `pyvenv.cfg` instead of directory existence * Add validation for lack of wheel placeholders * Try yet another Windows `uv` fix * Regenerate diagram and re-trigger Azure CI * Add missing `import sys` for abi3 C extension tests * Remove audit-command at the global level * Clarify `abi3audit` pinning a little bit * Regen constraints * Discard changes to cibuildwheel/resources/constraints-pyodide312.txt * Discard changes to cibuildwheel/resources/constraints-pyodide313.txt * try opt-in uv again * fix issue on windows on Python 3.13 related to nested venvs On win / python 3.13, virtualenv creates a venv where the 'home' points back to the venv that sys.executable was running in, rather than the root install. that seemingly leads to problems with package resolution, where pip.exe couldn't find the pip python package. this appears to fix it! * Update constraints * chore: revert python-discovery bump Assisted-by: OpenCode:glm-5.1 Signed-off-by: Henry Schreiner <henryfs@princeton.edu> * fix: restore workaround for graalpy Assisted-by: OpenCode:glm-5.1 Signed-off-by: Henry Schreiner <henryfs@princeton.edu> --------- Signed-off-by: Henry Schreiner <henryfs@princeton.edu> Co-authored-by: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Co-authored-by: Henry Schreiner <henryfs@princeton.edu>
703 lines
22 KiB
Python
703 lines
22 KiB
Python
import shlex
|
|
from pathlib import Path
|
|
from typing import Any, cast
|
|
|
|
import pytest
|
|
|
|
from cibuildwheel.options import (
|
|
EnvironmentFormat,
|
|
InheritRule,
|
|
ListFormat,
|
|
OptionsReader,
|
|
OptionsReaderError,
|
|
ShlexTableFormat,
|
|
_resolve_cascade,
|
|
)
|
|
from cibuildwheel.typing import PlatformName
|
|
|
|
PYPROJECT_1 = """
|
|
[tool.cibuildwheel]
|
|
build = "cp39*"
|
|
environment = {THING = "OTHER", FOO="BAR"}
|
|
xbuild-tools = ["first"]
|
|
|
|
test-command = "pyproject"
|
|
test-requires = "something"
|
|
test-extras = ["one", "two"]
|
|
test-groups = ["three", "four"]
|
|
test-sources = ["five", "six and seven"]
|
|
|
|
manylinux-x86_64-image = "manylinux_2_28"
|
|
|
|
[tool.cibuildwheel.macos]
|
|
test-requires = "else"
|
|
|
|
[tool.cibuildwheel.linux]
|
|
test-requires = ["other", "many"]
|
|
"""
|
|
|
|
|
|
@pytest.fixture(params=["linux", "macos", "windows"])
|
|
def platform(request: pytest.FixtureRequest) -> PlatformName:
|
|
return cast("PlatformName", request.param)
|
|
|
|
|
|
@pytest.mark.parametrize("fname", ["pyproject.toml", "cibuildwheel.toml"])
|
|
def test_simple_settings(tmp_path: Path, platform: PlatformName, fname: str) -> None:
|
|
config_file_path: Path = tmp_path / fname
|
|
config_file_path.write_text(PYPROJECT_1)
|
|
|
|
options_reader = OptionsReader(config_file_path, platform=platform, env={})
|
|
|
|
assert options_reader.get("build", option_format=ListFormat(" "), env_plat=False) == "cp39*"
|
|
|
|
assert options_reader.get("test-command") == "pyproject"
|
|
assert options_reader.get("archs", option_format=ListFormat(" ")) == "auto"
|
|
assert (
|
|
options_reader.get("test-sources", option_format=ListFormat(" ", quote=shlex.quote))
|
|
== "five 'six and seven'"
|
|
)
|
|
assert (
|
|
options_reader.get("test-requires", option_format=ListFormat(" "))
|
|
== {"windows": "something", "macos": "else", "linux": "other many"}[platform]
|
|
)
|
|
|
|
# Also testing options for support for both lists and tables
|
|
assert (
|
|
options_reader.get("environment", option_format=EnvironmentFormat())
|
|
== 'THING="OTHER" FOO="BAR"'
|
|
)
|
|
assert options_reader.get("test-extras", option_format=ListFormat(",")) == "one,two"
|
|
assert options_reader.get("test-groups", option_format=ListFormat(" ")) == "three four"
|
|
|
|
assert options_reader.get("manylinux-x86_64-image") == "manylinux_2_28"
|
|
assert options_reader.get("manylinux-i686-image") == "manylinux_2_28"
|
|
|
|
with pytest.raises(OptionsReaderError):
|
|
# fails because the option is a table and the option_format only works with lists
|
|
options_reader.get("environment", option_format=ListFormat(" "))
|
|
|
|
with pytest.raises(OptionsReaderError):
|
|
# fails because the option is a list and the option_format only works with tables
|
|
options_reader.get("test-extras", option_format=ShlexTableFormat())
|
|
|
|
|
|
def test_envvar_override(tmp_path: Path, platform: PlatformName) -> None:
|
|
config_file_path: Path = tmp_path / "pyproject.toml"
|
|
config_file_path.write_text(PYPROJECT_1)
|
|
|
|
options_reader = OptionsReader(
|
|
config_file_path,
|
|
platform=platform,
|
|
env={
|
|
"CIBW_BUILD": "cp38*",
|
|
"CIBW_MANYLINUX_X86_64_IMAGE": "manylinux_2_24",
|
|
"CIBW_XBUILD_TOOLS": "cmake rustc",
|
|
"CIBW_TEST_COMMAND": "mytest",
|
|
"CIBW_TEST_REQUIRES": "docs",
|
|
"CIBW_TEST_GROUPS": "mgroup two",
|
|
"CIBW_TEST_REQUIRES_LINUX": "scod",
|
|
"CIBW_TEST_GROUPS_LINUX": "lgroup",
|
|
"CIBW_TEST_SOURCES": 'first "second third"',
|
|
},
|
|
)
|
|
|
|
assert options_reader.get("archs", option_format=ListFormat(" ")) == "auto"
|
|
|
|
assert options_reader.get("build") == "cp38*"
|
|
assert options_reader.get("manylinux-x86_64-image") == "manylinux_2_24"
|
|
assert options_reader.get("manylinux-i686-image") == "manylinux_2_28"
|
|
|
|
assert (
|
|
options_reader.get("xbuild-tools", option_format=ListFormat(" ", quote=shlex.quote))
|
|
== "cmake rustc"
|
|
)
|
|
assert (
|
|
options_reader.get("test-sources", option_format=ListFormat(" ", quote=shlex.quote))
|
|
== 'first "second third"'
|
|
)
|
|
assert (
|
|
options_reader.get("test-requires", option_format=ListFormat(" "))
|
|
== {"windows": "docs", "macos": "docs", "linux": "scod"}[platform]
|
|
)
|
|
assert (
|
|
options_reader.get("test-groups", option_format=ListFormat(" "))
|
|
== {"windows": "mgroup two", "macos": "mgroup two", "linux": "lgroup"}[platform]
|
|
)
|
|
assert options_reader.get("test-command") == "mytest"
|
|
|
|
|
|
def test_project_global_override_default_platform(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
repair-wheel-command = "repair-project-global"
|
|
"""
|
|
)
|
|
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
|
|
assert options_reader.get("repair-wheel-command") == "repair-project-global"
|
|
|
|
|
|
def test_env_global_override_default_platform(platform: PlatformName) -> None:
|
|
options_reader = OptionsReader(
|
|
platform=platform, env={"CIBW_REPAIR_WHEEL_COMMAND": "repair-env-global"}
|
|
)
|
|
assert options_reader.get("repair-wheel-command") == "repair-env-global"
|
|
|
|
|
|
def test_env_global_override_project_platform(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel.linux]
|
|
repair-wheel-command = "repair-project-linux"
|
|
[tool.cibuildwheel.windows]
|
|
repair-wheel-command = "repair-project-windows"
|
|
[tool.cibuildwheel.macos]
|
|
repair-wheel-command = "repair-project-macos"
|
|
"""
|
|
)
|
|
options_reader = OptionsReader(
|
|
pyproject_toml,
|
|
platform=cast("Any", platform),
|
|
env={
|
|
"CIBW_REPAIR_WHEEL_COMMAND": "repair-env-global",
|
|
},
|
|
)
|
|
assert options_reader.get("repair-wheel-command") == "repair-env-global"
|
|
|
|
|
|
def test_global_platform_order(tmp_path: Path, platform: str) -> None:
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel.linux]
|
|
repair-wheel-command = "repair-project-linux"
|
|
[tool.cibuildwheel.windows]
|
|
repair-wheel-command = "repair-project-windows"
|
|
[tool.cibuildwheel.macos]
|
|
repair-wheel-command = "repair-project-macos"
|
|
[tool.cibuildwheel]
|
|
repair-wheel-command = "repair-project-global"
|
|
"""
|
|
)
|
|
options_reader = OptionsReader(pyproject_toml, platform=cast("Any", platform), env={})
|
|
assert options_reader.get("repair-wheel-command") == f"repair-project-{platform}"
|
|
|
|
|
|
def test_unexpected_key(tmp_path: Path) -> None:
|
|
# Note that platform contents are only checked when running
|
|
# for that platform.
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
repairs-wheel-command = "repair-project-linux"
|
|
"""
|
|
)
|
|
|
|
with pytest.raises(OptionsReaderError) as excinfo:
|
|
OptionsReader(pyproject_toml, platform="linux", env={})
|
|
|
|
assert "repair-wheel-command" in str(excinfo.value)
|
|
|
|
|
|
def test_underscores_in_key(tmp_path: Path) -> None:
|
|
# Note that platform contents are only checked when running
|
|
# for that platform.
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
repair_wheel_command = "repair-project-linux"
|
|
"""
|
|
)
|
|
|
|
with pytest.raises(OptionsReaderError) as excinfo:
|
|
OptionsReader(pyproject_toml, platform="linux", env={})
|
|
|
|
assert "repair-wheel-command" in str(excinfo.value)
|
|
|
|
|
|
def test_unexpected_table(tmp_path: Path) -> None:
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel.linus]
|
|
repair-wheel-command = "repair-project-linux"
|
|
"""
|
|
)
|
|
with pytest.raises(OptionsReaderError):
|
|
OptionsReader(pyproject_toml, platform="linux", env={})
|
|
|
|
|
|
def test_unsupported_join(tmp_path: Path) -> None:
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
build = ["1", "2"]
|
|
"""
|
|
)
|
|
options_reader = OptionsReader(pyproject_toml, platform="linux", env={})
|
|
|
|
assert options_reader.get("build", option_format=ListFormat(", ")) == "1, 2"
|
|
with pytest.raises(OptionsReaderError):
|
|
options_reader.get("build")
|
|
|
|
|
|
def test_disallowed_a(tmp_path: Path) -> None:
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel.windows]
|
|
manylinux-x86_64-image = "manylinux1"
|
|
"""
|
|
)
|
|
disallow = {"windows": {"manylinux-x86_64-image"}}
|
|
OptionsReader(pyproject_toml, platform="linux", disallow=disallow, env={})
|
|
with pytest.raises(OptionsReaderError):
|
|
OptionsReader(pyproject_toml, platform="windows", disallow=disallow, env={})
|
|
|
|
|
|
def test_environment_override_empty(tmp_path: Path) -> None:
|
|
pyproject_toml = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
manylinux-i686-image = "manylinux1"
|
|
manylinux-x86_64-image = ""
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(
|
|
pyproject_toml,
|
|
platform="linux",
|
|
env={
|
|
"CIBW_MANYLINUX_I686_IMAGE": "",
|
|
"CIBW_MANYLINUX_AARCH64_IMAGE": "manylinux1",
|
|
"CIBW_XBUILD_TOOLS": "",
|
|
},
|
|
)
|
|
|
|
assert options_reader.get("manylinux-x86_64-image") == ""
|
|
assert options_reader.get("manylinux-i686-image") == ""
|
|
assert options_reader.get("manylinux-aarch64-image") == "manylinux1"
|
|
|
|
assert options_reader.get("manylinux-x86_64-image", ignore_empty=True) == "manylinux_2_28"
|
|
assert options_reader.get("manylinux-i686-image", ignore_empty=True) == "manylinux1"
|
|
assert options_reader.get("manylinux-aarch64-image", ignore_empty=True) == "manylinux1"
|
|
|
|
assert (
|
|
options_reader.get("xbuild-tools", option_format=ListFormat(" ", quote=shlex.quote)) == ""
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("ignore_empty", [True, False], ids=["ignore_empty", "no_ignore_empty"])
|
|
def test_resolve_cascade(ignore_empty: bool) -> None:
|
|
answer = _resolve_cascade(
|
|
("not", InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
("", InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
ignore_empty=ignore_empty,
|
|
)
|
|
assert answer == ("not" if ignore_empty else "")
|
|
|
|
answer = _resolve_cascade(
|
|
("d4", InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
("that", InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
ignore_empty=ignore_empty,
|
|
)
|
|
assert answer == "that"
|
|
|
|
with pytest.raises(ValueError, match="a setting should at least have a default value"):
|
|
_resolve_cascade(
|
|
(None, InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
ignore_empty=ignore_empty,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("ignore_empty", [True, False], ids=["ignore_empty", "no_ignore_empty"])
|
|
@pytest.mark.parametrize("rule", [InheritRule.PREPEND, InheritRule.NONE, InheritRule.APPEND])
|
|
def test_resolve_cascade_merge_list(ignore_empty: bool, rule: InheritRule) -> None:
|
|
answer = _resolve_cascade(
|
|
(["a1", "a2"], InheritRule.NONE),
|
|
([], InheritRule.NONE),
|
|
(["b1", "b2"], rule),
|
|
(None, InheritRule.NONE),
|
|
ignore_empty=ignore_empty,
|
|
option_format=ListFormat(" "),
|
|
)
|
|
|
|
if not ignore_empty:
|
|
assert answer == "b1 b2"
|
|
elif rule == InheritRule.PREPEND:
|
|
assert answer == "b1 b2 a1 a2"
|
|
elif rule == InheritRule.NONE:
|
|
assert answer == "b1 b2"
|
|
elif rule == InheritRule.APPEND:
|
|
assert answer == "a1 a2 b1 b2"
|
|
|
|
|
|
@pytest.mark.parametrize("rule", [InheritRule.PREPEND, InheritRule.NONE, InheritRule.APPEND])
|
|
def test_resolve_cascade_merge_dict(rule: InheritRule) -> None:
|
|
answer = _resolve_cascade(
|
|
({"value": "a1", "base": "b1"}, InheritRule.NONE),
|
|
(None, InheritRule.NONE),
|
|
({"value": "override"}, rule),
|
|
(None, InheritRule.NONE),
|
|
option_format=ShlexTableFormat(),
|
|
)
|
|
|
|
if rule == InheritRule.PREPEND:
|
|
assert answer == "value=a1 base=b1"
|
|
elif rule == InheritRule.NONE:
|
|
assert answer == "value=override"
|
|
elif rule == InheritRule.APPEND:
|
|
assert answer == "value=override base=b1"
|
|
|
|
|
|
def test_resolve_cascade_merge_strings() -> None:
|
|
answer = _resolve_cascade(
|
|
("value=a1 base=b1", InheritRule.NONE),
|
|
("value=override", InheritRule.APPEND),
|
|
option_format=ShlexTableFormat(),
|
|
)
|
|
assert answer == "value=override base=b1"
|
|
|
|
|
|
def test_resolve_cascade_merge_different_types() -> None:
|
|
answer = _resolve_cascade(
|
|
("value=a1 base=b1", InheritRule.NONE),
|
|
({"value": "override"}, InheritRule.APPEND),
|
|
("extra_string_var=c1", InheritRule.APPEND),
|
|
option_format=ShlexTableFormat(),
|
|
)
|
|
assert answer == "value=override base=b1 extra_string_var=c1"
|
|
|
|
|
|
PYPROJECT_2 = """
|
|
[tool.cibuildwheel]
|
|
build = ["cp38*", "cp37*"]
|
|
environment = {FOO="BAR", "HAM"="EGGS"}
|
|
|
|
test-command = ["pyproject"]
|
|
|
|
manylinux-x86_64-image = "manylinux1"
|
|
|
|
[tool.cibuildwheel.macos]
|
|
test-requires = "else"
|
|
|
|
[[tool.cibuildwheel.overrides]]
|
|
select = "cp37*"
|
|
inherit = {test-command="prepend", environment="append"}
|
|
test-command = ["pyproject-override", "override2"]
|
|
manylinux-x86_64-image = "manylinux2014"
|
|
environment = {FOO="BAZ", "PYTHON"="MONTY"}
|
|
|
|
[[tool.cibuildwheel.overrides]]
|
|
select = "*-final"
|
|
inherit = {test-command="append"}
|
|
test-command = ["pyproject-finalize", "finalize2"]
|
|
|
|
[[tool.cibuildwheel.overrides]]
|
|
select = "*-final"
|
|
inherit = {test-command="append"}
|
|
test-command = ["extra-finalize"]
|
|
|
|
[[tool.cibuildwheel.overrides]]
|
|
select = "*-final"
|
|
inherit = {test-command="prepend"}
|
|
test-command = ["extra-prepend"]
|
|
"""
|
|
|
|
|
|
def test_pyproject_2(tmp_path: Path, platform: str) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(PYPROJECT_2)
|
|
|
|
options_reader = OptionsReader(
|
|
config_file_path=pyproject_toml, platform=cast("Any", platform), env={}
|
|
)
|
|
assert options_reader.get("test-command", option_format=ListFormat(" && ")) == "pyproject"
|
|
|
|
with options_reader.identifier("random"):
|
|
assert options_reader.get("test-command", option_format=ListFormat(" && ")) == "pyproject"
|
|
|
|
with options_reader.identifier("cp37-something"):
|
|
assert (
|
|
options_reader.get("test-command", option_format=ListFormat(" && "))
|
|
== "pyproject-override && override2 && pyproject"
|
|
)
|
|
assert (
|
|
options_reader.get("environment", option_format=EnvironmentFormat())
|
|
== 'FOO="BAR" HAM="EGGS" FOO="BAZ" PYTHON="MONTY"'
|
|
)
|
|
|
|
with options_reader.identifier("cp37-final"):
|
|
assert (
|
|
options_reader.get("test-command", option_format=ListFormat(" && "))
|
|
== "extra-prepend && pyproject-override && override2 && pyproject && pyproject-finalize && finalize2 && extra-finalize"
|
|
)
|
|
assert (
|
|
options_reader.get("environment", option_format=EnvironmentFormat())
|
|
== 'FOO="BAR" HAM="EGGS" FOO="BAZ" PYTHON="MONTY"'
|
|
)
|
|
|
|
|
|
def test_overrides_not_a_list(tmp_path: Path, platform: str) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
|
|
pyproject_toml.write_text(
|
|
"""\
|
|
[tool.cibuildwheel]
|
|
build = ["cp38*", "cp37*"]
|
|
[tool.cibuildwheel.overrides]
|
|
select = "cp37*"
|
|
test-command = "pyproject-override"
|
|
"""
|
|
)
|
|
|
|
with pytest.raises(OptionsReaderError):
|
|
OptionsReader(config_file_path=pyproject_toml, platform=cast("Any", platform), env={})
|
|
|
|
|
|
def test_config_settings(tmp_path: Path) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""\
|
|
[tool.cibuildwheel.config-settings]
|
|
example = "one"
|
|
other = ["two", "three"]
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(config_file_path=pyproject_toml, platform="linux", env={})
|
|
assert (
|
|
options_reader.get("config-settings", option_format=ShlexTableFormat(pair_sep="=", sep=" "))
|
|
== "example=one other=two other=three"
|
|
)
|
|
|
|
|
|
def test_pip_config_settings(tmp_path: Path) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""\
|
|
[tool.cibuildwheel.config-settings]
|
|
--build-option="--use-mypyc"
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(config_file_path=pyproject_toml, platform="linux", env={})
|
|
assert (
|
|
options_reader.get("config-settings", option_format=ShlexTableFormat(sep=" ", pair_sep="="))
|
|
== "--build-option=--use-mypyc"
|
|
)
|
|
|
|
|
|
def test_overrides_inherit(tmp_path: Path) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""\
|
|
[tool.cibuildwheel]
|
|
before-all = ["before-all"]
|
|
config-settings = {key1="value1", key2="value2", empty=""}
|
|
|
|
[[tool.cibuildwheel.overrides]]
|
|
select = "cp37*"
|
|
inherit.before-all = "append"
|
|
before-all = ["override1"]
|
|
|
|
inherit.config-settings = "append"
|
|
config-settings = {key3="value3", key2="override2"}
|
|
|
|
[[tool.cibuildwheel.overrides]]
|
|
select = "cp37*"
|
|
inherit.before-all = "prepend"
|
|
before-all = ["override2"]
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(config_file_path=pyproject_toml, platform="linux", env={})
|
|
with options_reader.identifier("cp38-something"):
|
|
assert options_reader.get("before-all", option_format=ListFormat(" && ")) == "before-all"
|
|
assert (
|
|
options_reader.get("config-settings", option_format=ShlexTableFormat())
|
|
== "key1=value1 key2=value2 empty=''"
|
|
)
|
|
with options_reader.identifier("cp37-something"):
|
|
assert (
|
|
options_reader.get("before-all", option_format=ListFormat(" && "))
|
|
== "override2 && before-all && override1"
|
|
)
|
|
assert (
|
|
options_reader.get("config-settings", option_format=ShlexTableFormat())
|
|
== "key1=value1 key2=override2 empty='' key3=value3"
|
|
)
|
|
|
|
|
|
def test_audit_command_option(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
audit-command = "abi3audit {abi3_wheel}"
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
|
|
assert (
|
|
options_reader.get("audit-command", option_format=ListFormat(" && "))
|
|
== "abi3audit {abi3_wheel}"
|
|
)
|
|
|
|
|
|
def test_audit_command_option_list(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
audit-command = ["first command", "second command"]
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
|
|
assert (
|
|
options_reader.get("audit-command", option_format=ListFormat(" && "))
|
|
== "first command && second command"
|
|
)
|
|
|
|
|
|
def test_audit_command_option_env(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(
|
|
pyproject_toml, platform=platform, env={"CIBW_AUDIT_COMMAND": "my-audit-tool {wheel}"}
|
|
)
|
|
assert (
|
|
options_reader.get("audit-command", option_format=ListFormat(" && "))
|
|
== "my-audit-tool {wheel}"
|
|
)
|
|
|
|
|
|
def test_audit_requires_option(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
audit-requires = "abi3audit"
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
|
|
assert options_reader.get("audit-requires", option_format=ListFormat(" ")) == "abi3audit"
|
|
|
|
|
|
def test_audit_requires_option_list(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
audit-requires = ["abi3audit", "twine"]
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
|
|
assert options_reader.get("audit-requires", option_format=ListFormat(" ")) == "abi3audit twine"
|
|
|
|
|
|
def test_audit_requires_option_env(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(
|
|
pyproject_toml, platform=platform, env={"CIBW_AUDIT_REQUIRES": "custom-audit-tool"}
|
|
)
|
|
assert (
|
|
options_reader.get("audit-requires", option_format=ListFormat(" ")) == "custom-audit-tool"
|
|
)
|
|
|
|
|
|
def test_audit_requires_option_env_override(tmp_path: Path, platform: PlatformName) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
audit-requires = "abi3audit"
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(
|
|
pyproject_toml, platform=platform, env={"CIBW_AUDIT_REQUIRES": "custom-audit-tool"}
|
|
)
|
|
assert (
|
|
options_reader.get("audit-requires", option_format=ListFormat(" ")) == "custom-audit-tool"
|
|
)
|
|
|
|
|
|
def test_audit_requires_platform_specific(tmp_path: Path) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
audit-requires = "abi3audit"
|
|
|
|
[tool.cibuildwheel.linux]
|
|
audit-requires = ["abi3audit", "check-wheel-contents"] # whatever
|
|
|
|
[tool.cibuildwheel.macos]
|
|
audit-requires = ["check-wheel-contents", "pydistcheck"] # whatever
|
|
"""
|
|
)
|
|
|
|
linux_reader = OptionsReader(pyproject_toml, platform="linux", env={})
|
|
assert (
|
|
linux_reader.get("audit-requires", option_format=ListFormat(" "))
|
|
== "abi3audit check-wheel-contents"
|
|
)
|
|
|
|
macos_reader = OptionsReader(pyproject_toml, platform="macos", env={})
|
|
assert (
|
|
macos_reader.get("audit-requires", option_format=ListFormat(" "))
|
|
== "check-wheel-contents pydistcheck"
|
|
)
|
|
|
|
windows_reader = OptionsReader(pyproject_toml, platform="windows", env={})
|
|
assert windows_reader.get("audit-requires", option_format=ListFormat(" ")) == "abi3audit"
|
|
|
|
|
|
def test_audit_requires_platform_env_override(tmp_path: Path) -> None:
|
|
pyproject_toml: Path = tmp_path / "pyproject.toml"
|
|
pyproject_toml.write_text(
|
|
"""
|
|
[tool.cibuildwheel]
|
|
audit-requires = "abi3audit"
|
|
"""
|
|
)
|
|
|
|
options_reader = OptionsReader(
|
|
pyproject_toml,
|
|
platform="linux",
|
|
env={
|
|
"CIBW_AUDIT_REQUIRES": "some-fallback-tool",
|
|
"CIBW_AUDIT_REQUIRES_LINUX": "linux-audit-tool",
|
|
},
|
|
)
|
|
assert options_reader.get("audit-requires", option_format=ListFormat(" ")) == "linux-audit-tool"
|