def topological_sort(source): pending = [(name, set(deps)) for name, deps in source] emitted = [] while pending: next_pending = [] next_emitted = [] for entry in pending: name, deps = entry deps.difference_update(set((name,)), emitted) # <-- pop self from dep, req Py2.6 if deps: next_pending.append(entry) else: yield name emitted.append(name) # <-- not required, but preserves original order next_emitted.append(name) if not next_emitted: raise ValueError("cyclic dependancy detected: %s %r" % (name, (next_pending,))) pending = next_pending emitted = next_emitted return emitted def sort_libs_by_dependencies(selected_libs): # no need for sorting in case of only one lib if len(selected_libs) < 2: return selected_libs lib_names = [] for lib in selected_libs: lib_names.append(lib['name']) deplist = [] for lib in selected_libs: name = lib['name'] # only sort after dependencies that are actually present to avoid cyclic dependencies deps = [] for dep in lib['dependencies'].split(','): if dep in lib_names: deps.append(dep) dependencies = set(deps) if dependencies == {''}: dependencies = {} deplist.append([name, dependencies]) sorted_deplist = topological_sort(deplist) sorted = [] for entry in sorted_deplist: for lib in selected_libs: if lib['name'] == entry: sorted.append(lib) return sorted