-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathfind_cycles.py
More file actions
82 lines (66 loc) · 2.1 KB
/
find_cycles.py
File metadata and controls
82 lines (66 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import yaml
from collections import defaultdict
import sys
def load_metadata(path):
with open(path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
def build_dependency_graph(metadata):
graph = defaultdict(list)
for key, value in metadata.items():
for dep in value.get("dependencies", []):
graph[key].append(dep)
return graph
def build_reverse_graph(graph):
reverse = defaultdict(list)
for node, deps in graph.items():
for dep in deps:
reverse[dep].append(node)
return reverse
def find_cycles(graph):
visited = set()
cycles = []
def dfs(node, path):
if node in path:
cycle_start = path.index(node)
cycles.append(path[cycle_start:] + [node])
return
if node in visited:
return
visited.add(node)
path.append(node)
for dep in graph.get(node, []):
dfs(dep, path)
path.pop()
for node in graph:
dfs(node, [])
return cycles
def print_graph(graph, title):
print(f"\n{title}")
for k, v in graph.items():
print(f" {k}: {v}")
def main():
if len(sys.argv) < 2:
print("Usage: python find_cycles.py <metadata.yml>")
sys.exit(1)
metadata_path = sys.argv[1]
metadata = load_metadata(metadata_path)
graph = build_dependency_graph(metadata)
reverse_graph = build_reverse_graph(graph)
print_graph(graph, "Dependency graph (who each node depends on):")
print_graph(reverse_graph, "Reverse dependency graph (who depends on each node):")
cycles = find_cycles(graph)
rev_cycles = find_cycles(reverse_graph)
if cycles:
print("\nCycles found in dependency graph:")
for cycle in cycles:
print(" -> ".join(cycle))
else:
print("\nNo cycles found in dependency graph.")
if rev_cycles:
print("\nCycles found in reverse dependency graph:")
for cycle in rev_cycles:
print(" -> ".join(cycle))
else:
print("\nNo cycles found in reverse dependency graph.")
if __name__ == "__main__":
main()