fix: config settings expansion issue (#2886)
This commit is contained in:
@@ -62,7 +62,17 @@ def _split_config_settings(config_settings: str) -> list[str]:
|
|||||||
|
|
||||||
|
|
||||||
def prepare_config_settings(config_settings: str, *, project: PathOrStr, package: PathOrStr) -> str:
|
def prepare_config_settings(config_settings: str, *, project: PathOrStr, package: PathOrStr) -> str:
|
||||||
return prepare_command(config_settings, project=project, package=package)
|
# Substitute the {project}/{package} placeholders on each already-split
|
||||||
|
# token rather than on the raw string. A substituted path may contain
|
||||||
|
# spaces or backslashes (e.g. a Windows `{package}` path), and the result
|
||||||
|
# is later re-parsed with shlex.split (in _split_config_settings /
|
||||||
|
# parse_config_settings) — substituting on the whole string would let
|
||||||
|
# those characters be reinterpreted, splitting one setting into several or
|
||||||
|
# eating backslashes. shlex.join re-quotes each token so the round-trip is
|
||||||
|
# lossless.
|
||||||
|
settings = shlex.split(config_settings)
|
||||||
|
prepared = [prepare_command(setting, project=project, package=package) for setting in settings]
|
||||||
|
return shlex.join(prepared)
|
||||||
|
|
||||||
|
|
||||||
# Based on build.__main__.main.
|
# Based on build.__main__.main.
|
||||||
|
|||||||
@@ -276,7 +276,12 @@ def setup_env(
|
|||||||
call(*pip, "install", *pb.build_system_requires, env=build_env)
|
call(*pip, "install", *pb.build_system_requires, env=build_env)
|
||||||
|
|
||||||
requires_for_build = pb.get_requires_for_build(
|
requires_for_build = pb.get_requires_for_build(
|
||||||
"wheel", parse_config_settings(build_options.config_settings)
|
"wheel",
|
||||||
|
parse_config_settings(
|
||||||
|
prepare_config_settings(
|
||||||
|
build_options.config_settings, project=".", package=build_options.package_dir
|
||||||
|
)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
if requires_for_build:
|
if requires_for_build:
|
||||||
call(*pip, "install", *requires_for_build, env=build_env)
|
call(*pip, "install", *requires_for_build, env=build_env)
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ from cibuildwheel import errors
|
|||||||
from cibuildwheel.bashlex_eval import local_environment_executor
|
from cibuildwheel.bashlex_eval import local_environment_executor
|
||||||
from cibuildwheel.frontend import (
|
from cibuildwheel.frontend import (
|
||||||
BuildFrontendConfig,
|
BuildFrontendConfig,
|
||||||
|
_split_config_settings,
|
||||||
get_build_frontend_extra_flags,
|
get_build_frontend_extra_flags,
|
||||||
|
parse_config_settings,
|
||||||
prepare_config_settings,
|
prepare_config_settings,
|
||||||
)
|
)
|
||||||
from cibuildwheel.logger import Logger
|
from cibuildwheel.logger import Logger
|
||||||
@@ -608,6 +610,29 @@ def test_prepare_config_settings(config_settings: str, expected: str) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("project", "package"),
|
||||||
|
[
|
||||||
|
(R"C:\Users\John Doe\project", R"C:\Users\John Doe\project\pkg"),
|
||||||
|
("/home/me/my project", "/home/me/my project/pkg"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_prepare_config_settings_special_chars(project: str, package: str) -> None:
|
||||||
|
# Paths with spaces or backslashes must survive the round-trip through the
|
||||||
|
# downstream shlex.split intact (regression test for the {package}/{project}
|
||||||
|
# substitution being mangled by re-parsing).
|
||||||
|
config_settings = "setup-args=--cross-file={package}/cross.ini other-setting={project}"
|
||||||
|
prepared = prepare_config_settings(config_settings, project=project, package=package)
|
||||||
|
assert _split_config_settings(prepared) == [
|
||||||
|
f"-Csetup-args=--cross-file={package}/cross.ini",
|
||||||
|
f"-Cother-setting={project}",
|
||||||
|
]
|
||||||
|
assert parse_config_settings(prepared) == {
|
||||||
|
"setup-args": f"--cross-file={package}/cross.ini",
|
||||||
|
"other-setting": project,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("definition", "expected_args"),
|
("definition", "expected_args"),
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user