pip: don't crash on cycles, fix them instead

pip does allow cycles and they are common in larger dependency trees. Instead of crashing on them, we should allow the user to deal with them.

As a result of this, it can happen that during the installation of individual dependencies, some dep(s) might be missing, which then can be fixed by including them manually or with a `--no-deps`
This commit is contained in:
DavHau 2023-08-22 12:39:14 +02:00
parent 5724c1e389
commit 3dd23864cb
2 changed files with 25 additions and 12 deletions

View File

@ -143,14 +143,6 @@ def evaluate_requirements(env, reqs, dependencies, root_name, extras, seen):
requirements to save space in the file.
A circuit breaker is included to avoid infinite recursion in nix.
"""
if root_name in seen:
print(
f"fatal: cycle detected: {root_name} ({' '.join(seen)})",
file=sys.stderr, # noqa: E501
)
sys.exit(1)
# we copy "seen", because we want to track cycles per
# tree-branch and the original would be visible for all branches.
seen = seen.copy()
seen.append(root_name)
@ -160,10 +152,11 @@ def evaluate_requirements(env, reqs, dependencies, root_name, extras, seen):
for req in reqs[root_name]:
if (not req.marker) or evaluate_extras(req, extras, env):
req_name = canonicalize_name(req.name)
dependencies[root_name].add(req_name)
evaluate_requirements(
env, reqs, dependencies, req_name, req.extras, seen
) # noqa: 501
if req_name not in seen:
dependencies[root_name].add(req_name)
evaluate_requirements(
env, reqs, dependencies, req_name, req.extras, seen
) # noqa: 501
return dependencies

View File

@ -68,3 +68,23 @@ def test_platform_mismatch():
seen=[],
)
assert result == dict(root_package=set())
def test_cycle():
result = l.evaluate_requirements(
env={},
reqs=dict(
root_package={Requirement("foo")},
foo={Requirement("bar")},
bar={Requirement("foo")},
),
dependencies=dict(),
root_name="root_package",
extras=None,
seen=[],
)
assert result == dict(
root_package={"foo"},
foo={"bar"},
bar=set(),
)