Skip to content

Commit

Permalink
Display dependency chain on each Collecting line
Browse files Browse the repository at this point in the history
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.
iXce committed Feb 24, 2023
1 parent 5e20a7b commit c546c99
Showing 3 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions news/11169.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Display dependency chain on each Collecting/Processing log line.
10 changes: 10 additions & 0 deletions src/pip/_internal/operations/prepare.py
Original file line number Diff line number Diff line change
@@ -270,6 +270,16 @@ def _log_preparing_link(self, req: InstallRequirement) -> None:
message = "Collecting %s"
information = str(req.req or req)

# If we used req.req, inject requirement source if available (this
# would already be included if we used req directly)
if req.req and req.comes_from:
if isinstance(req.comes_from, str):
comes_from: Optional[str] = req.comes_from
else:
comes_from = req.comes_from.from_path()
if comes_from:
information += f" (from {comes_from})"

if (message, information) != self._previous_requirement_header:
self._previous_requirement_header = (message, information)
logger.info(message, information)
58 changes: 58 additions & 0 deletions tests/functional/test_install.py
Original file line number Diff line number Diff line change
@@ -2393,3 +2393,61 @@ def find_distributions(self, context=None):
result = script.pip("install", "example")

assert "Requirement already satisfied: example in <memory>" in result.stdout


def test_install_pip_prints_req_chain_local(script: PipTestEnvironment) -> None:
"""
Test installing a local package with a dependency and check that the
dependency chain is reported.
"""

req_path = script.scratch_path.joinpath("requirements.txt")
req_path.write_text("base==0.1.0")

create_basic_wheel_for_package(
script,
"base",
"0.1.0",
depends=["dep"],
)
dep_path = create_basic_wheel_for_package(
script,
"dep",
"0.1.0",
)

result = script.pip(
"install",
"--no-cache-dir",
"--no-index",
"--find-links",
script.scratch_path,
"-r",
req_path,
)
assert_re_match(
rf"Processing .*{re.escape(os.path.basename(dep_path))} "
rf"\(from base==0.1.0->-r {re.escape(str(req_path))} \(line 1\)\)",
result.stdout,
)


@pytest.mark.network
def test_install_pip_prints_req_chain_pypi(script: PipTestEnvironment) -> None:
"""
Test installing a package with a dependency from PyPI and check that the
dependency chain is reported.
"""
req_path = script.scratch_path.joinpath("requirements.txt")
req_path.write_text("Paste[openid]==1.7.5.1")

result = script.pip(
"install",
"-r",
req_path,
)

assert (
f"Collecting python-openid "
f"(from Paste[openid]==1.7.5.1->-r {req_path} (line 1))" in result.stdout
)

0 comments on commit c546c99

Please sign in to comment.