Skip to content

Commit f32e196

Browse files
committed
Raise CycleError each time prepare() is called
1 parent 60e0004 commit f32e196

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

Lib/graphlib.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,17 @@ def prepare(self):
9090
still be used to obtain as many nodes as possible until cycles block more
9191
progress. After a call to this function, the graph cannot be modified and
9292
therefore no more nodes can be added using "add".
93+
94+
Raise ValueError if nodes have already been passed out of the sorter.
95+
9396
"""
94-
if self._ready_nodes is not None:
95-
if self._npassedout > 0:
96-
raise ValueError("cannot prepare() after starting sort")
97-
return
97+
if self._npassedout > 0:
98+
raise ValueError("cannot prepare() after starting sort")
9899

99-
self._ready_nodes = [
100-
i.node for i in self._node2info.values() if i.npredecessors == 0
101-
]
100+
if self._ready_nodes is None:
101+
self._ready_nodes = [
102+
i.node for i in self._node2info.values() if i.npredecessors == 0
103+
]
102104
# ready_nodes is set before we look for cycles on purpose:
103105
# if the user wants to catch the CycleError, that's fine,
104106
# they can continue using the instance to grab as many

Lib/test/test_graphlib.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ def test_prepare_after_pass_out(self):
149149
with self.assertRaisesRegex(ValueError, r"cannot prepare\(\) after starting sort"):
150150
ts.prepare()
151151

152+
def test_prepare_cycleerror_each_time(self):
153+
ts = graphlib.TopologicalSorter({'a': 'b', 'b': 'a'})
154+
for attempt in range(1, 4):
155+
with self.assertRaises(graphlib.CycleError, msg=f"{attempt=}"):
156+
ts.prepare()
157+
152158
def test_invalid_nodes_in_done(self):
153159
ts = graphlib.TopologicalSorter()
154160
ts.add(1, 2, 3, 4)

0 commit comments

Comments
 (0)