Skip to content

Commit 7cb863e

Browse files
authored
Stop propagating config_settings to dependencies (#11941)
1 parent 81f6a9f commit 7cb863e

File tree

5 files changed

+144
-18
lines changed

5 files changed

+144
-18
lines changed

docs/html/reference/build-system/pyproject-toml.md

+6
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ multiple times, in order to specify multiple settings).
116116

117117
The supplied configuration settings are passed to every backend hook call.
118118

119+
Configuration settings provided via `--config-settings` command line options (or the
120+
equivalent environment variables or configuration file entries) are passed to the build
121+
of requirements explicitly provided as pip command line arguments. They are not passed
122+
to the build of dependencies, or to the build of requirements provided in requirement
123+
files.
124+
119125
## Build output
120126

121127
It is the responsibility of the build backend to ensure that the output is

news/11941.feature.rst

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Stop propagating CLI ``--config-settings`` to the build dependencies. They already did
2+
not propagate to requirements provided in requirement files. To pass the same config
3+
settings to several requirements, users should provide the requirements as CLI
4+
arguments.

src/pip/_internal/cli/req_command.py

-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,6 @@ def make_resolver(
344344
install_req_from_req_string,
345345
isolated=options.isolated_mode,
346346
use_pep517=use_pep517,
347-
config_settings=getattr(options, "config_settings", None),
348347
)
349348
resolver_variant = cls.determine_resolver_variant(options)
350349
# The long import name and duplicated invocation is needed to convince

src/pip/_internal/req/constructors.py

-2
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,6 @@ def install_req_from_req_string(
416416
isolated: bool = False,
417417
use_pep517: Optional[bool] = None,
418418
user_supplied: bool = False,
419-
config_settings: Optional[Dict[str, Union[str, List[str]]]] = None,
420419
) -> InstallRequirement:
421420
try:
422421
req = get_requirement(req_string)
@@ -446,7 +445,6 @@ def install_req_from_req_string(
446445
isolated=isolated,
447446
use_pep517=use_pep517,
448447
user_supplied=user_supplied,
449-
config_settings=config_settings,
450448
)
451449

452450

tests/functional/test_config_settings.py

+134-15
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import json
2+
import tarfile
23
from pathlib import Path
3-
from typing import Tuple
4+
from typing import List, Optional, Tuple
45
from zipfile import ZipFile
56

7+
from pip._internal.utils.urls import path_to_url
68
from tests.lib import PipTestEnvironment
79

810
PYPROJECT_TOML = """\
@@ -36,9 +38,10 @@
3638
Author: None
3739
Author-email: [email protected]
3840
License: MIT
41+
{requires_dist}
3942
"""
4043
41-
def make_wheel(z, project, version, files):
44+
def make_wheel(z, project, version, requires_dist, files):
4245
record = []
4346
def add_file(name, data):
4447
data = data.encode("utf-8")
@@ -48,7 +51,9 @@ def add_file(name, data):
4851
record.append((name, f"sha256={hash}", len(data)))
4952
distinfo = f"{project}-{version}.dist-info"
5053
add_file(f"{distinfo}/WHEEL", WHEEL)
51-
add_file(f"{distinfo}/METADATA", METADATA.format(project=project, version=version))
54+
add_file(f"{distinfo}/METADATA", METADATA.format(
55+
project=project, version=version, requires_dist=requires_dist
56+
))
5257
for name, data in files:
5358
add_file(name, data)
5459
record_name = f"{distinfo}/RECORD"
@@ -70,29 +75,35 @@ def build_wheel(
7075
):
7176
if config_settings is None:
7277
config_settings = {}
73-
w = os.path.join(wheel_directory, "foo-1.0-py3-none-any.whl")
78+
w = os.path.join(wheel_directory, "{{name}}-1.0-py3-none-any.whl")
7479
with open(w, "wb") as f:
7580
with ZipFile(f, "w") as z:
7681
make_wheel(
77-
z, "foo", "1.0",
78-
[("config.json", json.dumps(config_settings))]
82+
z, "{{name}}", "1.0", "{{requires_dist}}",
83+
[("{{name}}-config.json", json.dumps(config_settings))]
7984
)
80-
return "foo-1.0-py3-none-any.whl"
85+
return "{{name}}-1.0-py3-none-any.whl"
8186
8287
build_editable = build_wheel
8388
8489
main = Backend()
8590
'''
8691

8792

88-
def make_project(path: Path) -> Tuple[str, str, Path]:
89-
name = "foo"
93+
def make_project(
94+
path: Path, name: str = "foo", dependencies: Optional[List[str]] = None
95+
) -> Tuple[str, str, Path]:
9096
version = "1.0"
9197
project_dir = path / name
9298
backend = project_dir / "backend"
9399
backend.mkdir(parents=True)
94100
(project_dir / "pyproject.toml").write_text(PYPROJECT_TOML)
95-
(backend / "dummy_backend.py").write_text(BACKEND_SRC)
101+
requires_dist = [f"Requires-Dist: {dep}" for dep in dependencies or []]
102+
(backend / "dummy_backend.py").write_text(
103+
BACKEND_SRC.replace("{{name}}", name).replace(
104+
"{{requires_dist}}", "\n".join(requires_dist)
105+
)
106+
)
96107
return name, version, project_dir
97108

98109

@@ -108,32 +119,140 @@ def test_backend_sees_config(script: PipTestEnvironment) -> None:
108119
wheel_file_path = script.cwd / wheel_file_name
109120
with open(wheel_file_path, "rb") as f:
110121
with ZipFile(f) as z:
111-
output = z.read("config.json")
122+
output = z.read(f"{name}-config.json")
123+
assert json.loads(output) == {"FOO": "Hello"}
124+
125+
126+
def test_backend_sees_config_via_constraint(script: PipTestEnvironment) -> None:
127+
name, version, project_dir = make_project(script.scratch_path)
128+
constraints_file = script.scratch_path / "constraints.txt"
129+
constraints_file.write_text(f"{name} @ {path_to_url(str(project_dir))}")
130+
script.pip(
131+
"wheel",
132+
"--config-settings",
133+
"FOO=Hello",
134+
"-c",
135+
"constraints.txt",
136+
name,
137+
)
138+
wheel_file_name = f"{name}-{version}-py3-none-any.whl"
139+
wheel_file_path = script.cwd / wheel_file_name
140+
with open(wheel_file_path, "rb") as f:
141+
with ZipFile(f) as z:
142+
output = z.read(f"{name}-config.json")
143+
assert json.loads(output) == {"FOO": "Hello"}
144+
145+
146+
def test_backend_sees_config_via_sdist(script: PipTestEnvironment) -> None:
147+
name, version, project_dir = make_project(script.scratch_path)
148+
dists_dir = script.scratch_path / "dists"
149+
dists_dir.mkdir()
150+
with tarfile.open(dists_dir / f"{name}-{version}.tar.gz", "w:gz") as dist_tar:
151+
dist_tar.add(project_dir, arcname=name)
152+
script.pip(
153+
"wheel",
154+
"--config-settings",
155+
"FOO=Hello",
156+
"-f",
157+
dists_dir,
158+
name,
159+
)
160+
wheel_file_name = f"{name}-{version}-py3-none-any.whl"
161+
wheel_file_path = script.cwd / wheel_file_name
162+
with open(wheel_file_path, "rb") as f:
163+
with ZipFile(f) as z:
164+
output = z.read(f"{name}-config.json")
112165
assert json.loads(output) == {"FOO": "Hello"}
113166

114167

168+
def test_req_file_does_not_see_config(script: PipTestEnvironment) -> None:
169+
"""Test that CLI config settings do not propagate to requirement files."""
170+
name, _, project_dir = make_project(script.scratch_path)
171+
reqs_file = script.scratch_path / "reqs.txt"
172+
reqs_file.write_text(f"{project_dir}")
173+
script.pip(
174+
"install",
175+
"--config-settings",
176+
"FOO=Hello",
177+
"-r",
178+
reqs_file,
179+
)
180+
config = script.site_packages_path / f"{name}-config.json"
181+
with open(config, "rb") as f:
182+
assert json.load(f) == {}
183+
184+
185+
def test_dep_does_not_see_config(script: PipTestEnvironment) -> None:
186+
"""Test that CLI config settings do not propagate to dependencies."""
187+
_, _, bar_project_dir = make_project(script.scratch_path, name="bar")
188+
_, _, foo_project_dir = make_project(
189+
script.scratch_path,
190+
name="foo",
191+
dependencies=[f"bar @ {path_to_url(str(bar_project_dir))}"],
192+
)
193+
script.pip(
194+
"install",
195+
"--config-settings",
196+
"FOO=Hello",
197+
foo_project_dir,
198+
)
199+
foo_config = script.site_packages_path / "foo-config.json"
200+
with open(foo_config, "rb") as f:
201+
assert json.load(f) == {"FOO": "Hello"}
202+
bar_config = script.site_packages_path / "bar-config.json"
203+
with open(bar_config, "rb") as f:
204+
assert json.load(f) == {}
205+
206+
207+
def test_dep_in_req_file_does_not_see_config(script: PipTestEnvironment) -> None:
208+
"""Test that CLI config settings do not propagate to dependencies found in
209+
requirement files."""
210+
_, _, bar_project_dir = make_project(script.scratch_path, name="bar")
211+
_, _, foo_project_dir = make_project(
212+
script.scratch_path,
213+
name="foo",
214+
dependencies=["bar"],
215+
)
216+
reqs_file = script.scratch_path / "reqs.txt"
217+
reqs_file.write_text(f"bar @ {path_to_url(str(bar_project_dir))}")
218+
script.pip(
219+
"install",
220+
"--config-settings",
221+
"FOO=Hello",
222+
"-r",
223+
reqs_file,
224+
foo_project_dir,
225+
)
226+
foo_config = script.site_packages_path / "foo-config.json"
227+
with open(foo_config, "rb") as f:
228+
assert json.load(f) == {"FOO": "Hello"}
229+
bar_config = script.site_packages_path / "bar-config.json"
230+
with open(bar_config, "rb") as f:
231+
assert json.load(f) == {}
232+
233+
115234
def test_install_sees_config(script: PipTestEnvironment) -> None:
116-
_, _, project_dir = make_project(script.scratch_path)
235+
name, _, project_dir = make_project(script.scratch_path)
117236
script.pip(
118237
"install",
119238
"--config-settings",
120239
"FOO=Hello",
121240
project_dir,
122241
)
123-
config = script.site_packages_path / "config.json"
242+
config = script.site_packages_path / f"{name}-config.json"
124243
with open(config, "rb") as f:
125244
assert json.load(f) == {"FOO": "Hello"}
126245

127246

128247
def test_install_editable_sees_config(script: PipTestEnvironment) -> None:
129-
_, _, project_dir = make_project(script.scratch_path)
248+
name, _, project_dir = make_project(script.scratch_path)
130249
script.pip(
131250
"install",
132251
"--config-settings",
133252
"FOO=Hello",
134253
"--editable",
135254
project_dir,
136255
)
137-
config = script.site_packages_path / "config.json"
256+
config = script.site_packages_path / f"{name}-config.json"
138257
with open(config, "rb") as f:
139258
assert json.load(f) == {"FOO": "Hello"}

0 commit comments

Comments
 (0)