@@ -11,6 +11,23 @@ class NodeType(Enum):
11
11
TASK = 2
12
12
13
13
14
+ class CycleFoundException (Exception ):
15
+ """Raised when there is a cycle when drawing the call tree."""
16
+
17
+ def __init__ (self , cycles , id2name ):
18
+ super ().__init__ ()
19
+ self .cycles = cycles
20
+ self .id2name = id2name
21
+
22
+ def __str__ (self ):
23
+ for c in self .cycles :
24
+ names = " → " .join (self .id2name .get (tid , hex (tid )) for tid in c )
25
+ return (
26
+ "ERROR: await-graph contains cycles – cannot print a tree!\n "
27
+ f"cycle: { names } "
28
+ )
29
+
30
+
14
31
# ─── indexing helpers ───────────────────────────────────────────
15
32
def _index (result ):
16
33
id2name , awaits = {}, []
@@ -56,9 +73,9 @@ def _cor_node(parent_key, frame_name):
56
73
57
74
58
75
def _roots (id2label , children ):
59
- roots = [n for n , lbl in id2label .items () if lbl == "Task-1" ]
60
- if roots :
61
- return roots
76
+ # roots = [n for n, lbl in id2label.items() if lbl == "Task-1"]
77
+ # if roots:
78
+ # return roots
62
79
all_children = {c for kids in children .values () for c in kids }
63
80
return [n for n in id2label if n not in all_children ]
64
81
@@ -80,7 +97,7 @@ def _find_cycles(graph):
80
97
empty list if the graph is acyclic.
81
98
"""
82
99
WHITE , GREY , BLACK = 0 , 1 , 2
83
- color = { n : WHITE for n in graph }
100
+ color = defaultdict ( lambda : WHITE )
84
101
path , cycles = [], []
85
102
86
103
def dfs (v ):
@@ -108,6 +125,10 @@ def print_async_tree(result, task_emoji="(T)", cor_emoji="", printer=print):
108
125
prefixing tasks with *task_emoji* and coroutine frames with *cor_emoji*.
109
126
"""
110
127
id2name , awaits = _index (result )
128
+ g = _task_graph (awaits )
129
+ cycles = _find_cycles (g )
130
+ if cycles :
131
+ raise CycleFoundException (cycles , id2name )
111
132
labels , children = _build_tree (id2name , awaits )
112
133
113
134
def pretty (node ):
@@ -166,20 +187,9 @@ def build_task_table(result):
166
187
print (f"Error retrieving tasks: { e } " )
167
188
sys .exit (1 )
168
189
190
+ print (tasks )
169
191
if args .tree :
170
192
# Print the async call tree
171
- id2name , awaits = _index (tasks )
172
- g = _task_graph (awaits )
173
- cycles = _find_cycles (g )
174
-
175
- if cycles :
176
- print ("ERROR: await-graph contains cycles – cannot print a tree!\n " )
177
- for c in cycles :
178
- # pretty-print task names instead of bare ids
179
- names = " → " .join (id2name .get (tid , hex (tid )) for tid in c )
180
- print (f" cycle: { names } " )
181
- sys .exit (1 )
182
-
183
193
result = print_async_tree (tasks )
184
194
for tree in result :
185
195
print ("\n " .join (tree ))
0 commit comments