Skip to content

Commit 2fae889

Browse files
committed
Merge branch 'main' into modulelocals
* main: pythongh-105540: Fix code generator tests (python#105707) pythongh-105375: Explicitly initialise all {Pickler,Unpickler}Object fields (python#105686) pythongh-105331: Change `asyncio.sleep` to raise ``ValueError` for nan (python#105641) Remove support for legacy bytecode instructions (python#105705)
2 parents 5609f64 + 8da9d1b commit 2fae889

File tree

8 files changed

+127
-187
lines changed

8 files changed

+127
-187
lines changed

Doc/library/asyncio-task.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,9 @@ Sleeping
426426
.. versionchanged:: 3.10
427427
Removed the *loop* parameter.
428428

429+
.. versionchanged:: 3.13
430+
Raises :exc:`ValueError` if *delay* is :data:`~math.nan`.
431+
429432

430433
Running Tasks Concurrently
431434
==========================

Lib/asyncio/tasks.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import functools
1616
import inspect
1717
import itertools
18+
import math
1819
import types
1920
import warnings
2021
import weakref
@@ -646,6 +647,9 @@ async def sleep(delay, result=None):
646647
await __sleep0()
647648
return result
648649

650+
if math.isnan(delay):
651+
raise ValueError("Invalid delay: NaN (not a number)")
652+
649653
loop = events.get_running_loop()
650654
future = loop.create_future()
651655
h = loop.call_later(delay,

Lib/test/test_asyncio/test_tasks.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,21 @@ async def sleeper(dt, arg):
16091609
self.assertEqual(t.result(), 'yeah')
16101610
self.assertAlmostEqual(0.1, loop.time())
16111611

1612+
def test_sleep_when_delay_is_nan(self):
1613+
1614+
def gen():
1615+
yield
1616+
1617+
loop = self.new_test_loop(gen)
1618+
1619+
async def sleeper():
1620+
await asyncio.sleep(float("nan"))
1621+
1622+
t = self.new_task(loop, sleeper())
1623+
1624+
with self.assertRaises(ValueError):
1625+
loop.run_until_complete(t)
1626+
16121627
def test_sleep_cancel(self):
16131628

16141629
def gen():
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raise :exc:`ValueError` if the ``delay`` argument to :func:`asyncio.sleep` is a NaN (matching :func:`time.sleep`).
2+

Modules/_pickle.c

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,42 +1145,49 @@ _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len)
11451145
static PicklerObject *
11461146
_Pickler_New(PickleState *st)
11471147
{
1148-
PicklerObject *self;
1149-
1150-
self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
1151-
if (self == NULL)
1148+
PyMemoTable *memo = PyMemoTable_New();
1149+
if (memo == NULL) {
11521150
return NULL;
1151+
}
1152+
1153+
const Py_ssize_t max_output_len = WRITE_BUF_SIZE;
1154+
PyObject *output_buffer = PyBytes_FromStringAndSize(NULL, max_output_len);
1155+
if (output_buffer == NULL) {
1156+
goto error;
1157+
}
11531158

1159+
PicklerObject *self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
1160+
if (self == NULL) {
1161+
goto error;
1162+
}
1163+
1164+
self->memo = memo;
11541165
self->pers_func = NULL;
1166+
self->pers_func_self = NULL;
11551167
self->dispatch_table = NULL;
1156-
self->buffer_callback = NULL;
1168+
self->reducer_override = NULL;
11571169
self->write = NULL;
1170+
self->output_buffer = output_buffer;
1171+
self->output_len = 0;
1172+
self->max_output_len = max_output_len;
11581173
self->proto = 0;
11591174
self->bin = 0;
11601175
self->framing = 0;
11611176
self->frame_start = -1;
1177+
self->buf_size = 0;
11621178
self->fast = 0;
11631179
self->fast_nesting = 0;
11641180
self->fix_imports = 0;
11651181
self->fast_memo = NULL;
1166-
self->max_output_len = WRITE_BUF_SIZE;
1167-
self->output_len = 0;
1168-
self->reducer_override = NULL;
1169-
1170-
self->memo = PyMemoTable_New();
1171-
if (self->memo == NULL) {
1172-
Py_DECREF(self);
1173-
return NULL;
1174-
}
1175-
self->output_buffer = PyBytes_FromStringAndSize(NULL,
1176-
self->max_output_len);
1177-
if (self->output_buffer == NULL) {
1178-
Py_DECREF(self);
1179-
return NULL;
1180-
}
1182+
self->buffer_callback = NULL;
11811183

11821184
PyObject_GC_Track(self);
11831185
return self;
1186+
1187+
error:
1188+
PyMem_Free(memo);
1189+
Py_XDECREF(output_buffer);
1190+
return NULL;
11841191
}
11851192

11861193
static int
@@ -1628,14 +1635,31 @@ _Unpickler_MemoCleanup(UnpicklerObject *self)
16281635
static UnpicklerObject *
16291636
_Unpickler_New(PyObject *module)
16301637
{
1631-
UnpicklerObject *self;
1638+
const int MEMO_SIZE = 32;
1639+
PyObject **memo = _Unpickler_NewMemo(MEMO_SIZE);
1640+
if (memo == NULL) {
1641+
return NULL;
1642+
}
1643+
16321644
PickleState *st = _Pickle_GetState(module);
1645+
PyObject *stack = Pdata_New(st);
1646+
if (stack == NULL) {
1647+
goto error;
1648+
}
16331649

1634-
self = PyObject_GC_New(UnpicklerObject, st->Unpickler_Type);
1635-
if (self == NULL)
1636-
return NULL;
1650+
UnpicklerObject *self = PyObject_GC_New(UnpicklerObject,
1651+
st->Unpickler_Type);
1652+
if (self == NULL) {
1653+
goto error;
1654+
}
16371655

1656+
self->stack = (Pdata *)stack;
1657+
self->memo = memo;
1658+
self->memo_size = MEMO_SIZE;
1659+
self->memo_len = 0;
16381660
self->pers_func = NULL;
1661+
self->pers_func_self = NULL;
1662+
memset(&self->buffer, 0, sizeof(Py_buffer));
16391663
self->input_buffer = NULL;
16401664
self->input_line = NULL;
16411665
self->input_len = 0;
@@ -1653,22 +1677,14 @@ _Unpickler_New(PyObject *module)
16531677
self->marks_size = 0;
16541678
self->proto = 0;
16551679
self->fix_imports = 0;
1656-
memset(&self->buffer, 0, sizeof(Py_buffer));
1657-
self->memo_size = 32;
1658-
self->memo_len = 0;
1659-
self->memo = _Unpickler_NewMemo(self->memo_size);
1660-
if (self->memo == NULL) {
1661-
Py_DECREF(self);
1662-
return NULL;
1663-
}
1664-
self->stack = (Pdata *)Pdata_New(st);
1665-
if (self->stack == NULL) {
1666-
Py_DECREF(self);
1667-
return NULL;
1668-
}
16691680

16701681
PyObject_GC_Track(self);
16711682
return self;
1683+
1684+
error:
1685+
PyMem_Free(memo);
1686+
Py_XDECREF(stack);
1687+
return NULL;
16721688
}
16731689

16741690
/* Returns -1 (with an exception set) on failure, 0 on success. This may

Tools/cases_generator/generate_cases.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ class Instruction:
230230

231231
# Parts of the underlying instruction definition
232232
inst: parser.InstDef
233-
kind: typing.Literal["inst", "op", "legacy"] # Legacy means no (input -- output)
233+
kind: typing.Literal["inst", "op"]
234234
name: str
235235
block: parser.Block
236236
block_text: list[str] # Block.text, less curlies, less PREDICT() calls
@@ -856,8 +856,6 @@ def get_stack_effect_info(
856856
self, thing: parser.InstDef | parser.Macro | parser.Pseudo
857857
) -> tuple[AnyInstruction | None, str, str]:
858858
def effect_str(effects: list[StackEffect]) -> str:
859-
if getattr(thing, "kind", None) == "legacy":
860-
return str(-1)
861859
n_effect, sym_effect = list_effect_size(effects)
862860
if sym_effect:
863861
return f"{sym_effect} + {n_effect}" if n_effect else sym_effect

Tools/cases_generator/parser.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class OpName(Node):
101101
class InstHeader(Node):
102102
override: bool
103103
register: bool
104-
kind: Literal["inst", "op", "legacy"] # Legacy means no (inputs -- outputs)
104+
kind: Literal["inst", "op"]
105105
name: str
106106
inputs: list[InputEffect]
107107
outputs: list[OutputEffect]
@@ -111,7 +111,7 @@ class InstHeader(Node):
111111
class InstDef(Node):
112112
override: bool
113113
register: bool
114-
kind: Literal["inst", "op", "legacy"]
114+
kind: Literal["inst", "op"]
115115
name: str
116116
inputs: list[InputEffect]
117117
outputs: list[OutputEffect]
@@ -174,9 +174,6 @@ def inst_header(self) -> InstHeader | None:
174174
if self.expect(lx.RPAREN):
175175
if (tkn := self.peek()) and tkn.kind == lx.LBRACE:
176176
return InstHeader(override, register, kind, name, inp, outp)
177-
elif self.expect(lx.RPAREN) and kind == "inst":
178-
# No legacy stack effect if kind is "op".
179-
return InstHeader(override, register, "legacy", name, [], [])
180177
return None
181178

182179
def io_effect(self) -> tuple[list[InputEffect], list[OutputEffect]]:

0 commit comments

Comments
 (0)