Skip to content

Commit 330d749

Browse files
committed
Display dependency chain on each Collecting line
This tremendously helps understand why a package is being fetched and can help investigate and fix dependency resolver backtracking issues when incoherent constraints/package sets are provided or when new versions of a package trigger a completely different backtracking strategy, leading to very hard to debug situations.
1 parent bd54161 commit 330d749

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

news/C0DAB099-D9CB-438B-9091-146533DD4741.trivial.rst

Whitespace-only changes.

src/pip/_internal/operations/prepare.py

+10
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,16 @@ def _log_preparing_link(self, req: InstallRequirement) -> None:
269269
message = "Collecting %s"
270270
information = str(req.req or req)
271271

272+
# If we used req.req, inject requirement source if available (this
273+
# would already be included if we used req directly)
274+
if req.req and req.comes_from:
275+
if isinstance(req.comes_from, str):
276+
comes_from: Optional[str] = req.comes_from
277+
else:
278+
comes_from = req.comes_from.from_path()
279+
if comes_from:
280+
information += f" (from {comes_from})"
281+
272282
if (message, information) != self._previous_requirement_header:
273283
self._previous_requirement_header = (message, information)
274284
logger.info(message, information)

tests/functional/test_install.py

+58
Original file line numberDiff line numberDiff line change
@@ -2344,3 +2344,61 @@ def test_install_8559_wheel_package_present(
23442344
allow_stderr_warning=False,
23452345
)
23462346
assert DEPRECATION_MSG_PREFIX not in result.stderr
2347+
2348+
2349+
def test_install_pip_prints_req_chain_local(script: PipTestEnvironment) -> None:
2350+
"""
2351+
Test installing a local package with a dependency and check that the
2352+
dependency chain is reported.
2353+
"""
2354+
2355+
req_path = script.scratch_path.joinpath("requirements.txt")
2356+
req_path.write_text("base==0.1.0")
2357+
2358+
create_basic_wheel_for_package(
2359+
script,
2360+
"base",
2361+
"0.1.0",
2362+
depends=["dep"],
2363+
)
2364+
dep_path = create_basic_wheel_for_package(
2365+
script,
2366+
"dep",
2367+
"0.1.0",
2368+
)
2369+
2370+
result = script.pip(
2371+
"install",
2372+
"--no-cache-dir",
2373+
"--no-index",
2374+
"--find-links",
2375+
script.scratch_path,
2376+
"-r",
2377+
req_path,
2378+
)
2379+
assert_re_match(
2380+
rf"Processing .*{os.path.basename(dep_path)} "
2381+
rf"\(from base==0.1.0->-r {req_path} \(line 1\)\)",
2382+
result.stdout,
2383+
)
2384+
2385+
2386+
@pytest.mark.network
2387+
def test_install_pip_prints_req_chain_pypi(script: PipTestEnvironment) -> None:
2388+
"""
2389+
Test installing a package with a dependency from PyPI and check that the
2390+
dependency chain is reported.
2391+
"""
2392+
req_path = script.scratch_path.joinpath("requirements.txt")
2393+
req_path.write_text("Paste[openid]==1.7.5.1")
2394+
2395+
result = script.pip(
2396+
"install",
2397+
"-r",
2398+
req_path,
2399+
)
2400+
2401+
assert (
2402+
f"Collecting python-openid "
2403+
f"(from Paste[openid]==1.7.5.1->-r {req_path} (line 1))" in result.stdout
2404+
)

0 commit comments

Comments
 (0)