19
def topo_sort(nodes, pairs):
19
from bzrlib.errors import GraphCycleError
20
22
"""Topological sort a graph.
22
nodes -- list of all nodes in the graph
23
pairs -- list of (a, b) pairs, meaning a is a predecessor of b.
24
both a and b must occur in the node list.
24
graph -- sequence of pairs of node->parents_list.
26
The result is a list of node names, such that all parents come before
29
Nodes at the same depth are returned in sorted order.
26
31
node identifiers can be any hashable object, and are typically strings.
28
33
parents = {} # node -> list of parents
29
34
children = {} # node -> list of children
35
for node, node_parents in graph:
36
assert node not in parents, \
37
('node %r repeated in graph' % node)
38
parents[node] = set(node_parents)
39
if node not in children:
40
children[node] = set()
41
for parent in node_parents:
42
if parent in children:
43
children[parent].add(node)
45
children[parent] = set([node])
38
48
# find nodes with no parents, and take them now
39
ready = [n for n in parents if len(parents[n]) == 0]
41
raise AssertionError('cycle in graph?')
49
no_parents = [n for n in parents if len(parents[n]) == 0]
52
raise GraphCycleError(parents)
44
55
for child in children[n]:
45
56
assert n in parents[child]