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:
|
||||
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.
|
||||
|
||||
@@ -276,7 +276,12 @@ def setup_env(
|
||||
call(*pip, "install", *pb.build_system_requires, env=build_env)
|
||||
|
||||
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:
|
||||
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.frontend import (
|
||||
BuildFrontendConfig,
|
||||
_split_config_settings,
|
||||
get_build_frontend_extra_flags,
|
||||
parse_config_settings,
|
||||
prepare_config_settings,
|
||||
)
|
||||
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(
|
||||
("definition", "expected_args"),
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user