Skip to content

Commit a9ecf42

Browse files
committed
Optimize init into a single pass
1 parent 6f1249a commit a9ecf42

1 file changed

Lines changed: 20 additions & 12 deletions

File tree

mypy/graph_utils.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,25 +137,33 @@ class topsort2(Iterator[set[T]]):
137137
"""
138138

139139
def __init__(self, data: dict[T, set[T]]) -> None:
140-
for k, v in data.items():
141-
v.discard(k) # Ignore self dependencies.
142-
for item in set.union(*data.values()) - set(data.keys()):
143-
data[item] = set()
144-
145-
# Build reverse adjacency list and in-degree counts.
140+
# Single pass: remove self-deps, build reverse adjacency list,
141+
# compute in-degree counts, detect orphans, and find initial ready set.
146142
in_degree: dict[T, int] = {}
147143
rev: dict[T, list[T]] = {}
148-
for item in data:
149-
in_degree[item] = len(data[item])
150-
rev[item] = []
144+
ready: set[T] = set()
151145
for item, deps in data.items():
146+
deps.discard(item) # Ignore self dependencies.
147+
deg = len(deps)
148+
in_degree[item] = deg
149+
if deg == 0:
150+
ready.add(item)
151+
if item not in rev:
152+
rev[item] = []
152153
for dep in deps:
153-
rev[dep].append(item)
154+
if dep in rev:
155+
rev[dep].append(item)
156+
else:
157+
rev[dep] = [item]
158+
if dep not in data:
159+
# Orphan: appears as dependency but has no entry in data.
160+
in_degree[dep] = 0
161+
ready.add(dep)
154162

155163
self.in_degree = in_degree
156164
self.rev = rev
157-
self.ready = {item for item, deg in in_degree.items() if deg == 0}
158-
self.remaining = len(in_degree) - len(self.ready)
165+
self.ready = ready
166+
self.remaining = len(in_degree) - len(ready)
159167

160168
def __iter__(self) -> Iterator[set[T]]:
161169
return self

0 commit comments

Comments
 (0)