41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
# -*- coding=utf-8 -*-
|
|
|
|
from __future__ import absolute_import, unicode_literals
|
|
|
|
|
|
def _trace_visit_vertex(graph, current, target, visited, path, paths):
|
|
if current == target:
|
|
paths.append(path)
|
|
return
|
|
for v in graph.iter_children(current):
|
|
if v == current or v in visited:
|
|
continue
|
|
next_path = path + [current]
|
|
next_visited = visited | {current}
|
|
_trace_visit_vertex(graph, v, target, next_visited, next_path, paths)
|
|
|
|
|
|
def trace_graph(graph):
|
|
"""Build a collection of "traces" for each package.
|
|
|
|
A trace is a list of names that eventually leads to the package. For
|
|
example, if A and B are root dependencies, A depends on C and D, B
|
|
depends on C, and C depends on D, the return value would be like::
|
|
|
|
{
|
|
None: [],
|
|
"A": [None],
|
|
"B": [None],
|
|
"C": [[None, "A"], [None, "B"]],
|
|
"D": [[None, "B", "C"], [None, "A"]],
|
|
}
|
|
"""
|
|
result = {None: []}
|
|
for vertex in graph:
|
|
result[vertex] = []
|
|
for root in graph.iter_children(None):
|
|
paths = []
|
|
_trace_visit_vertex(graph, root, vertex, {None}, [None], paths)
|
|
result[vertex].extend(paths)
|
|
return result
|