Skip to content

Commit eb04d61

Browse files
committed
Require every call_subprocess call-site to pass command_desc
This serves as additional context that can be presented in error messages.
1 parent 2009a22 commit eb04d61

File tree

10 files changed

+72
-28
lines changed

10 files changed

+72
-28
lines changed

src/pip/_internal/build_env.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ def install_requirements(
189189
finder: "PackageFinder",
190190
requirements: Iterable[str],
191191
prefix_as_string: str,
192-
message: str,
192+
*,
193+
kind: str,
193194
) -> None:
194195
prefix = self._prefixes[prefix_as_string]
195196
assert not prefix.setup
@@ -203,7 +204,7 @@ def install_requirements(
203204
finder,
204205
requirements,
205206
prefix,
206-
message,
207+
kind=kind,
207208
)
208209

209210
@staticmethod
@@ -212,7 +213,8 @@ def _install_requirements(
212213
finder: "PackageFinder",
213214
requirements: Iterable[str],
214215
prefix: _Prefix,
215-
message: str,
216+
*,
217+
kind: str,
216218
) -> None:
217219
args: List[str] = [
218220
sys.executable,
@@ -254,8 +256,13 @@ def _install_requirements(
254256
args.append("--")
255257
args.extend(requirements)
256258
extra_environ = {"_PIP_STANDALONE_CERT": where()}
257-
with open_spinner(message) as spinner:
258-
call_subprocess(args, spinner=spinner, extra_environ=extra_environ)
259+
with open_spinner(f"Installing {kind}") as spinner:
260+
call_subprocess(
261+
args,
262+
command_desc=f"pip subprocess to install {kind}",
263+
spinner=spinner,
264+
extra_environ=extra_environ,
265+
)
259266

260267

261268
class NoOpBuildEnvironment(BuildEnvironment):
@@ -283,6 +290,7 @@ def install_requirements(
283290
finder: "PackageFinder",
284291
requirements: Iterable[str],
285292
prefix_as_string: str,
286-
message: str,
293+
*,
294+
kind: str,
287295
) -> None:
288296
raise NotImplementedError()

src/pip/_internal/distributions/sdist.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def _prepare_build_backend(self, finder: PackageFinder) -> None:
5454

5555
self.req.build_env = BuildEnvironment()
5656
self.req.build_env.install_requirements(
57-
finder, pyproject_requires, "overlay", "Installing build dependencies"
57+
finder, pyproject_requires, "overlay", kind="build dependencies"
5858
)
5959
conflicting, missing = self.req.build_env.check_requirements(
6060
self.req.requirements_to_check
@@ -106,7 +106,7 @@ def _install_build_reqs(self, finder: PackageFinder) -> None:
106106
if conflicting:
107107
self._raise_conflicts("the backend dependencies", conflicting)
108108
self.req.build_env.install_requirements(
109-
finder, missing, "normal", "Installing backend dependencies"
109+
finder, missing, "normal", kind="backend dependencies"
110110
)
111111

112112
def _raise_conflicts(

src/pip/_internal/operations/build/wheel_legacy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def build_wheel_legacy(
8686
try:
8787
output = call_subprocess(
8888
wheel_args,
89+
command_desc="python setup.py bdist_wheel",
8990
cwd=source_dir,
9091
spinner=spinner,
9192
)

src/pip/_internal/operations/install/editable_legacy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,6 @@ def install_editable(
4242
with build_env:
4343
call_subprocess(
4444
args,
45+
command_desc="python setup.py develop",
4546
cwd=unpacked_source_directory,
4647
)

src/pip/_internal/utils/subprocess.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,13 @@ def call_subprocess(
110110
cwd: Optional[str] = None,
111111
on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise",
112112
extra_ok_returncodes: Optional[Iterable[int]] = None,
113-
command_desc: Optional[str] = None,
114113
extra_environ: Optional[Mapping[str, Any]] = None,
115114
unset_environ: Optional[Iterable[str]] = None,
116115
spinner: Optional[SpinnerInterface] = None,
117116
log_failed_cmd: Optional[bool] = True,
118117
stdout_only: Optional[bool] = False,
118+
*,
119+
command_desc: str,
119120
) -> str:
120121
"""
121122
Args:
@@ -166,9 +167,6 @@ def call_subprocess(
166167
# and we have a spinner.
167168
use_spinner = not showing_subprocess and spinner is not None
168169

169-
if command_desc is None:
170-
command_desc = format_command_args(cmd)
171-
172170
log_subprocess("Running command %s", command_desc)
173171
env = os.environ.copy()
174172
if extra_environ:
@@ -281,6 +279,7 @@ def runner(
281279
with open_spinner(message) as spinner:
282280
call_subprocess(
283281
cmd,
282+
command_desc=message,
284283
cwd=cwd,
285284
extra_environ=extra_environ,
286285
spinner=spinner,

src/pip/_internal/vcs/git.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,12 @@ def is_immutable_rev_checkout(self, url: str, dest: str) -> bool:
9191
return not is_tag_or_branch
9292

9393
def get_git_version(self) -> Tuple[int, ...]:
94-
version = self.run_command(["version"], show_stdout=False, stdout_only=True)
94+
version = self.run_command(
95+
["version"],
96+
command_desc="git version",
97+
show_stdout=False,
98+
stdout_only=True,
99+
)
95100
match = GIT_VERSION_REGEX.match(version)
96101
if not match:
97102
logger.warning("Can't parse git version: %s", version)

src/pip/_internal/vcs/versioncontrol.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@
3131
is_installable_dir,
3232
rmtree,
3333
)
34-
from pip._internal.utils.subprocess import CommandArgs, call_subprocess, make_command
34+
from pip._internal.utils.subprocess import (
35+
CommandArgs,
36+
call_subprocess,
37+
format_command_args,
38+
make_command,
39+
)
3540
from pip._internal.utils.urls import get_url_scheme
3641

3742
if TYPE_CHECKING:
@@ -634,6 +639,8 @@ def run_command(
634639
command name, and checks that the VCS is available
635640
"""
636641
cmd = make_command(cls.name, *cmd)
642+
if command_desc is None:
643+
command_desc = format_command_args(cmd)
637644
try:
638645
return call_subprocess(
639646
cmd,

src/pip/_internal/wheel_builder.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,9 @@ def _clean_one_legacy(req: InstallRequirement, global_options: List[str]) -> boo
310310

311311
logger.info("Running setup.py clean for %s", req.name)
312312
try:
313-
call_subprocess(clean_args, cwd=req.source_dir)
313+
call_subprocess(
314+
clean_args, command_desc="python setup.py clean", cwd=req.source_dir
315+
)
314316
return True
315317
except Exception:
316318
logger.error("Failed cleaning build dir for %s", req.name)

tests/functional/test_build_env.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_build_env_allow_empty_requirements_install() -> None:
8181
build_env = BuildEnvironment()
8282
for prefix in ("normal", "overlay"):
8383
build_env.install_requirements(
84-
finder, [], prefix, "Installing build dependencies"
84+
finder, [], prefix, "Installing build dependencies", kind="test"
8585
)
8686

8787

@@ -92,15 +92,15 @@ def test_build_env_allow_only_one_install(script: PipTestEnvironment) -> None:
9292
build_env = BuildEnvironment()
9393
for prefix in ("normal", "overlay"):
9494
build_env.install_requirements(
95-
finder, ["foo"], prefix, f"installing foo in {prefix}"
95+
finder, ["foo"], prefix, f"installing foo in {prefix}", kind="test"
9696
)
9797
with pytest.raises(AssertionError):
9898
build_env.install_requirements(
99-
finder, ["bar"], prefix, f"installing bar in {prefix}"
99+
finder, ["bar"], prefix, f"installing bar in {prefix}", kind="test"
100100
)
101101
with pytest.raises(AssertionError):
102102
build_env.install_requirements(
103-
finder, [], prefix, f"installing in {prefix}"
103+
finder, [], prefix, f"installing in {prefix}", kind="test"
104104
)
105105

106106

@@ -131,7 +131,7 @@ def test_build_env_requirements_check(script: PipTestEnvironment) -> None:
131131
script,
132132
"""
133133
build_env.install_requirements(finder, ['foo', 'bar==3.0'], 'normal',
134-
'installing foo in normal')
134+
'installing foo in normal', kind="test")
135135
136136
r = build_env.check_requirements(['foo', 'bar', 'other'])
137137
assert r == (set(), {'other'}), repr(r)
@@ -148,9 +148,9 @@ def test_build_env_requirements_check(script: PipTestEnvironment) -> None:
148148
script,
149149
"""
150150
build_env.install_requirements(finder, ['foo', 'bar==3.0'], 'normal',
151-
'installing foo in normal')
151+
'installing foo in normal', kind="test")
152152
build_env.install_requirements(finder, ['bar==1.0'], 'overlay',
153-
'installing foo in overlay')
153+
'installing foo in overlay', kind="test")
154154
155155
r = build_env.check_requirements(['foo', 'bar', 'other'])
156156
assert r == (set(), {'other'}), repr(r)
@@ -172,9 +172,9 @@ def test_build_env_overlay_prefix_has_priority(script: PipTestEnvironment) -> No
172172
script,
173173
"""
174174
build_env.install_requirements(finder, ['pkg==2.0'], 'overlay',
175-
'installing pkg==2.0 in overlay')
175+
'installing pkg==2.0 in overlay', kind="test")
176176
build_env.install_requirements(finder, ['pkg==4.3'], 'normal',
177-
'installing pkg==4.3 in normal')
177+
'installing pkg==4.3 in normal', kind="test")
178178
""",
179179
"""
180180
print(__import__('pkg').__version__)

tests/unit/test_utils_subprocess.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ def test_call_subprocess_stdout_only(
163163
"-c",
164164
"import sys; sys.stdout.write('out\\n'); sys.stderr.write('err\\n')",
165165
],
166+
command_desc="test stdout_only",
166167
stdout_only=stdout_only,
167168
)
168169
assert out in expected
@@ -271,7 +272,11 @@ def test_debug_logging(
271272
"""
272273
log_level = DEBUG
273274
args, spinner = self.prepare_call(caplog, log_level)
274-
result = call_subprocess(args, spinner=spinner)
275+
result = call_subprocess(
276+
args,
277+
command_desc="test debug logging",
278+
spinner=spinner,
279+
)
275280

276281
expected = (
277282
["Hello", "world"],
@@ -301,7 +306,11 @@ def test_info_logging(
301306
"""
302307
log_level = INFO
303308
args, spinner = self.prepare_call(caplog, log_level)
304-
result = call_subprocess(args, spinner=spinner)
309+
result = call_subprocess(
310+
args,
311+
command_desc="test info logging",
312+
spinner=spinner,
313+
)
305314

306315
expected: Tuple[List[str], List[Tuple[str, int, str]]] = (
307316
["Hello", "world"],
@@ -331,7 +340,11 @@ def test_info_logging__subprocess_error(
331340
args, spinner = self.prepare_call(caplog, log_level, command=command)
332341

333342
with pytest.raises(InstallationSubprocessError) as exc:
334-
call_subprocess(args, spinner=spinner)
343+
call_subprocess(
344+
args,
345+
command_desc="test info logging with subprocess error",
346+
spinner=spinner,
347+
)
335348
result = None
336349
exc_message = str(exc.value)
337350
assert exc_message.startswith("Command errored out with exit status 1: ")
@@ -390,7 +403,12 @@ def test_info_logging_with_show_stdout_true(
390403
"""
391404
log_level = INFO
392405
args, spinner = self.prepare_call(caplog, log_level)
393-
result = call_subprocess(args, spinner=spinner, show_stdout=True)
406+
result = call_subprocess(
407+
args,
408+
command_desc="test info logging with show_stdout",
409+
spinner=spinner,
410+
show_stdout=True,
411+
)
394412

395413
expected = (
396414
["Hello", "world"],
@@ -456,6 +474,7 @@ def test_spinner_finish(
456474
try:
457475
call_subprocess(
458476
args,
477+
command_desc="spinner go spinny",
459478
show_stdout=show_stdout,
460479
extra_ok_returncodes=extra_ok_returncodes,
461480
spinner=spinner,
@@ -474,6 +493,7 @@ def test_closes_stdin(self) -> None:
474493
call_subprocess(
475494
[sys.executable, "-c", "input()"],
476495
show_stdout=True,
496+
command_desc="stdin reader",
477497
)
478498

479499

@@ -487,6 +507,7 @@ def test_unicode_decode_error(caplog: pytest.LogCaptureFixture) -> None:
487507
"-c",
488508
"import sys; sys.stdout.buffer.write(b'\\xff')",
489509
],
510+
command_desc="invalid decode output",
490511
show_stdout=True,
491512
)
492513

0 commit comments

Comments
 (0)