libinstaller/lib/sort.py

52 lines
1.6 KiB
Python

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