Skip to content

Commit 1fe1099

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 e58a8a5 commit 1fe1099

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-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

+51
Original file line numberDiff line numberDiff line change
@@ -2243,3 +2243,54 @@ def test_install_logs_pip_version_in_debug(
22432243
result = script.pip("install", "-v", fake_package)
22442244
pattern = "Using pip .* from .*"
22452245
assert_re_match(pattern, result.stdout)
2246+
2247+
2248+
def test_install_pip_prints_req_chain_local(script: PipTestEnvironment) -> None:
2249+
"""
2250+
Test installing a local package with a dependency and check that the
2251+
dependency chain is reported.
2252+
"""
2253+
2254+
req_path = script.scratch_path.joinpath("requirements.txt")
2255+
req_path.write_text("base==0.1.0")
2256+
2257+
create_basic_wheel_for_package(
2258+
script,
2259+
"base",
2260+
"0.1.0",
2261+
depends=["dep"],
2262+
)
2263+
dep_path = create_basic_wheel_for_package(
2264+
script,
2265+
"dep",
2266+
"0.1.0",
2267+
)
2268+
2269+
result = script.pip(
2270+
"install",
2271+
"--no-cache-dir",
2272+
"--no-index",
2273+
"--find-links",
2274+
script.scratch_path,
2275+
"-r",
2276+
req_path,
2277+
)
2278+
assert f"Processing ./{os.path.basename(dep_path)} (from base==0.1.0->-r {req_path} (line 1))" in result.stdout
2279+
2280+
2281+
@pytest.mark.network
2282+
def test_install_pip_prints_req_chain_pypi(script: PipTestEnvironment) -> None:
2283+
"""
2284+
Test installing a package with a dependency from PyPI and check that the
2285+
dependency chain is reported.
2286+
"""
2287+
req_path = script.scratch_path.joinpath("requirements.txt")
2288+
req_path.write_text("Paste[openid]==1.7.5.1")
2289+
2290+
result = script.pip(
2291+
"install",
2292+
"-r",
2293+
req_path,
2294+
)
2295+
2296+
assert f"Collecting python-openid (from Paste[openid]==1.7.5.1->-r {req_path} (line 1))" in result.stdout

0 commit comments

Comments
 (0)