Skip to content

Commit d9cffd9

Browse files
authored
Merge branch 'main' into pythongh-93376
2 parents 70ae9e3 + c1b42db commit d9cffd9

File tree

8 files changed

+57
-6
lines changed

8 files changed

+57
-6
lines changed

Doc/c-api/monitoring.rst

+12
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,15 @@ would typically correspond to a python function.
196196
.. c:function:: int PyMonitoring_ExitScope(void)
197197
198198
Exit the last scope that was entered with :c:func:`!PyMonitoring_EnterScope`.
199+
200+
201+
.. c:function:: int PY_MONITORING_IS_INSTRUMENTED_EVENT(uint8_t ev)
202+
203+
Return true if the event corresponding to the event ID *ev* is
204+
a :ref:`local event <monitoring-event-local>`.
205+
206+
.. versionadded:: 3.13
207+
208+
.. deprecated:: next
209+
210+
This function is :term:`soft deprecated`.

Doc/library/graphlib.rst

+8
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@
106106
function, the graph cannot be modified, and therefore no more nodes can be
107107
added using :meth:`~TopologicalSorter.add`.
108108

109+
A :exc:`ValueError` will be raised if the sort has been started by
110+
:meth:`~.static_order` or :meth:`~.get_ready`.
111+
112+
.. versionchanged:: next
113+
114+
``prepare()`` can now be called more than once as long as the sort has
115+
not started. Previously this raised :exc:`ValueError`.
116+
109117
.. method:: is_active()
110118

111119
Returns ``True`` if more progress can be made and ``False`` otherwise.

Doc/library/sys.monitoring.rst

+2
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ events, use the expression ``PY_RETURN | PY_START``.
173173

174174
Events are divided into three groups:
175175

176+
.. _monitoring-event-local:
177+
176178
Local events
177179
''''''''''''
178180

Doc/whatsnew/3.14.rst

+9
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,15 @@ getopt
607607
* Add support for returning intermixed options and non-option arguments in order.
608608
(Contributed by Serhiy Storchaka in :gh:`126390`.)
609609

610+
611+
graphlib
612+
--------
613+
614+
* Allow :meth:`graphlib.TopologicalSorter.prepare` to be called more than once
615+
as long as sorting has not started.
616+
(Contributed by Daniel Pope in :gh:`130914`)
617+
618+
610619
http
611620
----
612621

Lib/graphlib.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -90,13 +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-
raise ValueError("cannot prepare() more than once")
97+
if self._npassedout > 0:
98+
raise ValueError("cannot prepare() after starting sort")
9699

97-
self._ready_nodes = [
98-
i.node for i in self._node2info.values() if i.npredecessors == 0
99-
]
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+
]
100104
# ready_nodes is set before we look for cycles on purpose:
101105
# if the user wants to catch the CycleError, that's fine,
102106
# they can continue using the instance to grab as many

Lib/test/test_graphlib.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,21 @@ def test_calls_before_prepare(self):
140140
def test_prepare_multiple_times(self):
141141
ts = graphlib.TopologicalSorter()
142142
ts.prepare()
143-
with self.assertRaisesRegex(ValueError, r"cannot prepare\(\) more than once"):
143+
ts.prepare()
144+
145+
def test_prepare_after_pass_out(self):
146+
ts = graphlib.TopologicalSorter({'a': 'bc'})
147+
ts.prepare()
148+
self.assertEqual(set(ts.get_ready()), {'b', 'c'})
149+
with self.assertRaisesRegex(ValueError, r"cannot prepare\(\) after starting sort"):
144150
ts.prepare()
145151

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+
146158
def test_invalid_nodes_in_done(self):
147159
ts = graphlib.TopologicalSorter()
148160
ts.add(1, 2, 3, 4)

Misc/ACKS

+1
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,7 @@ Michael Pomraning
14831483
Martin Pool
14841484
Iustin Pop
14851485
Claudiu Popa
1486+
Daniel Pope
14861487
Nick Pope
14871488
John Popplewell
14881489
Matheus Vieira Portela
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Allow :meth:`graphlib.TopologicalSorter.prepare` to be called more than once
2+
as long as sorting has not started.
3+
Patch by Daniel Pope.

0 commit comments

Comments
 (0)