Skip to content

Commit d571c90

Browse files
authored
Merge branch 'main' into morsel-js-output
2 parents b8dd6e4 + 59b41c8 commit d571c90

39 files changed

Lines changed: 1020 additions & 426 deletions

Doc/howto/enum.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ Equality comparisons are defined though::
371371
>>> Color.BLUE == Color.BLUE
372372
True
373373

374-
Comparisons against non-enumeration values will always compare not equal
374+
Equality comparisons against non-enumeration values will always return ``False``
375375
(again, :class:`IntEnum` was explicitly designed to behave differently, see
376376
below)::
377377

Doc/library/itertools.rst

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
833833
from collections import Counter, deque
834834
from contextlib import suppress
835835
from functools import reduce
836+
from heapq import heappush, heappushpop, heappush_max, heappushpop_max
836837
from math import comb, isqrt, prod, sumprod
837838
from operator import getitem, is_not, itemgetter, mul, neg, truediv
838839

@@ -848,11 +849,6 @@ and :term:`generators <generator>` which incur interpreter overhead.
848849
# prepend(1, [2, 3, 4]) → 1 2 3 4
849850
return chain([value], iterable)
850851

851-
def running_mean(iterable):
852-
"Yield the average of all values seen so far."
853-
# running_mean([8.5, 9.5, 7.5, 6.5]) → 8.5 9.0 8.5 8.0
854-
return map(truediv, accumulate(iterable), count(1))
855-
856852
def repeatfunc(function, times=None, *args):
857853
"Repeat calls to a function with specified arguments."
858854
if times is None:
@@ -1150,6 +1146,49 @@ and :term:`generators <generator>` which incur interpreter overhead.
11501146
return n
11511147

11521148

1149+
# ==== Running statistics ====
1150+
1151+
def running_mean(iterable):
1152+
"Average of values seen so far."
1153+
# running_mean([37, 33, 38, 28]) → 37 35 36 34
1154+
return map(truediv, accumulate(iterable), count(1))
1155+
1156+
def running_min(iterable):
1157+
"Smallest of values seen so far."
1158+
# running_min([37, 33, 38, 28]) → 37 33 33 28
1159+
return accumulate(iterable, func=min)
1160+
1161+
def running_max(iterable):
1162+
"Largest of values seen so far."
1163+
# running_max([37, 33, 38, 28]) → 37 37 38 38
1164+
return accumulate(iterable, func=max)
1165+
1166+
def running_median(iterable):
1167+
"Median of values seen so far."
1168+
# running_median([37, 33, 38, 28]) → 37 35 37 35
1169+
read = iter(iterable).__next__
1170+
lo = [] # max-heap
1171+
hi = [] # min-heap the same size as or one smaller than lo
1172+
with suppress(StopIteration):
1173+
while True:
1174+
heappush_max(lo, heappushpop(hi, read()))
1175+
yield lo[0]
1176+
heappush(hi, heappushpop_max(lo, read()))
1177+
yield (lo[0] + hi[0]) / 2
1178+
1179+
def running_statistics(iterable):
1180+
"Aggregate statistics for values seen so far."
1181+
# Generate tuples: (size, minimum, median, maximum, mean)
1182+
t0, t1, t2, t3 = tee(iterable, 4)
1183+
return zip(
1184+
count(1),
1185+
running_min(t0),
1186+
running_median(t1),
1187+
running_max(t2),
1188+
running_mean(t3),
1189+
)
1190+
1191+
11531192
.. doctest::
11541193
:hide:
11551194

@@ -1226,10 +1265,6 @@ and :term:`generators <generator>` which incur interpreter overhead.
12261265
[(0, 'a'), (1, 'b'), (2, 'c')]
12271266

12281267

1229-
>>> list(running_mean([8.5, 9.5, 7.5, 6.5]))
1230-
[8.5, 9.0, 8.5, 8.0]
1231-
1232-
12331268
>>> for _ in loops(5):
12341269
... print('hi')
12351270
...
@@ -1789,6 +1824,28 @@ and :term:`generators <generator>` which incur interpreter overhead.
17891824
True
17901825

17911826

1827+
>>> list(running_mean([8.5, 9.5, 7.5, 6.5]))
1828+
[8.5, 9.0, 8.5, 8.0]
1829+
>>> list(running_mean([37, 33, 38, 28]))
1830+
[37.0, 35.0, 36.0, 34.0]
1831+
1832+
1833+
>>> list(running_min([37, 33, 38, 28]))
1834+
[37, 33, 33, 28]
1835+
1836+
1837+
>>> list(running_max([37, 33, 38, 28]))
1838+
[37, 37, 38, 38]
1839+
1840+
1841+
>>> list(running_median([37, 33, 38, 28]))
1842+
[37, 35.0, 37, 35.0]
1843+
1844+
1845+
>>> list(running_statistics([37, 33, 38, 28]))
1846+
[(1, 37, 37, 37, 37.0), (2, 33, 35.0, 37, 35.0), (3, 33, 37, 38, 36.0), (4, 28, 35.0, 38, 34.0)]
1847+
1848+
17921849
.. testcode::
17931850
:hide:
17941851

Doc/library/sys.monitoring.rst

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ Local events
180180
''''''''''''
181181

182182
Local events are associated with normal execution of the program and happen
183-
at clearly defined locations. All local events can be disabled.
184-
The local events are:
183+
at clearly defined locations. All local events can be disabled
184+
per location. The local events are:
185185

186186
* :monitoring-event:`PY_START`
187187
* :monitoring-event:`PY_RESUME`
@@ -205,6 +205,8 @@ Using :monitoring-event:`BRANCH_LEFT` and :monitoring-event:`BRANCH_RIGHT`
205205
events will give much better performance as they can be disabled
206206
independently.
207207

208+
.. _monitoring-ancillary-events:
209+
208210
Ancillary events
209211
''''''''''''''''
210212

@@ -226,14 +228,20 @@ Other events
226228
''''''''''''
227229

228230
Other events are not necessarily tied to a specific location in the
229-
program and cannot be individually disabled via :data:`DISABLE`.
231+
program and cannot be individually disabled per location.
230232

231233
The other events that can be monitored are:
232234

233235
* :monitoring-event:`PY_THROW`
234236
* :monitoring-event:`PY_UNWIND`
235237
* :monitoring-event:`RAISE`
236238
* :monitoring-event:`EXCEPTION_HANDLED`
239+
* :monitoring-event:`RERAISE`
240+
241+
.. versionchanged:: 3.15
242+
Other events can now be turned on and disabled on a per code object
243+
basis. Returning :data:`DISABLE` from a callback disables the event
244+
for the entire code object (for the current tool).
237245

238246

239247
The STOP_ITERATION event
@@ -247,8 +255,7 @@ raise an exception unless it would be visible to other code.
247255

248256
To allow tools to monitor for real exceptions without slowing down generators
249257
and coroutines, the :monitoring-event:`STOP_ITERATION` event is provided.
250-
:monitoring-event:`STOP_ITERATION` can be locally disabled, unlike
251-
:monitoring-event:`RAISE`.
258+
:monitoring-event:`STOP_ITERATION` can be locally disabled.
252259

253260
Note that the :monitoring-event:`STOP_ITERATION` event and the
254261
:monitoring-event:`RAISE` event for a :exc:`StopIteration` exception are
@@ -314,15 +321,14 @@ location by returning :data:`sys.monitoring.DISABLE` from a callback function.
314321
This does not change which events are set, or any other code locations for the
315322
same event.
316323

317-
Disabling events for specific locations is very important for high
318-
performance monitoring. For example, a program can be run under a
319-
debugger with no overhead if the debugger disables all monitoring
320-
except for a few breakpoints.
324+
:ref:`Other events <monitoring-event-global>` can be disabled on a per code
325+
object basis by returning :data:`sys.monitoring.DISABLE` from a callback
326+
function. This disables the event for the entire code object (for the current
327+
tool).
321328

322-
If :data:`DISABLE` is returned by a callback for a
323-
:ref:`global event <monitoring-event-global>`, :exc:`ValueError` will be raised
324-
by the interpreter in a non-specific location (that is, no traceback will be
325-
provided).
329+
Disabling events for specific locations is very important for high performance
330+
monitoring. For example, a program can be run under a debugger with no overhead
331+
if the debugger disables all monitoring except for a few breakpoints.
326332

327333
.. function:: restart_events() -> None
328334

Doc/library/typing.rst

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1980,7 +1980,7 @@ without the dedicated syntax, as documented below.
19801980

19811981
.. _typevartuple:
19821982

1983-
.. class:: TypeVarTuple(name, *, default=typing.NoDefault)
1983+
.. class:: TypeVarTuple(name, *, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)
19841984

19851985
Type variable tuple. A specialized form of :ref:`type variable <typevar>`
19861986
that enables *variadic* generics.
@@ -2090,6 +2090,24 @@ without the dedicated syntax, as documented below.
20902090

20912091
The name of the type variable tuple.
20922092

2093+
.. attribute:: __covariant__
2094+
2095+
Whether the type variable tuple has been explicitly marked as covariant.
2096+
2097+
.. versionadded:: 3.15
2098+
2099+
.. attribute:: __contravariant__
2100+
2101+
Whether the type variable tuple has been explicitly marked as contravariant.
2102+
2103+
.. versionadded:: 3.15
2104+
2105+
.. attribute:: __infer_variance__
2106+
2107+
Whether the type variable tuple's variance should be inferred by type checkers.
2108+
2109+
.. versionadded:: 3.15
2110+
20932111
.. attribute:: __default__
20942112

20952113
The default value of the type variable tuple, or :data:`typing.NoDefault` if it
@@ -2116,6 +2134,11 @@ without the dedicated syntax, as documented below.
21162134

21172135
.. versionadded:: 3.13
21182136

2137+
Type variable tuples created with ``covariant=True`` or
2138+
``contravariant=True`` can be used to declare covariant or contravariant
2139+
generic types. The ``bound`` argument is also accepted, similar to
2140+
:class:`TypeVar`, but its actual semantics are yet to be decided.
2141+
21192142
.. versionadded:: 3.11
21202143

21212144
.. versionchanged:: 3.12
@@ -2127,6 +2150,11 @@ without the dedicated syntax, as documented below.
21272150

21282151
Support for default values was added.
21292152

2153+
.. versionchanged:: 3.15
2154+
2155+
Added support for the ``bound``, ``covariant``, ``contravariant``, and
2156+
``infer_variance`` parameters.
2157+
21302158
.. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault)
21312159

21322160
Parameter specification variable. A specialized version of
@@ -2196,6 +2224,20 @@ without the dedicated syntax, as documented below.
21962224

21972225
The name of the parameter specification.
21982226

2227+
.. attribute:: __covariant__
2228+
2229+
Whether the parameter specification has been explicitly marked as covariant.
2230+
2231+
.. attribute:: __contravariant__
2232+
2233+
Whether the parameter specification has been explicitly marked as contravariant.
2234+
2235+
.. attribute:: __infer_variance__
2236+
2237+
Whether the parameter specification's variance should be inferred by type checkers.
2238+
2239+
.. versionadded:: 3.12
2240+
21992241
.. attribute:: __default__
22002242

22012243
The default value of the parameter specification, or :data:`typing.NoDefault` if it

Doc/whatsnew/3.15.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,19 @@ sys
11191119
(Contributed by Klaus Zimmermann in :gh:`137476`.)
11201120

11211121

1122+
sys.monitoring
1123+
--------------
1124+
1125+
* The :ref:`other events <monitoring-event-global>`
1126+
(:monitoring-event:`PY_THROW`, :monitoring-event:`PY_UNWIND`,
1127+
:monitoring-event:`RAISE`, :monitoring-event:`EXCEPTION_HANDLED`, and
1128+
:monitoring-event:`RERAISE`) can now be turned on and disabled on a per code
1129+
object basis. Returning :data:`~sys.monitoring.DISABLE` from a callback for
1130+
one of these events disables the event for the entire code object (for the
1131+
current tool), rather than raising :exc:`ValueError` as in prior versions.
1132+
(Contributed by Gabriele N. Tornetta in :gh:`146182`.)
1133+
1134+
11221135
tarfile
11231136
-------
11241137

@@ -1283,6 +1296,11 @@ typing
12831296
child classes of that class cannot inherit from other disjoint bases that are
12841297
not parent or child classes of ``C``. (Contributed by Jelle Zijlstra in :gh:`148639`.)
12851298

1299+
* :class:`~typing.TypeVarTuple` now accepts ``bound``, ``covariant``,
1300+
``contravariant``, and ``infer_variance`` keyword arguments, matching the
1301+
interface of :class:`~typing.TypeVar` and :class:`~typing.ParamSpec`.
1302+
``bound`` semantics remain undefined in the specification.
1303+
12861304

12871305
unicodedata
12881306
-----------

Include/cpython/monitoring.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,20 @@ extern "C" {
2424
#define PY_MONITORING_EVENT_STOP_ITERATION 10
2525

2626
#define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \
27-
((ev) < _PY_MONITORING_LOCAL_EVENTS)
27+
((ev) <= PY_MONITORING_EVENT_STOP_ITERATION)
2828

29-
/* Other events, mainly exceptions */
29+
/* Other events, mainly exceptions.
30+
* These can now be turned on and disabled on a per code object basis. */
3031

31-
#define PY_MONITORING_EVENT_RAISE 11
32+
#define PY_MONITORING_EVENT_PY_UNWIND 11
3233
#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 12
33-
#define PY_MONITORING_EVENT_PY_UNWIND 13
34+
#define PY_MONITORING_EVENT_RAISE 13
3435
#define PY_MONITORING_EVENT_PY_THROW 14
3536
#define PY_MONITORING_EVENT_RERAISE 15
3637

38+
#define _PY_MONITORING_IS_UNGROUPED_EVENT(ev) \
39+
((ev) < _PY_MONITORING_UNGROUPED_EVENTS)
40+
3741

3842
/* Ancillary events */
3943

Include/internal/pycore_ceval.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ PyObject * _PyEval_ImportNameWithImport(
320320
PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs);
321321
PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys);
322322
PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
323-
PyAPI_FUNC(bool) _PyEval_NoToolsForUnwind(PyThreadState *tstate);
323+
PyAPI_FUNC(bool) _PyEval_NoToolsForUnwind(PyThreadState *tstate, _PyInterpreterFrame *frame);
324324
PyAPI_FUNC(int) _PyEval_UnpackIterableStackRef(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, _PyStackRef *sp);
325325
PyAPI_FUNC(void) _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);
326326
PyAPI_FUNC(PyObject **) _PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_ssize_t nargs, PyObject **scratch);

Include/internal/pycore_instruments.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,15 @@ PyAPI_DATA(PyObject) _PyInstrumentation_DISABLE;
7070

7171
/* Total tool ids available */
7272
#define PY_MONITORING_TOOL_IDS 8
73-
/* Count of all local monitoring events */
74-
#define _PY_MONITORING_LOCAL_EVENTS 11
75-
/* Count of all "real" monitoring events (not derived from other events) */
73+
/* Count of all "real" monitoring events (not derived from other events).
74+
* "Other" events can now be turned on/disabled per code object. */
7675
#define _PY_MONITORING_UNGROUPED_EVENTS 16
7776
/* Count of all monitoring events */
7877
#define _PY_MONITORING_EVENTS 19
7978

8079
/* Tables of which tools are active for each monitored event. */
8180
typedef struct _Py_LocalMonitors {
82-
uint8_t tools[_PY_MONITORING_LOCAL_EVENTS];
81+
uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS];
8382
} _Py_LocalMonitors;
8483

8584
typedef struct _Py_GlobalMonitors {

Lib/test/test_asyncio/test_sock_lowlevel.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,27 @@ def test_recvfrom_into(self):
427427
self.loop.run_until_complete(
428428
self._basetest_datagram_recvfrom_into(server_address))
429429

430+
async def _basetest_datagram_recvfrom_into_wrong_size(self, server_address):
431+
# Call sock_sendto() with a size larger than the buffer
432+
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
433+
sock.setblocking(False)
434+
435+
buf = bytearray(5000)
436+
data = b'\x01' * 4096
437+
wrong_size = len(buf) + 1
438+
await self.loop.sock_sendto(sock, data, server_address)
439+
with self.assertRaises(ValueError):
440+
await self.loop.sock_recvfrom_into(
441+
sock, buf, wrong_size)
442+
443+
size, addr = await self.loop.sock_recvfrom_into(sock, buf)
444+
self.assertEqual(buf[:size], data)
445+
446+
def test_recvfrom_into_wrong_size(self):
447+
with test_utils.run_udp_echo_server() as server_address:
448+
self.loop.run_until_complete(
449+
self._basetest_datagram_recvfrom_into_wrong_size(server_address))
450+
430451
async def _basetest_datagram_sendto_blocking(self, server_address):
431452
# Sad path, sock.sendto() raises BlockingIOError
432453
# This involves patching sock.sendto() to raise BlockingIOError but

0 commit comments

Comments
 (0)