@@ -95,22 +95,35 @@ def get_dep_tree(package_spec, verbose):
9595
9696def 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