From e97e4562b1de2cc53824819c0452b096718ed0ad Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Tue, 4 Aug 2026 11:52:22 +0100 Subject: [PATCH] add tests --- cibuildwheel/options.py | 8 +- ...ns_toml_test.py => options_reader_test.py} | 109 ++++++++++++++++++ 2 files changed, 114 insertions(+), 3 deletions(-) rename unit_test/{options_toml_test.py => options_reader_test.py} (88%) diff --git a/cibuildwheel/options.py b/cibuildwheel/options.py index 014d501c..2345f18d 100644 --- a/cibuildwheel/options.py +++ b/cibuildwheel/options.py @@ -450,7 +450,7 @@ def parse_inherit(config: str | dict[str, str] | None) -> dict[str, InheritRule] if isinstance(config, str): parsed = parse_kw_string(config, default_kw_value="append") - inherit_dict = {k: "".join(v).upper() for k, v in parsed.items()} + inherit_dict = {k: "".join(v) for k, v in parsed.items()} elif isinstance(config, dict): inherit_dict = config else: @@ -523,7 +523,7 @@ class OptionsReader: Raises an error if an option with this name is not allowed in the [tool.cibuildwheel] section of a config file. """ - allowed_option_names = self.default_options.keys() | PLATFORMS | {"overrides"} + allowed_option_names = self.default_options.keys() | PLATFORMS | {"inherit", "overrides"} if name not in allowed_option_names: msg = f"Option {name!r} not supported in a config file." @@ -542,7 +542,9 @@ class OptionsReader: msg = f"{name!r} is not allowed in {disallowed_platform_options}" raise OptionsReaderError(msg) - allowed_option_names = self.default_options.keys() | self.default_platform_options.keys() + allowed_option_names = ( + self.default_options.keys() | self.default_platform_options.keys() | {"inherit"} + ) if name not in allowed_option_names: msg = f"Option {name!r} not supported in the {self.platform!r} section" diff --git a/unit_test/options_toml_test.py b/unit_test/options_reader_test.py similarity index 88% rename from unit_test/options_toml_test.py rename to unit_test/options_reader_test.py index dc14d392..140b335c 100644 --- a/unit_test/options_toml_test.py +++ b/unit_test/options_reader_test.py @@ -1,3 +1,5 @@ +"""Tests for reading and resolving configuration options.""" + from __future__ import annotations import shlex @@ -5,6 +7,7 @@ from typing import Any, cast import pytest +from cibuildwheel import errors from cibuildwheel.options import ( EnvironmentFormat, InheritRule, @@ -553,6 +556,112 @@ before-all = ["override2"] ) +def test_global_inherit(tmp_path: Path) -> None: + pyproject_toml = tmp_path / "pyproject.toml" + pyproject_toml.write_text( + """\ +[tool.cibuildwheel] +inherit = {audit-command = "append"} +audit-command = "twine check {wheel}" +""" + ) + + options_reader = OptionsReader(pyproject_toml, platform="linux", env={}) + + assert ( + options_reader.get("audit-command", option_format=ListFormat(" && ")) + == "abi3audit --strict --report {abi3_wheel} && twine check {wheel}" + ) + + +def test_platform_inherit(tmp_path: Path) -> None: + pyproject_toml = tmp_path / "pyproject.toml" + pyproject_toml.write_text( + """\ +[tool.cibuildwheel] +before-all = "global" + +[tool.cibuildwheel.linux] +inherit = {before-all = "prepend"} +before-all = "linux" +""" + ) + + options_reader = OptionsReader(pyproject_toml, platform="linux", env={}) + + assert options_reader.get("before-all", option_format=ListFormat(" && ")) == "linux && global" + + +def test_environment_inherit(tmp_path: Path) -> None: + pyproject_toml = tmp_path / "pyproject.toml" + pyproject_toml.write_text( + """\ +[tool.cibuildwheel] +before-all = "config" +""" + ) + + options_reader = OptionsReader( + pyproject_toml, + platform="linux", + env={ + "CIBW_BEFORE_ALL": "env", + "CIBW_BEFORE_ALL_LINUX": "linux-env", + # A key without a value defaults to append. + "CIBW_INHERIT": "before-all; before-all-linux: prepend", + }, + ) + + assert ( + options_reader.get("before-all", option_format=ListFormat(" && ")) + == "linux-env && config && env" + ) + + +def test_environment_inherit_none_overrides_default_rule(tmp_path: Path) -> None: + pyproject_toml = tmp_path / "pyproject.toml" + pyproject_toml.write_text( + """\ +[tool.cibuildwheel] +enable = ["cpython-freethreading"] +""" + ) + options_reader = OptionsReader( + pyproject_toml, + platform="linux", + env={"CIBW_ENABLE": "pypy", "CIBW_INHERIT": "enable: none"}, + ) + + assert ( + options_reader.get( + "enable", option_format=ListFormat(" "), default_env_rule=InheritRule.APPEND + ) + == "pypy" + ) + + +def test_invalid_config_inherit_rule(tmp_path: Path) -> None: + pyproject_toml = tmp_path / "pyproject.toml" + pyproject_toml.write_text( + """\ +[tool.cibuildwheel] +inherit = {before-all = "invalid"} +""" + ) + + with pytest.raises(OptionsReaderError, match="must contain only"): + OptionsReader(pyproject_toml, platform="linux", env={}) + + +def test_invalid_environment_inherit_rule() -> None: + options_reader = OptionsReader(platform="linux", env={"CIBW_INHERIT": "before-all: invalid"}) + + with pytest.raises( + errors.ConfigurationError, match="Failed to parse CIBW_INHERIT environment variable" + ): + options_reader.get("before-all", option_format=ListFormat(" && ")) + + def test_audit_command_option(tmp_path: Path, platform: PlatformName) -> None: pyproject_toml: Path = tmp_path / "pyproject.toml" pyproject_toml.write_text(