(self, awaited_info_list)
| 127 | yield frames, thread_id |
| 128 | |
| 129 | def _build_task_graph(self, awaited_info_list): |
| 130 | task_map = {} |
| 131 | child_to_parent = {} # Maps child_id -> (selected_parent_id, parent_count) |
| 132 | all_task_ids = set() |
| 133 | all_parent_ids = set() # Track ALL parent IDs for leaf detection |
| 134 | |
| 135 | for awaited_info in awaited_info_list: |
| 136 | thread_id = awaited_info.thread_id |
| 137 | for task_info in awaited_info.awaited_by: |
| 138 | task_id = task_info.task_id |
| 139 | task_map[task_id] = (task_info, thread_id) |
| 140 | all_task_ids.add(task_id) |
| 141 | |
| 142 | # Pre-compute selected parent and count for optimization |
| 143 | if task_info.awaited_by: |
| 144 | parent_ids = [p.task_name for p in task_info.awaited_by] |
| 145 | parent_count = len(parent_ids) |
| 146 | # Track ALL parents for leaf detection |
| 147 | all_parent_ids.update(parent_ids) |
| 148 | # Use min() for O(n) instead of sorted()[0] which is O(n log n) |
| 149 | selected_parent = min(parent_ids) if parent_count > 1 else parent_ids[0] |
| 150 | child_to_parent[task_id] = (selected_parent, parent_count) |
| 151 | |
| 152 | return task_map, child_to_parent, all_task_ids, all_parent_ids |
| 153 | |
| 154 | def _find_leaf_tasks(self, all_task_ids, all_parent_ids): |
| 155 | # Leaves are tasks that are not parents of any other task |
no test coverage detected