Skip to content

Commit 03a7f3b

Browse files
authored
Merge pull request #4633 from Flamefire/findpythondeps
fix `findPythonDeps.py` script for cyclic dependencies
2 parents 36db0c7 + 84786cb commit 03a7f3b

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

easybuild/scripts/findPythonDeps.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,35 @@ def get_dep_tree(package_spec, verbose):
9595

9696
def find_deps(pkgs, dep_tree):
9797
"""Recursively resolve dependencies of the given package(s) and return them"""
98+
MAX_PACKAGES = 1000
9899
res = []
99-
for orig_pkg in pkgs:
100-
pkg = canonicalize_name(orig_pkg)
101-
matching_entries = [entry for entry in dep_tree
102-
if pkg in (entry['package']['package_name'], entry['package']['key'])]
103-
if not matching_entries:
100+
next_pkgs = set(pkgs)
101+
# Don't check any package multiple times to avoid infinite recursion
102+
seen_pkgs = set()
103+
count = 0
104+
while next_pkgs:
105+
cur_pkgs = next_pkgs - seen_pkgs
106+
seen_pkgs.update(cur_pkgs)
107+
next_pkgs = set()
108+
for orig_pkg in cur_pkgs:
109+
count += 1
110+
if count > MAX_PACKAGES:
111+
raise RuntimeError("Aborting after checking %s packages. Possibly cycle detected!" % MAX_PACKAGES)
112+
pkg = canonicalize_name(orig_pkg)
104113
matching_entries = [entry for entry in dep_tree
105-
if orig_pkg in (entry['package']['package_name'], entry['package']['key'])]
106-
if not matching_entries:
107-
raise RuntimeError("Found no installed package for '%s' in %s" % (pkg, dep_tree))
108-
if len(matching_entries) > 1:
109-
raise RuntimeError("Found multiple installed packages for '%s' in %s" % (pkg, dep_tree))
110-
entry = matching_entries[0]
111-
res.append((entry['package']['package_name'], entry['package']['installed_version']))
112-
deps = (dep['package_name'] for dep in entry['dependencies'])
113-
res.extend(find_deps(deps, dep_tree))
114+
if pkg in (entry['package']['package_name'], entry['package']['key'])]
115+
if not matching_entries:
116+
matching_entries = [entry for entry in dep_tree
117+
if orig_pkg in (entry['package']['package_name'], entry['package']['key'])]
118+
if not matching_entries:
119+
raise RuntimeError("Found no installed package for '%s' in %s" % (pkg, dep_tree))
120+
if len(matching_entries) > 1:
121+
raise RuntimeError("Found multiple installed packages for '%s' in %s" % (pkg, dep_tree))
122+
entry = matching_entries[0]
123+
res.append((entry['package']['package_name'], entry['package']['installed_version']))
124+
# Add dependencies to list of packages to check next
125+
# Could call this function recursively but that might exceed the max recursion depth
126+
next_pkgs.update(dep['package_name'] for dep in entry['dependencies'])
114127
return res
115128

116129

0 commit comments

Comments
 (0)