From 6acaf659ef0fdee131bc02f0b58685da039b5855 Mon Sep 17 00:00:00 2001 From: krylosov-aa Date: Thu, 5 Mar 2026 06:48:25 +0300 Subject: [PATCH 001/775] gh-145301: Fix double-free in hashlib and hmac module initialization (GH-145321) gh-145301: Fix double-free in hashlib and hmac initialization --- ...-02-27-19-00-26.gh-issue-145301.2Wih4b.rst | 2 ++ ...-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst | 2 ++ Modules/_hashopenssl.c | 2 +- Modules/hmacmodule.c | 23 +++++++++++-------- 4 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst create mode 100644 Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst diff --git a/Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst b/Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst new file mode 100644 index 00000000000..7aeb6a1145a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst @@ -0,0 +1,2 @@ +:mod:`hashlib`: fix a crash when the initialization of the underlying C +extension module fails. diff --git a/Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst b/Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst new file mode 100644 index 00000000000..436ff316b2c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst @@ -0,0 +1,2 @@ +:mod:`hmac`: fix a crash when the initialization of the underlying C +extension module fails. diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 77832a768e0..e19eb1abcf2 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -268,7 +268,7 @@ py_hashentry_table_new(void) { if (h->py_alias != NULL) { if (_Py_hashtable_set(ht, (const void*)entry->py_alias, (void*)entry) < 0) { - PyMem_Free(entry); + /* entry is already in ht, will be freed by _Py_hashtable_destroy() */ goto error; } entry->refcnt++; diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index f074f248077..7a040103bcb 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1453,16 +1453,19 @@ py_hmac_hinfo_ht_new(void) assert(value->display_name == NULL); value->refcnt = 0; -#define Py_HMAC_HINFO_LINK(KEY) \ - do { \ - int rc = py_hmac_hinfo_ht_add(table, KEY, value); \ - if (rc < 0) { \ - PyMem_Free(value); \ - goto error; \ - } \ - else if (rc == 1) { \ - value->refcnt++; \ - } \ +#define Py_HMAC_HINFO_LINK(KEY) \ + do { \ + int rc = py_hmac_hinfo_ht_add(table, (KEY), value); \ + if (rc < 0) { \ + /* entry may already be in ht, freed upon exit */ \ + if (value->refcnt == 0) { \ + PyMem_Free(value); \ + } \ + goto error; \ + } \ + else if (rc == 1) { \ + value->refcnt++; \ + } \ } while (0) Py_HMAC_HINFO_LINK(e->name); Py_HMAC_HINFO_LINK(e->hashlib_name); From 0eaf260d79f8547b02d8e80d760b11e821928fde Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Thu, 5 Mar 2026 11:21:49 +0100 Subject: [PATCH 002/775] gh-145376: Fix refleak and null pointer deref in unusual error path of datetime module (GH-145476) --- Modules/_datetimemodule.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 8f64e572bd6..6b23a5c637a 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3822,9 +3822,26 @@ iso_calendar_date_new_impl(PyTypeObject *type, int year, int week, return NULL; } - PyTuple_SET_ITEM(self, 0, PyLong_FromLong(year)); - PyTuple_SET_ITEM(self, 1, PyLong_FromLong(week)); - PyTuple_SET_ITEM(self, 2, PyLong_FromLong(weekday)); + PyObject *year_object = PyLong_FromLong(year); + if (year_object == NULL) { + Py_DECREF(self); + return NULL; + } + PyTuple_SET_ITEM(self, 0, year_object); + + PyObject *week_object = PyLong_FromLong(week); + if (week_object == NULL) { + Py_DECREF(self); + return NULL; + } + PyTuple_SET_ITEM(self, 1, week_object); + + PyObject *weekday_object = PyLong_FromLong(weekday); + if (weekday_object == NULL) { + Py_DECREF(self); + return NULL; + } + PyTuple_SET_ITEM(self, 2, weekday_object); return (PyObject *)self; } @@ -6891,9 +6908,9 @@ datetime_datetime_astimezone_impl(PyDateTime_DateTime *self, goto naive; } else if (!PyDelta_Check(offset)) { + PyErr_Format(PyExc_TypeError, "utcoffset() returned %T," + " expected timedelta or None", offset); Py_DECREF(offset); - PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s," - " expected timedelta or None", Py_TYPE(offset)->tp_name); return NULL; } /* result = self - offset */ From 23a4e3ba3c44b423eff635672c56d614f5ea3899 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 5 Mar 2026 12:29:34 +0100 Subject: [PATCH 003/775] gh-145335: Skip Emscripten for os.execve() test (#145528) Emscripten's os.execve() always fails with ENOEXEC. Co-authored-by: Victor Stinner --- Lib/test/test_os/test_os.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_os/test_os.py b/Lib/test/test_os/test_os.py index 3cab8ff9536..06f69caad12 100644 --- a/Lib/test/test_os/test_os.py +++ b/Lib/test/test_os/test_os.py @@ -2824,7 +2824,8 @@ def test_negative_fd_ebadf(self, fd): func(*args) self.assertEqual(ctx.exception.errno, errno.EBADF) - if hasattr(os, "execve") and os.execve in os.supports_fd: + if (hasattr(os, "execve") and os.execve in os.supports_fd + and support.has_subprocess_support): # glibc fails with EINVAL, musl fails with EBADF with self.assertRaises(OSError) as ctx: os.execve(fd, [sys.executable, "-c", "pass"], os.environ) From 0fe20fc1703c52c0b2597d70df6cad9b3e4056f0 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 12:31:29 +0100 Subject: [PATCH 004/775] gh-141510: Don't accept frozendict in PyDict_Watch() (#145529) Don't accept frozendict in PyDict_Watch() and PyDict_Unwatch(). A frozendict cannot be modified, so it's not useful to watch for modifications. --- Lib/test/test_capi/test_watchers.py | 5 +++-- Objects/dictobject.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_capi/test_watchers.py b/Lib/test/test_capi/test_watchers.py index bef72032513..67595e3550b 100644 --- a/Lib/test/test_capi/test_watchers.py +++ b/Lib/test/test_capi/test_watchers.py @@ -176,8 +176,9 @@ def test_watch_unassigned_watcher_id(self): def test_unwatch_non_dict(self): with self.watcher() as wid: - with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): - self.unwatch(wid, 1) + for wrong_type in (frozendict(), 5, [123], object()): + with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): + self.unwatch(wid, wrong_type) def test_unwatch_out_of_range_watcher_id(self): d = {} diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 2552216152f..e0127f04249 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -7912,7 +7912,7 @@ validate_watcher_id(PyInterpreterState *interp, int watcher_id) int PyDict_Watch(int watcher_id, PyObject* dict) { - if (!PyAnyDict_Check(dict)) { + if (!PyDict_Check(dict)) { PyErr_SetString(PyExc_ValueError, "Cannot watch non-dictionary"); return -1; } @@ -7927,7 +7927,7 @@ PyDict_Watch(int watcher_id, PyObject* dict) int PyDict_Unwatch(int watcher_id, PyObject* dict) { - if (!PyAnyDict_Check(dict)) { + if (!PyDict_Check(dict)) { PyErr_SetString(PyExc_ValueError, "Cannot watch non-dictionary"); return -1; } From 2acfad9d57a5f4f184410b438ca4432e47ed99dc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 12:32:32 +0100 Subject: [PATCH 005/775] gh-82626: Schedule removal of bool used as file descriptor (#145469) --- Doc/deprecations/pending-removal-in-3.18.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/deprecations/pending-removal-in-3.18.rst b/Doc/deprecations/pending-removal-in-3.18.rst index 3e799219478..eb42fe9919e 100644 --- a/Doc/deprecations/pending-removal-in-3.18.rst +++ b/Doc/deprecations/pending-removal-in-3.18.rst @@ -1,6 +1,9 @@ Pending removal in Python 3.18 ------------------------------ +* No longer accept a boolean value when a file descriptor is expected. + (Contributed by Serhiy Storchaka in :gh:`82626`.) + * :mod:`decimal`: * The non-standard and undocumented :class:`~decimal.Decimal` format From c8aa8de9a5ad4df58ac0ffeae897e1258728b7eb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 12:33:13 +0100 Subject: [PATCH 006/775] gh-141510: Use frozendict in the _opcode_metadata (#144910) Enhance py_metadata_generator.py to skip duplicates. Co-authored-by: Donghee Na --- Lib/_opcode_metadata.py | 732 +++++++++--------- .../cases_generator/py_metadata_generator.py | 28 +- 2 files changed, 383 insertions(+), 377 deletions(-) diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 8f14d81a43e..6e37288c32d 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -2,375 +2,373 @@ # from: # Python/bytecodes.c # Do not edit! -_specializations = { - "RESUME": [ - "RESUME_CHECK", - ], - "TO_BOOL": [ - "TO_BOOL_ALWAYS_TRUE", - "TO_BOOL_BOOL", - "TO_BOOL_INT", - "TO_BOOL_LIST", - "TO_BOOL_NONE", - "TO_BOOL_STR", - ], - "BINARY_OP": [ - "BINARY_OP_MULTIPLY_INT", - "BINARY_OP_ADD_INT", - "BINARY_OP_SUBTRACT_INT", - "BINARY_OP_MULTIPLY_FLOAT", - "BINARY_OP_ADD_FLOAT", - "BINARY_OP_SUBTRACT_FLOAT", - "BINARY_OP_ADD_UNICODE", - "BINARY_OP_SUBSCR_LIST_INT", - "BINARY_OP_SUBSCR_LIST_SLICE", - "BINARY_OP_SUBSCR_TUPLE_INT", - "BINARY_OP_SUBSCR_STR_INT", - "BINARY_OP_SUBSCR_USTR_INT", - "BINARY_OP_SUBSCR_DICT", - "BINARY_OP_SUBSCR_GETITEM", - "BINARY_OP_INPLACE_ADD_UNICODE", - "BINARY_OP_EXTEND", - "BINARY_OP_INPLACE_ADD_UNICODE", - ], - "STORE_SUBSCR": [ - "STORE_SUBSCR_DICT", - "STORE_SUBSCR_LIST_INT", - ], - "SEND": [ - "SEND_GEN", - ], - "UNPACK_SEQUENCE": [ - "UNPACK_SEQUENCE_TWO_TUPLE", - "UNPACK_SEQUENCE_TUPLE", - "UNPACK_SEQUENCE_LIST", - ], - "STORE_ATTR": [ - "STORE_ATTR_INSTANCE_VALUE", - "STORE_ATTR_SLOT", - "STORE_ATTR_WITH_HINT", - ], - "LOAD_GLOBAL": [ - "LOAD_GLOBAL_MODULE", - "LOAD_GLOBAL_BUILTIN", - ], - "LOAD_SUPER_ATTR": [ - "LOAD_SUPER_ATTR_ATTR", - "LOAD_SUPER_ATTR_METHOD", - ], - "LOAD_ATTR": [ - "LOAD_ATTR_INSTANCE_VALUE", - "LOAD_ATTR_MODULE", - "LOAD_ATTR_WITH_HINT", - "LOAD_ATTR_SLOT", - "LOAD_ATTR_CLASS", - "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK", - "LOAD_ATTR_PROPERTY", - "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", - "LOAD_ATTR_METHOD_WITH_VALUES", - "LOAD_ATTR_METHOD_NO_DICT", - "LOAD_ATTR_METHOD_LAZY_DICT", - "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", - "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", - ], - "COMPARE_OP": [ - "COMPARE_OP_FLOAT", - "COMPARE_OP_INT", - "COMPARE_OP_STR", - ], - "CONTAINS_OP": [ - "CONTAINS_OP_SET", - "CONTAINS_OP_DICT", - ], - "JUMP_BACKWARD": [ - "JUMP_BACKWARD_NO_JIT", - "JUMP_BACKWARD_JIT", - ], - "FOR_ITER": [ - "FOR_ITER_LIST", - "FOR_ITER_TUPLE", - "FOR_ITER_RANGE", - "FOR_ITER_GEN", - ], - "CALL": [ - "CALL_BOUND_METHOD_EXACT_ARGS", - "CALL_PY_EXACT_ARGS", - "CALL_TYPE_1", - "CALL_STR_1", - "CALL_TUPLE_1", - "CALL_BUILTIN_CLASS", - "CALL_BUILTIN_O", - "CALL_BUILTIN_FAST", - "CALL_BUILTIN_FAST_WITH_KEYWORDS", - "CALL_LEN", - "CALL_ISINSTANCE", - "CALL_LIST_APPEND", - "CALL_METHOD_DESCRIPTOR_O", - "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", - "CALL_METHOD_DESCRIPTOR_NOARGS", - "CALL_METHOD_DESCRIPTOR_FAST", - "CALL_ALLOC_AND_ENTER_INIT", - "CALL_PY_GENERAL", - "CALL_BOUND_METHOD_GENERAL", - "CALL_NON_PY_GENERAL", - ], - "CALL_KW": [ - "CALL_KW_BOUND_METHOD", - "CALL_KW_PY", - "CALL_KW_NON_PY", - ], - "CALL_FUNCTION_EX": [ - "CALL_EX_PY", - "CALL_EX_NON_PY_GENERAL", - ], -} +_specializations = frozendict( + RESUME=( + "RESUME_CHECK", + ), + TO_BOOL=( + "TO_BOOL_ALWAYS_TRUE", + "TO_BOOL_BOOL", + "TO_BOOL_INT", + "TO_BOOL_LIST", + "TO_BOOL_NONE", + "TO_BOOL_STR", + ), + BINARY_OP=( + "BINARY_OP_MULTIPLY_INT", + "BINARY_OP_ADD_INT", + "BINARY_OP_SUBTRACT_INT", + "BINARY_OP_MULTIPLY_FLOAT", + "BINARY_OP_ADD_FLOAT", + "BINARY_OP_SUBTRACT_FLOAT", + "BINARY_OP_ADD_UNICODE", + "BINARY_OP_SUBSCR_LIST_INT", + "BINARY_OP_SUBSCR_LIST_SLICE", + "BINARY_OP_SUBSCR_TUPLE_INT", + "BINARY_OP_SUBSCR_STR_INT", + "BINARY_OP_SUBSCR_USTR_INT", + "BINARY_OP_SUBSCR_DICT", + "BINARY_OP_SUBSCR_GETITEM", + "BINARY_OP_INPLACE_ADD_UNICODE", + "BINARY_OP_EXTEND", + ), + STORE_SUBSCR=( + "STORE_SUBSCR_DICT", + "STORE_SUBSCR_LIST_INT", + ), + SEND=( + "SEND_GEN", + ), + UNPACK_SEQUENCE=( + "UNPACK_SEQUENCE_TWO_TUPLE", + "UNPACK_SEQUENCE_TUPLE", + "UNPACK_SEQUENCE_LIST", + ), + STORE_ATTR=( + "STORE_ATTR_INSTANCE_VALUE", + "STORE_ATTR_SLOT", + "STORE_ATTR_WITH_HINT", + ), + LOAD_GLOBAL=( + "LOAD_GLOBAL_MODULE", + "LOAD_GLOBAL_BUILTIN", + ), + LOAD_SUPER_ATTR=( + "LOAD_SUPER_ATTR_ATTR", + "LOAD_SUPER_ATTR_METHOD", + ), + LOAD_ATTR=( + "LOAD_ATTR_INSTANCE_VALUE", + "LOAD_ATTR_MODULE", + "LOAD_ATTR_WITH_HINT", + "LOAD_ATTR_SLOT", + "LOAD_ATTR_CLASS", + "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK", + "LOAD_ATTR_PROPERTY", + "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", + "LOAD_ATTR_METHOD_WITH_VALUES", + "LOAD_ATTR_METHOD_NO_DICT", + "LOAD_ATTR_METHOD_LAZY_DICT", + "LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", + "LOAD_ATTR_NONDESCRIPTOR_NO_DICT", + ), + COMPARE_OP=( + "COMPARE_OP_FLOAT", + "COMPARE_OP_INT", + "COMPARE_OP_STR", + ), + CONTAINS_OP=( + "CONTAINS_OP_SET", + "CONTAINS_OP_DICT", + ), + JUMP_BACKWARD=( + "JUMP_BACKWARD_NO_JIT", + "JUMP_BACKWARD_JIT", + ), + FOR_ITER=( + "FOR_ITER_LIST", + "FOR_ITER_TUPLE", + "FOR_ITER_RANGE", + "FOR_ITER_GEN", + ), + CALL=( + "CALL_BOUND_METHOD_EXACT_ARGS", + "CALL_PY_EXACT_ARGS", + "CALL_TYPE_1", + "CALL_STR_1", + "CALL_TUPLE_1", + "CALL_BUILTIN_CLASS", + "CALL_BUILTIN_O", + "CALL_BUILTIN_FAST", + "CALL_BUILTIN_FAST_WITH_KEYWORDS", + "CALL_LEN", + "CALL_ISINSTANCE", + "CALL_LIST_APPEND", + "CALL_METHOD_DESCRIPTOR_O", + "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", + "CALL_METHOD_DESCRIPTOR_NOARGS", + "CALL_METHOD_DESCRIPTOR_FAST", + "CALL_ALLOC_AND_ENTER_INIT", + "CALL_PY_GENERAL", + "CALL_BOUND_METHOD_GENERAL", + "CALL_NON_PY_GENERAL", + ), + CALL_KW=( + "CALL_KW_BOUND_METHOD", + "CALL_KW_PY", + "CALL_KW_NON_PY", + ), + CALL_FUNCTION_EX=( + "CALL_EX_PY", + "CALL_EX_NON_PY_GENERAL", + ), +) -_specialized_opmap = { - 'BINARY_OP_ADD_FLOAT': 129, - 'BINARY_OP_ADD_INT': 130, - 'BINARY_OP_ADD_UNICODE': 131, - 'BINARY_OP_EXTEND': 132, - 'BINARY_OP_INPLACE_ADD_UNICODE': 3, - 'BINARY_OP_INPLACE_ADD_UNICODE': 3, - 'BINARY_OP_MULTIPLY_FLOAT': 133, - 'BINARY_OP_MULTIPLY_INT': 134, - 'BINARY_OP_SUBSCR_DICT': 135, - 'BINARY_OP_SUBSCR_GETITEM': 136, - 'BINARY_OP_SUBSCR_LIST_INT': 137, - 'BINARY_OP_SUBSCR_LIST_SLICE': 138, - 'BINARY_OP_SUBSCR_STR_INT': 139, - 'BINARY_OP_SUBSCR_TUPLE_INT': 140, - 'BINARY_OP_SUBSCR_USTR_INT': 141, - 'BINARY_OP_SUBTRACT_FLOAT': 142, - 'BINARY_OP_SUBTRACT_INT': 143, - 'CALL_ALLOC_AND_ENTER_INIT': 144, - 'CALL_BOUND_METHOD_EXACT_ARGS': 145, - 'CALL_BOUND_METHOD_GENERAL': 146, - 'CALL_BUILTIN_CLASS': 147, - 'CALL_BUILTIN_FAST': 148, - 'CALL_BUILTIN_FAST_WITH_KEYWORDS': 149, - 'CALL_BUILTIN_O': 150, - 'CALL_EX_NON_PY_GENERAL': 151, - 'CALL_EX_PY': 152, - 'CALL_ISINSTANCE': 153, - 'CALL_KW_BOUND_METHOD': 154, - 'CALL_KW_NON_PY': 155, - 'CALL_KW_PY': 156, - 'CALL_LEN': 157, - 'CALL_LIST_APPEND': 158, - 'CALL_METHOD_DESCRIPTOR_FAST': 159, - 'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 160, - 'CALL_METHOD_DESCRIPTOR_NOARGS': 161, - 'CALL_METHOD_DESCRIPTOR_O': 162, - 'CALL_NON_PY_GENERAL': 163, - 'CALL_PY_EXACT_ARGS': 164, - 'CALL_PY_GENERAL': 165, - 'CALL_STR_1': 166, - 'CALL_TUPLE_1': 167, - 'CALL_TYPE_1': 168, - 'COMPARE_OP_FLOAT': 169, - 'COMPARE_OP_INT': 170, - 'COMPARE_OP_STR': 171, - 'CONTAINS_OP_DICT': 172, - 'CONTAINS_OP_SET': 173, - 'FOR_ITER_GEN': 174, - 'FOR_ITER_LIST': 175, - 'FOR_ITER_RANGE': 176, - 'FOR_ITER_TUPLE': 177, - 'JUMP_BACKWARD_JIT': 178, - 'JUMP_BACKWARD_NO_JIT': 179, - 'LOAD_ATTR_CLASS': 180, - 'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 181, - 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 182, - 'LOAD_ATTR_INSTANCE_VALUE': 183, - 'LOAD_ATTR_METHOD_LAZY_DICT': 184, - 'LOAD_ATTR_METHOD_NO_DICT': 185, - 'LOAD_ATTR_METHOD_WITH_VALUES': 186, - 'LOAD_ATTR_MODULE': 187, - 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 188, - 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 189, - 'LOAD_ATTR_PROPERTY': 190, - 'LOAD_ATTR_SLOT': 191, - 'LOAD_ATTR_WITH_HINT': 192, - 'LOAD_GLOBAL_BUILTIN': 193, - 'LOAD_GLOBAL_MODULE': 194, - 'LOAD_SUPER_ATTR_ATTR': 195, - 'LOAD_SUPER_ATTR_METHOD': 196, - 'RESUME_CHECK': 197, - 'SEND_GEN': 198, - 'STORE_ATTR_INSTANCE_VALUE': 199, - 'STORE_ATTR_SLOT': 200, - 'STORE_ATTR_WITH_HINT': 201, - 'STORE_SUBSCR_DICT': 202, - 'STORE_SUBSCR_LIST_INT': 203, - 'TO_BOOL_ALWAYS_TRUE': 204, - 'TO_BOOL_BOOL': 205, - 'TO_BOOL_INT': 206, - 'TO_BOOL_LIST': 207, - 'TO_BOOL_NONE': 208, - 'TO_BOOL_STR': 209, - 'UNPACK_SEQUENCE_LIST': 210, - 'UNPACK_SEQUENCE_TUPLE': 211, - 'UNPACK_SEQUENCE_TWO_TUPLE': 212, -} +_specialized_opmap = frozendict( + BINARY_OP_ADD_FLOAT=129, + BINARY_OP_ADD_INT=130, + BINARY_OP_ADD_UNICODE=131, + BINARY_OP_EXTEND=132, + BINARY_OP_INPLACE_ADD_UNICODE=3, + BINARY_OP_MULTIPLY_FLOAT=133, + BINARY_OP_MULTIPLY_INT=134, + BINARY_OP_SUBSCR_DICT=135, + BINARY_OP_SUBSCR_GETITEM=136, + BINARY_OP_SUBSCR_LIST_INT=137, + BINARY_OP_SUBSCR_LIST_SLICE=138, + BINARY_OP_SUBSCR_STR_INT=139, + BINARY_OP_SUBSCR_TUPLE_INT=140, + BINARY_OP_SUBSCR_USTR_INT=141, + BINARY_OP_SUBTRACT_FLOAT=142, + BINARY_OP_SUBTRACT_INT=143, + CALL_ALLOC_AND_ENTER_INIT=144, + CALL_BOUND_METHOD_EXACT_ARGS=145, + CALL_BOUND_METHOD_GENERAL=146, + CALL_BUILTIN_CLASS=147, + CALL_BUILTIN_FAST=148, + CALL_BUILTIN_FAST_WITH_KEYWORDS=149, + CALL_BUILTIN_O=150, + CALL_EX_NON_PY_GENERAL=151, + CALL_EX_PY=152, + CALL_ISINSTANCE=153, + CALL_KW_BOUND_METHOD=154, + CALL_KW_NON_PY=155, + CALL_KW_PY=156, + CALL_LEN=157, + CALL_LIST_APPEND=158, + CALL_METHOD_DESCRIPTOR_FAST=159, + CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS=160, + CALL_METHOD_DESCRIPTOR_NOARGS=161, + CALL_METHOD_DESCRIPTOR_O=162, + CALL_NON_PY_GENERAL=163, + CALL_PY_EXACT_ARGS=164, + CALL_PY_GENERAL=165, + CALL_STR_1=166, + CALL_TUPLE_1=167, + CALL_TYPE_1=168, + COMPARE_OP_FLOAT=169, + COMPARE_OP_INT=170, + COMPARE_OP_STR=171, + CONTAINS_OP_DICT=172, + CONTAINS_OP_SET=173, + FOR_ITER_GEN=174, + FOR_ITER_LIST=175, + FOR_ITER_RANGE=176, + FOR_ITER_TUPLE=177, + JUMP_BACKWARD_JIT=178, + JUMP_BACKWARD_NO_JIT=179, + LOAD_ATTR_CLASS=180, + LOAD_ATTR_CLASS_WITH_METACLASS_CHECK=181, + LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN=182, + LOAD_ATTR_INSTANCE_VALUE=183, + LOAD_ATTR_METHOD_LAZY_DICT=184, + LOAD_ATTR_METHOD_NO_DICT=185, + LOAD_ATTR_METHOD_WITH_VALUES=186, + LOAD_ATTR_MODULE=187, + LOAD_ATTR_NONDESCRIPTOR_NO_DICT=188, + LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES=189, + LOAD_ATTR_PROPERTY=190, + LOAD_ATTR_SLOT=191, + LOAD_ATTR_WITH_HINT=192, + LOAD_GLOBAL_BUILTIN=193, + LOAD_GLOBAL_MODULE=194, + LOAD_SUPER_ATTR_ATTR=195, + LOAD_SUPER_ATTR_METHOD=196, + RESUME_CHECK=197, + SEND_GEN=198, + STORE_ATTR_INSTANCE_VALUE=199, + STORE_ATTR_SLOT=200, + STORE_ATTR_WITH_HINT=201, + STORE_SUBSCR_DICT=202, + STORE_SUBSCR_LIST_INT=203, + TO_BOOL_ALWAYS_TRUE=204, + TO_BOOL_BOOL=205, + TO_BOOL_INT=206, + TO_BOOL_LIST=207, + TO_BOOL_NONE=208, + TO_BOOL_STR=209, + UNPACK_SEQUENCE_LIST=210, + UNPACK_SEQUENCE_TUPLE=211, + UNPACK_SEQUENCE_TWO_TUPLE=212, +) -opmap = { - 'CACHE': 0, - 'RESERVED': 17, - 'RESUME': 128, - 'INSTRUMENTED_LINE': 253, - 'ENTER_EXECUTOR': 254, - 'TRACE_RECORD': 255, - 'BINARY_SLICE': 1, - 'BUILD_TEMPLATE': 2, - 'CALL_FUNCTION_EX': 4, - 'CHECK_EG_MATCH': 5, - 'CHECK_EXC_MATCH': 6, - 'CLEANUP_THROW': 7, - 'DELETE_SUBSCR': 8, - 'END_FOR': 9, - 'END_SEND': 10, - 'EXIT_INIT_CHECK': 11, - 'FORMAT_SIMPLE': 12, - 'FORMAT_WITH_SPEC': 13, - 'GET_AITER': 14, - 'GET_ANEXT': 15, - 'GET_ITER': 16, - 'GET_LEN': 18, - 'GET_YIELD_FROM_ITER': 19, - 'INTERPRETER_EXIT': 20, - 'LOAD_BUILD_CLASS': 21, - 'LOAD_LOCALS': 22, - 'MAKE_FUNCTION': 23, - 'MATCH_KEYS': 24, - 'MATCH_MAPPING': 25, - 'MATCH_SEQUENCE': 26, - 'NOP': 27, - 'NOT_TAKEN': 28, - 'POP_EXCEPT': 29, - 'POP_ITER': 30, - 'POP_TOP': 31, - 'PUSH_EXC_INFO': 32, - 'PUSH_NULL': 33, - 'RETURN_GENERATOR': 34, - 'RETURN_VALUE': 35, - 'SETUP_ANNOTATIONS': 36, - 'STORE_SLICE': 37, - 'STORE_SUBSCR': 38, - 'TO_BOOL': 39, - 'UNARY_INVERT': 40, - 'UNARY_NEGATIVE': 41, - 'UNARY_NOT': 42, - 'WITH_EXCEPT_START': 43, - 'BINARY_OP': 44, - 'BUILD_INTERPOLATION': 45, - 'BUILD_LIST': 46, - 'BUILD_MAP': 47, - 'BUILD_SET': 48, - 'BUILD_SLICE': 49, - 'BUILD_STRING': 50, - 'BUILD_TUPLE': 51, - 'CALL': 52, - 'CALL_INTRINSIC_1': 53, - 'CALL_INTRINSIC_2': 54, - 'CALL_KW': 55, - 'COMPARE_OP': 56, - 'CONTAINS_OP': 57, - 'CONVERT_VALUE': 58, - 'COPY': 59, - 'COPY_FREE_VARS': 60, - 'DELETE_ATTR': 61, - 'DELETE_DEREF': 62, - 'DELETE_FAST': 63, - 'DELETE_GLOBAL': 64, - 'DELETE_NAME': 65, - 'DICT_MERGE': 66, - 'DICT_UPDATE': 67, - 'END_ASYNC_FOR': 68, - 'EXTENDED_ARG': 69, - 'FOR_ITER': 70, - 'GET_AWAITABLE': 71, - 'IMPORT_FROM': 72, - 'IMPORT_NAME': 73, - 'IS_OP': 74, - 'JUMP_BACKWARD': 75, - 'JUMP_BACKWARD_NO_INTERRUPT': 76, - 'JUMP_FORWARD': 77, - 'LIST_APPEND': 78, - 'LIST_EXTEND': 79, - 'LOAD_ATTR': 80, - 'LOAD_COMMON_CONSTANT': 81, - 'LOAD_CONST': 82, - 'LOAD_DEREF': 83, - 'LOAD_FAST': 84, - 'LOAD_FAST_AND_CLEAR': 85, - 'LOAD_FAST_BORROW': 86, - 'LOAD_FAST_BORROW_LOAD_FAST_BORROW': 87, - 'LOAD_FAST_CHECK': 88, - 'LOAD_FAST_LOAD_FAST': 89, - 'LOAD_FROM_DICT_OR_DEREF': 90, - 'LOAD_FROM_DICT_OR_GLOBALS': 91, - 'LOAD_GLOBAL': 92, - 'LOAD_NAME': 93, - 'LOAD_SMALL_INT': 94, - 'LOAD_SPECIAL': 95, - 'LOAD_SUPER_ATTR': 96, - 'MAKE_CELL': 97, - 'MAP_ADD': 98, - 'MATCH_CLASS': 99, - 'POP_JUMP_IF_FALSE': 100, - 'POP_JUMP_IF_NONE': 101, - 'POP_JUMP_IF_NOT_NONE': 102, - 'POP_JUMP_IF_TRUE': 103, - 'RAISE_VARARGS': 104, - 'RERAISE': 105, - 'SEND': 106, - 'SET_ADD': 107, - 'SET_FUNCTION_ATTRIBUTE': 108, - 'SET_UPDATE': 109, - 'STORE_ATTR': 110, - 'STORE_DEREF': 111, - 'STORE_FAST': 112, - 'STORE_FAST_LOAD_FAST': 113, - 'STORE_FAST_STORE_FAST': 114, - 'STORE_GLOBAL': 115, - 'STORE_NAME': 116, - 'SWAP': 117, - 'UNPACK_EX': 118, - 'UNPACK_SEQUENCE': 119, - 'YIELD_VALUE': 120, - 'INSTRUMENTED_END_FOR': 233, - 'INSTRUMENTED_POP_ITER': 234, - 'INSTRUMENTED_END_SEND': 235, - 'INSTRUMENTED_FOR_ITER': 236, - 'INSTRUMENTED_INSTRUCTION': 237, - 'INSTRUMENTED_JUMP_FORWARD': 238, - 'INSTRUMENTED_NOT_TAKEN': 239, - 'INSTRUMENTED_POP_JUMP_IF_TRUE': 240, - 'INSTRUMENTED_POP_JUMP_IF_FALSE': 241, - 'INSTRUMENTED_POP_JUMP_IF_NONE': 242, - 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 243, - 'INSTRUMENTED_RESUME': 244, - 'INSTRUMENTED_RETURN_VALUE': 245, - 'INSTRUMENTED_YIELD_VALUE': 246, - 'INSTRUMENTED_END_ASYNC_FOR': 247, - 'INSTRUMENTED_LOAD_SUPER_ATTR': 248, - 'INSTRUMENTED_CALL': 249, - 'INSTRUMENTED_CALL_KW': 250, - 'INSTRUMENTED_CALL_FUNCTION_EX': 251, - 'INSTRUMENTED_JUMP_BACKWARD': 252, - 'ANNOTATIONS_PLACEHOLDER': 256, - 'JUMP': 257, - 'JUMP_IF_FALSE': 258, - 'JUMP_IF_TRUE': 259, - 'JUMP_NO_INTERRUPT': 260, - 'LOAD_CLOSURE': 261, - 'POP_BLOCK': 262, - 'SETUP_CLEANUP': 263, - 'SETUP_FINALLY': 264, - 'SETUP_WITH': 265, - 'STORE_FAST_MAYBE_NULL': 266, -} +opmap = frozendict( + CACHE=0, + RESERVED=17, + RESUME=128, + INSTRUMENTED_LINE=253, + ENTER_EXECUTOR=254, + TRACE_RECORD=255, + BINARY_SLICE=1, + BUILD_TEMPLATE=2, + CALL_FUNCTION_EX=4, + CHECK_EG_MATCH=5, + CHECK_EXC_MATCH=6, + CLEANUP_THROW=7, + DELETE_SUBSCR=8, + END_FOR=9, + END_SEND=10, + EXIT_INIT_CHECK=11, + FORMAT_SIMPLE=12, + FORMAT_WITH_SPEC=13, + GET_AITER=14, + GET_ANEXT=15, + GET_ITER=16, + GET_LEN=18, + GET_YIELD_FROM_ITER=19, + INTERPRETER_EXIT=20, + LOAD_BUILD_CLASS=21, + LOAD_LOCALS=22, + MAKE_FUNCTION=23, + MATCH_KEYS=24, + MATCH_MAPPING=25, + MATCH_SEQUENCE=26, + NOP=27, + NOT_TAKEN=28, + POP_EXCEPT=29, + POP_ITER=30, + POP_TOP=31, + PUSH_EXC_INFO=32, + PUSH_NULL=33, + RETURN_GENERATOR=34, + RETURN_VALUE=35, + SETUP_ANNOTATIONS=36, + STORE_SLICE=37, + STORE_SUBSCR=38, + TO_BOOL=39, + UNARY_INVERT=40, + UNARY_NEGATIVE=41, + UNARY_NOT=42, + WITH_EXCEPT_START=43, + BINARY_OP=44, + BUILD_INTERPOLATION=45, + BUILD_LIST=46, + BUILD_MAP=47, + BUILD_SET=48, + BUILD_SLICE=49, + BUILD_STRING=50, + BUILD_TUPLE=51, + CALL=52, + CALL_INTRINSIC_1=53, + CALL_INTRINSIC_2=54, + CALL_KW=55, + COMPARE_OP=56, + CONTAINS_OP=57, + CONVERT_VALUE=58, + COPY=59, + COPY_FREE_VARS=60, + DELETE_ATTR=61, + DELETE_DEREF=62, + DELETE_FAST=63, + DELETE_GLOBAL=64, + DELETE_NAME=65, + DICT_MERGE=66, + DICT_UPDATE=67, + END_ASYNC_FOR=68, + EXTENDED_ARG=69, + FOR_ITER=70, + GET_AWAITABLE=71, + IMPORT_FROM=72, + IMPORT_NAME=73, + IS_OP=74, + JUMP_BACKWARD=75, + JUMP_BACKWARD_NO_INTERRUPT=76, + JUMP_FORWARD=77, + LIST_APPEND=78, + LIST_EXTEND=79, + LOAD_ATTR=80, + LOAD_COMMON_CONSTANT=81, + LOAD_CONST=82, + LOAD_DEREF=83, + LOAD_FAST=84, + LOAD_FAST_AND_CLEAR=85, + LOAD_FAST_BORROW=86, + LOAD_FAST_BORROW_LOAD_FAST_BORROW=87, + LOAD_FAST_CHECK=88, + LOAD_FAST_LOAD_FAST=89, + LOAD_FROM_DICT_OR_DEREF=90, + LOAD_FROM_DICT_OR_GLOBALS=91, + LOAD_GLOBAL=92, + LOAD_NAME=93, + LOAD_SMALL_INT=94, + LOAD_SPECIAL=95, + LOAD_SUPER_ATTR=96, + MAKE_CELL=97, + MAP_ADD=98, + MATCH_CLASS=99, + POP_JUMP_IF_FALSE=100, + POP_JUMP_IF_NONE=101, + POP_JUMP_IF_NOT_NONE=102, + POP_JUMP_IF_TRUE=103, + RAISE_VARARGS=104, + RERAISE=105, + SEND=106, + SET_ADD=107, + SET_FUNCTION_ATTRIBUTE=108, + SET_UPDATE=109, + STORE_ATTR=110, + STORE_DEREF=111, + STORE_FAST=112, + STORE_FAST_LOAD_FAST=113, + STORE_FAST_STORE_FAST=114, + STORE_GLOBAL=115, + STORE_NAME=116, + SWAP=117, + UNPACK_EX=118, + UNPACK_SEQUENCE=119, + YIELD_VALUE=120, + INSTRUMENTED_END_FOR=233, + INSTRUMENTED_POP_ITER=234, + INSTRUMENTED_END_SEND=235, + INSTRUMENTED_FOR_ITER=236, + INSTRUMENTED_INSTRUCTION=237, + INSTRUMENTED_JUMP_FORWARD=238, + INSTRUMENTED_NOT_TAKEN=239, + INSTRUMENTED_POP_JUMP_IF_TRUE=240, + INSTRUMENTED_POP_JUMP_IF_FALSE=241, + INSTRUMENTED_POP_JUMP_IF_NONE=242, + INSTRUMENTED_POP_JUMP_IF_NOT_NONE=243, + INSTRUMENTED_RESUME=244, + INSTRUMENTED_RETURN_VALUE=245, + INSTRUMENTED_YIELD_VALUE=246, + INSTRUMENTED_END_ASYNC_FOR=247, + INSTRUMENTED_LOAD_SUPER_ATTR=248, + INSTRUMENTED_CALL=249, + INSTRUMENTED_CALL_KW=250, + INSTRUMENTED_CALL_FUNCTION_EX=251, + INSTRUMENTED_JUMP_BACKWARD=252, + ANNOTATIONS_PLACEHOLDER=256, + JUMP=257, + JUMP_IF_FALSE=258, + JUMP_IF_TRUE=259, + JUMP_NO_INTERRUPT=260, + LOAD_CLOSURE=261, + POP_BLOCK=262, + SETUP_CLEANUP=263, + SETUP_FINALLY=264, + SETUP_WITH=265, + STORE_FAST_MAYBE_NULL=266, +) HAVE_ARGUMENT = 43 MIN_INSTRUMENTED_OPCODE = 233 diff --git a/Tools/cases_generator/py_metadata_generator.py b/Tools/cases_generator/py_metadata_generator.py index 3ec06faf338..6df72de44e7 100644 --- a/Tools/cases_generator/py_metadata_generator.py +++ b/Tools/cases_generator/py_metadata_generator.py @@ -30,35 +30,43 @@ def get_specialized(analysis: Analysis) -> set[str]: def generate_specializations(analysis: Analysis, out: CWriter) -> None: - out.emit("_specializations = {\n") + out.emit("_specializations = frozendict(\n") for family in analysis.families.values(): - out.emit(f'"{family.name}": [\n') + out.emit(f'{family.name}=(\n') + seen = set() for member in family.members: + if member.name in seen: + continue + seen.add(member.name) out.emit(f' "{member.name}",\n') - out.emit("],\n") - out.emit("}\n\n") + out.emit("),\n") + out.emit(")\n\n") def generate_specialized_opmap(analysis: Analysis, out: CWriter) -> None: - out.emit("_specialized_opmap = {\n") + out.emit("_specialized_opmap = frozendict(\n") names = [] + seen = set() for family in analysis.families.values(): for member in family.members: if member.name == family.name: continue + if member.name in seen: + continue + seen.add(member.name) names.append(member.name) for name in sorted(names): - out.emit(f"'{name}': {analysis.opmap[name]},\n") - out.emit("}\n\n") + out.emit(f"{name}={analysis.opmap[name]},\n") + out.emit(")\n\n") def generate_opmap(analysis: Analysis, out: CWriter) -> None: specialized = get_specialized(analysis) - out.emit("opmap = {\n") + out.emit("opmap = frozendict(\n") for inst, op in analysis.opmap.items(): if inst not in specialized: - out.emit(f"'{inst}': {analysis.opmap[inst]},\n") - out.emit("}\n\n") + out.emit(f"{inst}={analysis.opmap[inst]},\n") + out.emit(")\n\n") def generate_py_metadata( From c0ecf211b26978859c5112458bcd01d883e04b42 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 12:35:43 +0100 Subject: [PATCH 007/775] gh-145055: Accept frozendict for globals in exec() and eval() (#145072) --- Doc/library/functions.rst | 10 +++++++- Include/internal/pycore_dict.h | 4 +-- Lib/test/test_builtin.py | 25 +++++++++++++++++++ ...-02-21-12-16-46.gh-issue-145055.VyT-zI.rst | 2 ++ Objects/codeobject.c | 2 +- Objects/dictobject.c | 2 +- Objects/funcobject.c | 2 +- Python/_warnings.c | 9 ++++--- Python/bltinmodule.c | 14 ++++++----- Python/ceval.c | 8 ++++-- Python/import.c | 5 ++-- Python/pythonrun.c | 5 ++-- 12 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 65b8ffdb231..d9a2eff667e 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -594,7 +594,7 @@ are always available. They are listed here in alphabetical order. :param globals: The global namespace (default: ``None``). - :type globals: :class:`dict` | ``None`` + :type globals: :class:`dict` | :class:`frozendict` | ``None`` :param locals: The local namespace (default: ``None``). @@ -660,6 +660,10 @@ are always available. They are listed here in alphabetical order. The semantics of the default *locals* namespace have been adjusted as described for the :func:`locals` builtin. + .. versionchanged:: next + + *globals* can now be a :class:`frozendict`. + .. index:: pair: built-in function; exec .. function:: exec(source, /, globals=None, locals=None, *, closure=None) @@ -737,6 +741,10 @@ are always available. They are listed here in alphabetical order. The semantics of the default *locals* namespace have been adjusted as described for the :func:`locals` builtin. + .. versionchanged:: next + + *globals* can now be a :class:`frozendict`. + .. function:: filter(function, iterable, /) diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 1aeec32f55a..a2c5ee41c37 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -372,7 +372,7 @@ _PyDict_UniqueId(PyDictObject *mp) static inline void _Py_INCREF_DICT(PyObject *op) { - assert(PyDict_Check(op)); + assert(PyAnyDict_Check(op)); Py_ssize_t id = _PyDict_UniqueId((PyDictObject *)op); _Py_THREAD_INCREF_OBJECT(op, id); } @@ -380,7 +380,7 @@ _Py_INCREF_DICT(PyObject *op) static inline void _Py_DECREF_DICT(PyObject *op) { - assert(PyDict_Check(op)); + assert(PyAnyDict_Check(op)); Py_ssize_t id = _PyDict_UniqueId((PyDictObject *)op); _Py_THREAD_DECREF_OBJECT(op, id); } diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index eabfdcd447f..844656eb0e2 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -784,6 +784,16 @@ def __getitem__(self, key): raise ValueError self.assertRaises(ValueError, eval, "foo", {}, X()) + def test_eval_frozendict(self): + ns = frozendict(x=1, data=[], __builtins__=__builtins__) + eval("data.append(x)", ns, ns) + self.assertEqual(ns['data'], [1]) + + ns = frozendict() + errmsg = "cannot assign __builtins__ to frozendict globals" + with self.assertRaisesRegex(TypeError, errmsg): + eval("", ns, ns) + def test_eval_kwargs(self): data = {"A_GLOBAL_VALUE": 456} self.assertEqual(eval("globals()['A_GLOBAL_VALUE']", globals=data), 456) @@ -882,6 +892,21 @@ def test_exec(self): del l['__builtins__'] self.assertEqual((g, l), ({'a': 1}, {'b': 2})) + def test_exec_frozendict(self): + ns = frozendict(x=1, data=[], __builtins__=__builtins__) + exec("data.append(x)", ns, ns) + self.assertEqual(ns['data'], [1]) + + ns = frozendict(__builtins__=__builtins__) + errmsg = "'frozendict' object does not support item assignment" + with self.assertRaisesRegex(TypeError, errmsg): + exec("x = 1", ns, ns) + + ns = frozendict() + errmsg = "cannot assign __builtins__ to frozendict globals" + with self.assertRaisesRegex(TypeError, errmsg): + exec("", ns, ns) + def test_exec_kwargs(self): g = {} exec('global z\nz = 1', globals=g) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst new file mode 100644 index 00000000000..c9daaa27717 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst @@ -0,0 +1,2 @@ +:func:`exec` and :func:`eval` now accept :class:`frozendict` for *globals*. +Patch by Victor Stinner. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 520190824fb..d26516f7c2f 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -1830,7 +1830,7 @@ identify_unbound_names(PyThreadState *tstate, PyCodeObject *co, assert(attrnames != NULL); assert(PySet_Check(attrnames)); assert(PySet_GET_SIZE(attrnames) == 0 || counts != NULL); - assert(globalsns == NULL || PyDict_Check(globalsns)); + assert(globalsns == NULL || PyAnyDict_Check(globalsns)); assert(builtinsns == NULL || PyDict_Check(builtinsns)); assert(counts == NULL || counts->total == 0); struct co_unbound_counts unbound = {0}; diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e0127f04249..14019e4f1d9 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2687,7 +2687,7 @@ _PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObje PyObject * _PyDict_LoadBuiltinsFromGlobals(PyObject *globals) { - if (!PyDict_Check(globals)) { + if (!PyAnyDict_Check(globals)) { PyErr_BadInternalCall(); return NULL; } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index efe27a2b70c..fc32826fb3a 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -150,7 +150,7 @@ PyObject * PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) { assert(globals != NULL); - assert(PyDict_Check(globals)); + assert(PyAnyDict_Check(globals)); _Py_INCREF_DICT(globals); PyCodeObject *code_obj = (PyCodeObject *)code; diff --git a/Python/_warnings.c b/Python/_warnings.c index d44d414bc93..0ea785772f0 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1045,7 +1045,7 @@ setup_context(Py_ssize_t stack_level, /* Setup registry. */ assert(globals != NULL); - assert(PyDict_Check(globals)); + assert(PyAnyDict_Check(globals)); int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__), registry); if (rc < 0) { @@ -1269,10 +1269,11 @@ warnings_warn_explicit_impl(PyObject *module, PyObject *message, } if (module_globals && module_globals != Py_None) { - if (!PyDict_Check(module_globals)) { + if (!PyAnyDict_Check(module_globals)) { PyErr_Format(PyExc_TypeError, - "module_globals must be a dict, not '%.200s'", - Py_TYPE(module_globals)->tp_name); + "module_globals must be a dict or a frozendict, " + "not %T", + module_globals); return NULL; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 301125051f3..fc69f637202 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1040,10 +1040,11 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals, PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); return NULL; } - if (globals != Py_None && !PyDict_Check(globals)) { + if (globals != Py_None && !PyAnyDict_Check(globals)) { PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ? - "globals must be a real dict; try eval(expr, {}, mapping)" - : "globals must be a dict"); + "globals must be a real dict or a frozendict; " + "try eval(expr, {}, mapping)" + : "globals must be a dict or a frozendict"); return NULL; } @@ -1197,9 +1198,10 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals, locals = Py_NewRef(globals); } - if (!PyDict_Check(globals)) { - PyErr_Format(PyExc_TypeError, "exec() globals must be a dict, not %.100s", - Py_TYPE(globals)->tp_name); + if (!PyAnyDict_Check(globals)) { + PyErr_Format(PyExc_TypeError, + "exec() globals must be a dict or a frozendict, not %T", + globals); goto error; } if (!PyMapping_Check(locals)) { diff --git a/Python/ceval.c b/Python/ceval.c index 3ad46cf1ec8..1e5142f4b45 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2718,7 +2718,7 @@ static PyObject * get_globals_builtins(PyObject *globals) { PyObject *builtins = NULL; - if (PyDict_Check(globals)) { + if (PyAnyDict_Check(globals)) { if (PyDict_GetItemRef(globals, &_Py_ID(__builtins__), &builtins) < 0) { return NULL; } @@ -2743,6 +2743,10 @@ set_globals_builtins(PyObject *globals, PyObject *builtins) } else { if (PyObject_SetItem(globals, &_Py_ID(__builtins__), builtins) < 0) { + if (PyFrozenDict_Check(globals)) { + PyErr_SetString(PyExc_TypeError, + "cannot assign __builtins__ to frozendict globals"); + } return -1; } } @@ -3584,7 +3588,7 @@ _PyEval_GetANext(PyObject *aiter) void _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name, _PyStackRef *writeto) { - if (PyDict_CheckExact(globals) && PyDict_CheckExact(builtins)) { + if (PyAnyDict_CheckExact(globals) && PyAnyDict_CheckExact(builtins)) { _PyDict_LoadGlobalStackRef((PyDictObject *)globals, (PyDictObject *)builtins, name, writeto); diff --git a/Python/import.c b/Python/import.c index 3ed808f67f4..34224f4c6d6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3728,8 +3728,9 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level _PyErr_SetString(tstate, PyExc_KeyError, "'__name__' not in globals"); goto error; } - if (!PyDict_Check(globals)) { - _PyErr_SetString(tstate, PyExc_TypeError, "globals must be a dict"); + if (!PyAnyDict_Check(globals)) { + _PyErr_SetString(tstate, PyExc_TypeError, + "globals must be a dict or a frozendict"); goto error; } if (PyDict_GetItemRef(globals, &_Py_ID(__package__), &package) < 0) { diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 043bdf3433a..a21f494dc69 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1348,8 +1348,9 @@ static PyObject * run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, PyObject *locals) { /* Set globals['__builtins__'] if it doesn't exist */ - if (!globals || !PyDict_Check(globals)) { - PyErr_SetString(PyExc_SystemError, "globals must be a real dict"); + if (!globals || !PyAnyDict_Check(globals)) { + PyErr_SetString(PyExc_SystemError, + "globals must be a real dict or a real frozendict"); return NULL; } int has_builtins = PyDict_ContainsString(globals, "__builtins__"); From 7bdfce0d3a1696ed08ffa16e4574428ef09a6b40 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 12:55:28 +0100 Subject: [PATCH 008/775] gh-145056: Accept frozendict in xml.etree (#145508) Element and SubElement of xml.etree.ElementTree now also accept frozendict for attrib. Export _PyDict_CopyAsDict() function. --- Doc/library/xml.etree.elementtree.rst | 6 ++++++ Include/internal/pycore_dict.h | 3 ++- Lib/test/test_xml_etree.py | 11 +++++++++-- Lib/xml/etree/ElementTree.py | 4 ++-- Modules/_elementtree.c | 26 +++++++++++++++++--------- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index e021a81d2a2..45abf5b1e73 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -702,6 +702,9 @@ Functions attributes. *extra* contains additional attributes, given as keyword arguments. Returns an element instance. + .. versionchanged:: next + *attrib* can now be a :class:`frozendict`. + .. function:: tostring(element, encoding="us-ascii", method="xml", *, \ xml_declaration=None, default_namespace=None, \ @@ -887,6 +890,9 @@ Element Objects an optional dictionary, containing element attributes. *extra* contains additional attributes, given as keyword arguments. + .. versionchanged:: next + *attrib* can now be a :class:`frozendict`. + .. attribute:: tag diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index a2c5ee41c37..6d7d68eda84 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -160,7 +160,8 @@ extern void _PyDict_Clear_LockHeld(PyObject *op); PyAPI_FUNC(void) _PyDict_EnsureSharedOnRead(PyDictObject *mp); #endif -extern PyObject* _PyDict_CopyAsDict(PyObject *op); +// Export for '_elementtree' shared extension +PyAPI_FUNC(PyObject*) _PyDict_CopyAsDict(PyObject *op); #define DKIX_EMPTY (-1) #define DKIX_DUMMY (-2) /* Used internally */ diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 93162f52ba0..5b06e422672 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -4472,6 +4472,9 @@ def test_issue14818(self): ET.Element('a', dict(href="#"), id="foo"), ET.Element('a', href="#", id="foo"), ET.Element('a', dict(href="#", id="foo"), href="#", id="foo"), + ET.Element('a', frozendict(href="#", id="foo")), + ET.Element('a', frozendict(href="#"), id="foo"), + ET.Element('a', attrib=frozendict(href="#", id="foo")), ] for e in elements: self.assertEqual(e.tag, 'a') @@ -4479,10 +4482,14 @@ def test_issue14818(self): e2 = ET.SubElement(elements[0], 'foobar', attrib={'key1': 'value1'}) self.assertEqual(e2.attrib['key1'], 'value1') + e3 = ET.SubElement(elements[0], 'foobar', + attrib=frozendict({'key1': 'value1'})) + self.assertEqual(e3.attrib['key1'], 'value1') - with self.assertRaisesRegex(TypeError, 'must be dict, not str'): + errmsg = 'must be dict or frozendict, not str' + with self.assertRaisesRegex(TypeError, errmsg): ET.Element('a', "I'm not a dict") - with self.assertRaisesRegex(TypeError, 'must be dict, not str'): + with self.assertRaisesRegex(TypeError, errmsg): ET.Element('a', attrib="I'm not a dict") # -------------------------------------------------------------------- diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index e3d81a2c456..57c5b64ea3b 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -165,8 +165,8 @@ class Element: """ def __init__(self, tag, attrib={}, **extra): - if not isinstance(attrib, dict): - raise TypeError("attrib must be dict, not %s" % ( + if not isinstance(attrib, (dict, frozendict)): + raise TypeError("attrib must be dict or frozendict, not %s" % ( attrib.__class__.__name__,)) self.tag = tag self.attrib = {**attrib, **extra} diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index f60a4c295e6..e0bc69c5fe2 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -16,6 +16,7 @@ #endif #include "Python.h" +#include "pycore_dict.h" // _PyDict_CopyAsDict() #include "pycore_pyhash.h" // _Py_HashSecret #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() @@ -382,13 +383,14 @@ get_attrib_from_keywords(PyObject *kwds) /* If attrib was found in kwds, copy its value and remove it from * kwds */ - if (!PyDict_Check(attrib)) { - PyErr_Format(PyExc_TypeError, "attrib must be dict, not %.100s", - Py_TYPE(attrib)->tp_name); + if (!PyAnyDict_Check(attrib)) { + PyErr_Format(PyExc_TypeError, + "attrib must be dict or frozendict, not %T", + attrib); Py_DECREF(attrib); return NULL; } - Py_SETREF(attrib, PyDict_Copy(attrib)); + Py_SETREF(attrib, _PyDict_CopyAsDict(attrib)); } else { attrib = PyDict_New(); @@ -416,12 +418,18 @@ element_init(PyObject *self, PyObject *args, PyObject *kwds) PyObject *attrib = NULL; ElementObject *self_elem; - if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib)) + if (!PyArg_ParseTuple(args, "O|O:Element", &tag, &attrib)) return -1; + if (attrib != NULL && !PyAnyDict_Check(attrib)) { + PyErr_Format(PyExc_TypeError, + "Element() argument 2 must be dict or frozendict, not %T", + attrib); + return -1; + } if (attrib) { /* attrib passed as positional arg */ - attrib = PyDict_Copy(attrib); + attrib = _PyDict_CopyAsDict(attrib); if (!attrib) return -1; if (kwds) { @@ -2111,10 +2119,10 @@ static int element_attrib_setter(PyObject *op, PyObject *value, void *closure) { _VALIDATE_ATTR_VALUE(value); - if (!PyDict_Check(value)) { + if (!PyAnyDict_Check(value)) { PyErr_Format(PyExc_TypeError, - "attrib must be dict, not %.200s", - Py_TYPE(value)->tp_name); + "attrib must be dict or frozendict, not %T", + value); return -1; } ElementObject *self = _Element_CAST(op); From 11840ca99ae809c1c8401b4f34d2820de55e27a0 Mon Sep 17 00:00:00 2001 From: Xianpeng Shen Date: Thu, 5 Mar 2026 14:23:06 +0200 Subject: [PATCH 009/775] gh-140681: Freeze pre-commit hooks and update zizmor links (#140682) Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- .github/actionlint.yaml | 4 ---- .github/zizmor.yml | 2 +- .pre-commit-config.yaml | 18 +++++++++--------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 675712d65d4..eacfff24889 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -1,7 +1,3 @@ -self-hosted-runner: - # Pending https://github.com/rhysd/actionlint/pull/615 - labels: ["windows-2025-vs2026"] - config-variables: null paths: diff --git a/.github/zizmor.yml b/.github/zizmor.yml index fab3abcb355..8b7b4de0fc8 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -1,5 +1,5 @@ # Configuration for the zizmor static analysis tool, run via prek in CI -# https://woodruffw.github.io/zizmor/configuration/ +# https://docs.zizmor.sh/configuration/ rules: dangerous-triggers: ignore: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4893ec28f23..dfd18182105 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.0 + rev: a27a2e47c7751b639d2b5badf0ef6ff11fee893f # frozen: v0.15.4 hooks: - id: ruff-check name: Run Ruff (lint) on Apple/ @@ -60,20 +60,20 @@ repos: files: ^Tools/wasm/ - repo: https://github.com/psf/black-pre-commit-mirror - rev: 26.1.0 + rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0 hooks: - id: black name: Run Black on Tools/jit/ files: ^Tools/jit/ - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.6 + rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8 # frozen: v1.5.6 hooks: - id: remove-tabs types: [python] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0 hooks: - id: check-case-conflict - id: check-merge-conflict @@ -91,24 +91,24 @@ repos: files: '^\.github/CODEOWNERS|\.(gram)$' - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.36.1 + rev: 9f48a48aa91a6040d749ad68ec70907d907a5a7f # frozen: 0.37.0 hooks: - id: check-dependabot - id: check-github-workflows - id: check-readthedocs - repo: https://github.com/rhysd/actionlint - rev: v1.7.10 + rev: 393031adb9afb225ee52ae2ccd7a5af5525e03e8 # frozen: v1.7.11 hooks: - id: actionlint - - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.22.0 + - repo: https://github.com/zizmorcore/zizmor-pre-commit + rev: b546b77c44c466a54a42af5499dcc0dcc1a3193f # frozen: v1.22.0 hooks: - id: zizmor - repo: https://github.com/sphinx-contrib/sphinx-lint - rev: v1.0.2 + rev: c883505f64b59c3c5c9375191e4ad9f98e727ccd # frozen: v1.0.2 hooks: - id: sphinx-lint args: [--enable=default-role] From 2cd0ddfe04afbe38bfbe73de1050ea5d1185f4b6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 14:14:04 +0100 Subject: [PATCH 010/775] gh-141510: Fix frozendict.items() ^ frozendict.items() (#145535) Add non-regression tests. --- Lib/test/test_dict.py | 13 +++++++++++++ Objects/dictobject.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 162b0b38f85..45448d1264a 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1848,11 +1848,19 @@ def test_merge(self): frozendict({'x': 1, 'y': 2})) self.assertEqual(frozendict(x=1, y=2) | frozendict(y=5), frozendict({'x': 1, 'y': 5})) + self.assertEqual(FrozenDict(x=1, y=2) | FrozenDict(y=5), + frozendict({'x': 1, 'y': 5})) + fd = frozendict(x=1, y=2) self.assertIs(fd | frozendict(), fd) self.assertIs(fd | {}, fd) self.assertIs(frozendict() | fd, fd) + fd = FrozenDict(x=1, y=2) + self.assertEqual(fd | frozendict(), fd) + self.assertEqual(fd | {}, fd) + self.assertEqual(frozendict() | fd, fd) + def test_update(self): # test "a |= b" operator d = frozendict(x=1) @@ -1863,6 +1871,11 @@ def test_update(self): self.assertEqual(d, frozendict({'x': 1, 'y': 2})) self.assertEqual(copy, frozendict({'x': 1})) + def test_items_xor(self): + # test "a ^ b" operator on items views + res = frozendict(a=1, b=2).items() ^ frozendict(b=2, c=3).items() + self.assertEqual(res, {('a', 1), ('c', 3)}) + def test_repr(self): d = frozendict() self.assertEqual(repr(d), "frozendict()") diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 14019e4f1d9..d86ab2634a9 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -6523,7 +6523,7 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2) ASSERT_DICT_LOCKED(d1); ASSERT_DICT_LOCKED(d2); - PyObject *temp_dict = copy_lock_held(d1, PyFrozenDict_Check(d1)); + PyObject *temp_dict = copy_lock_held(d1, 0); if (temp_dict == NULL) { return NULL; } From dbe0007ab2ff679c85d88e62fb875437b2dc2522 Mon Sep 17 00:00:00 2001 From: Shrey Naithani Date: Thu, 5 Mar 2026 19:49:49 +0530 Subject: [PATCH 011/775] gh-145417: Do not preserve SELinux context when copying venv scripts (#145454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Miro Hrončok Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Victor Stinner --- Lib/test/test_venv.py | 12 +++++++++++- Lib/venv/__init__.py | 2 +- .../2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst | 4 ++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 68bcf535ead..78461abcd69 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -11,12 +11,12 @@ import os.path import pathlib import re +import shlex import shutil import subprocess import sys import sysconfig import tempfile -import shlex from test.support import (captured_stdout, captured_stderr, skip_if_broken_multiprocessing_synchronize, verbose, requires_subprocess, is_android, is_apple_mobile, @@ -373,6 +373,16 @@ def create_contents(self, paths, filename): with open(fn, 'wb') as f: f.write(b'Still here?') + @unittest.skipUnless(hasattr(os, 'listxattr'), 'test requires os.listxattr') + def test_install_scripts_selinux(self): + """ + gh-145417: Test that install_scripts does not copy SELinux context + when copying scripts. + """ + with patch('os.listxattr') as listxattr_mock: + venv.create(self.env_dir) + listxattr_mock.assert_not_called() + def test_overwrite_existing(self): """ Test creating environment in an existing directory. diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 19eddde700b..21f82125f5a 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -581,7 +581,7 @@ def skip_file(f): 'may be binary: %s', srcfile, e) continue if new_data == data: - shutil.copy2(srcfile, dstfile) + shutil.copy(srcfile, dstfile) else: with open(dstfile, 'wb') as f: f.write(new_data) diff --git a/Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst b/Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst new file mode 100644 index 00000000000..17d62df72ce --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst @@ -0,0 +1,4 @@ +:mod:`venv`: Prevent incorrect preservation of SELinux context +when copying the ``Activate.ps1`` script. The script inherited +the SELinux security context of the system template directory, +rather than the destination project directory. From 0c29f83caa053c437131972147935c02e4e06630 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 15:26:54 +0100 Subject: [PATCH 012/775] gh-141510: No longer accept frozendict in PyDict_Copy() (#145542) Rename _PyDict_Copy() to anydict_copy(). Replace PyObject_IsInstance(op, &PyFrozenDict_Type) with PyFrozenDict_Check(). --- Doc/c-api/dict.rst | 4 -- Lib/test/test_capi/test_dict.py | 16 ++------ Objects/clinic/dictobject.c.h | 20 +++++++++- Objects/dictobject.c | 66 ++++++++++++++++++++++----------- 4 files changed, 67 insertions(+), 39 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 734462bc005..371761573e9 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -82,10 +82,6 @@ Dictionary objects Return a new dictionary that contains the same key-value pairs as *p*. - .. versionchanged:: next - If *p* is a subclass of :class:`frozendict`, the result will be a - :class:`frozendict` instance instead of a :class:`dict` instance. - .. c:function:: int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val) Insert *val* into the dictionary *p* with a key of *key*. *key* must be diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py index 561e1ea4d52..5bdf74ef73a 100644 --- a/Lib/test/test_capi/test_dict.py +++ b/Lib/test/test_capi/test_dict.py @@ -97,21 +97,13 @@ def test_dictproxy_new(self): def test_dict_copy(self): # Test PyDict_Copy() copy = _testlimitedcapi.dict_copy - for dict_type in ANYDICT_TYPES: + for dict_type in DICT_TYPES: dct = dict_type({1: 2}) dct_copy = copy(dct) - if dict_type == frozendict: - expected_type = frozendict - self.assertIs(dct_copy, dct) - else: - if issubclass(dict_type, frozendict): - expected_type = frozendict - else: - expected_type = dict - self.assertIs(type(dct_copy), expected_type) - self.assertEqual(dct_copy, dct) + self.assertIs(type(dct_copy), dict) + self.assertEqual(dct_copy, dct) - for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: + for test_type in NOT_DICT_TYPES + OTHER_TYPES: self.assertRaises(SystemError, copy, test_type()) self.assertRaises(SystemError, copy, NULL) diff --git a/Objects/clinic/dictobject.c.h b/Objects/clinic/dictobject.c.h index abf6b38449f..15b8705d9c7 100644 --- a/Objects/clinic/dictobject.c.h +++ b/Objects/clinic/dictobject.c.h @@ -323,4 +323,22 @@ dict_values(PyObject *self, PyObject *Py_UNUSED(ignored)) { return dict_values_impl((PyDictObject *)self); } -/*[clinic end generated code: output=9007b74432217017 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(frozendict_copy__doc__, +"copy($self, /)\n" +"--\n" +"\n" +"Return a shallow copy of the frozendict."); + +#define FROZENDICT_COPY_METHODDEF \ + {"copy", (PyCFunction)frozendict_copy, METH_NOARGS, frozendict_copy__doc__}, + +static PyObject * +frozendict_copy_impl(PyFrozenDictObject *self); + +static PyObject * +frozendict_copy(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return frozendict_copy_impl((PyFrozenDictObject *)self); +} +/*[clinic end generated code: output=f4c88a3464928ae3 input=a9049054013a1b77]*/ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index d86ab2634a9..61fde37f8d4 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -146,8 +146,9 @@ static int dict_merge_from_seq2(PyObject *d, PyObject *seq2, int override); /*[clinic input] class dict "PyDictObject *" "&PyDict_Type" +class frozendict "PyFrozenDictObject *" "&PyFrozenDict_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5dfa93bac68e7c54]*/ /* @@ -2406,7 +2407,7 @@ dict_unhashable_type(PyObject *op, PyObject *key) } const char *errmsg; - if (PyObject_IsInstance(op, (PyObject*)&PyFrozenDict_Type)) { + if (PyFrozenDict_Check(op)) { errmsg = "cannot use '%T' as a frozendict key (%S)"; } else { @@ -4384,9 +4385,25 @@ copy_lock_held(PyObject *o, int as_frozendict) return NULL; } -// Similar to PyDict_Copy(), but copy also frozendict. +PyObject * +PyDict_Copy(PyObject *o) +{ + if (o == NULL || !PyDict_Check(o)) { + PyErr_BadInternalCall(); + return NULL; + } + + PyObject *res; + Py_BEGIN_CRITICAL_SECTION(o); + res = copy_lock_held(o, 0); + Py_END_CRITICAL_SECTION(); + return res; +} + +// Similar to PyDict_Copy(), but return a frozendict if the argument +// is a frozendict. static PyObject * -_PyDict_Copy(PyObject *o) +anydict_copy(PyObject *o) { assert(PyAnyDict_Check(o)); @@ -4397,22 +4414,8 @@ _PyDict_Copy(PyObject *o) return res; } -PyObject * -PyDict_Copy(PyObject *o) -{ - if (o == NULL || !PyAnyDict_Check(o)) { - PyErr_BadInternalCall(); - return NULL; - } - - if (PyFrozenDict_CheckExact(o)) { - return Py_NewRef(o); - } - - return _PyDict_Copy(o); -} - -// Similar to PyDict_Copy(), but return a dict if the argument is a frozendict. +// Similar to PyDict_Copy(), but accept also frozendict: +// convert frozendict to a new dict. PyObject* _PyDict_CopyAsDict(PyObject *o) { @@ -4969,7 +4972,7 @@ dict_or(PyObject *self, PyObject *other) if (!PyAnyDict_Check(self) || !PyAnyDict_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } - PyObject *new = _PyDict_Copy(self); + PyObject *new = anydict_copy(self); if (new == NULL) { return NULL; } @@ -8057,7 +8060,7 @@ static PyMethodDef frozendict_methods[] = { DICT_ITEMS_METHODDEF DICT_VALUES_METHODDEF DICT_FROMKEYS_METHODDEF - DICT_COPY_METHODDEF + FROZENDICT_COPY_METHODDEF DICT___REVERSED___METHODDEF {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, {"__getnewargs__", frozendict_getnewargs, METH_NOARGS}, @@ -8182,6 +8185,25 @@ PyFrozenDict_New(PyObject *iterable) } } +/*[clinic input] +frozendict.copy + +Return a shallow copy of the frozendict. +[clinic start generated code]*/ + +static PyObject * +frozendict_copy_impl(PyFrozenDictObject *self) +/*[clinic end generated code: output=e580fd91d9fc2cf7 input=35f6abeaa08fd4bc]*/ +{ + assert(PyFrozenDict_Check(self)); + + if (PyFrozenDict_CheckExact(self)) { + return Py_NewRef(self); + } + + return anydict_copy((PyObject*)self); +} + PyTypeObject PyFrozenDict_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) From 37e421bb4330c184114aa6a23998dba9bd8d3bc5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 17:44:58 +0100 Subject: [PATCH 013/775] gh-141510: Complete What's New in Python 3.15 for frozendict (#145537) Mention updated stdlib modules and built-in functions. Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- Doc/library/functions.rst | 4 ++++ Doc/library/stdtypes.rst | 4 ++++ Doc/whatsnew/3.15.rst | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index d9a2eff667e..af53b57dc9d 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -2099,6 +2099,10 @@ are always available. They are listed here in alphabetical order. Subclasses of :class:`!type` which don't override ``type.__new__`` may no longer use the one-argument form to get the type of an object. + .. versionchanged:: next + + *dict* can now be a :class:`frozendict`. + .. function:: vars() vars(object, /) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 76a4367dd2d..c930b876b3c 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2385,6 +2385,10 @@ expression support in the :mod:`re` module). the same position in *to*. If there is a third argument, it must be a string, whose characters will be mapped to ``None`` in the result. + .. versionchanged:: next + + *dict* can now be a :class:`frozendict`. + .. method:: str.partition(sep, /) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index fff2168be72..0b5902bb013 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -211,6 +211,13 @@ For example:: >>> a == b True +The following standard library modules have been updated to accept +:class:`!frozendict`: :mod:`copy`, :mod:`decimal`, :mod:`json`, :mod:`marshal`, +:mod:`pickle`, :mod:`pprint` and :mod:`xml.etree.ElementTree`. + +:func:`eval` and :func:`exec` accept :class:`!frozendict` for *globals*, and +:func:`type` and :meth:`str.maketrans` accept :class:`!frozendict` for *dict*. + .. seealso:: :pep:`814` for the full specification and rationale. (Contributed by Victor Stinner and Donghee Na in :gh:`141510`.) From e0945443a0abdee56a51a5cb82a31edba5f1adab Mon Sep 17 00:00:00 2001 From: Yash Kaushik Date: Thu, 5 Mar 2026 23:18:48 +0530 Subject: [PATCH 014/775] doc: Clarify logger creation example in logging HOWTO (GH-145540) --- Doc/howto/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index b7225ff1c2c..454e2f4930e 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -28,7 +28,7 @@ When to use logging ^^^^^^^^^^^^^^^^^^^ You can access logging functionality by creating a logger via ``logger = -getLogger(__name__)``, and then calling the logger's :meth:`~Logger.debug`, +logging.getLogger(__name__)``, and then calling the logger's :meth:`~Logger.debug`, :meth:`~Logger.info`, :meth:`~Logger.warning`, :meth:`~Logger.error` and :meth:`~Logger.critical` methods. To determine when to use logging, and to see which logger methods to use when, see the table below. It states, for each of a From 7232883adfc28f94a62d2e79c897db59711702d7 Mon Sep 17 00:00:00 2001 From: Alex Malyshev Date: Thu, 5 Mar 2026 14:03:30 -0500 Subject: [PATCH 015/775] gh-145557: Check ctypes is available in test_external_inspection (#145558) Currently TestGetStackTrace.test_self_trace_after_ctypes_import() will fail if the _ctypes extension is not built. Make it match test_ctypes by skipping the test in that case. --- Lib/test/test_external_inspection.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/test/test_external_inspection.py b/Lib/test/test_external_inspection.py index 890aa584cd1..ec7192b1b89 100644 --- a/Lib/test/test_external_inspection.py +++ b/Lib/test/test_external_inspection.py @@ -17,6 +17,7 @@ requires_gil_enabled, requires_remote_subprocess_debugging, ) +from test.support.import_helper import import_module from test.support.script_helper import make_script from test.support.socket_helper import find_unused_port @@ -529,6 +530,10 @@ def test_self_trace_after_ctypes_import(self): The remote debugging code must skip these uninitialized duplicate mappings and find the real PyRuntime. See gh-144563. """ + + # Skip the test if the _ctypes module is missing. + import_module("_ctypes") + # Run the test in a subprocess to avoid side effects script = textwrap.dedent("""\ import os From c3fb0d9d96902774c08b199dda0479a8d31398a5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 6 Mar 2026 01:42:41 +0100 Subject: [PATCH 016/775] gh-145177: Support multiple Emscripten versions for Emscripten buildbot (#145180) Adds an `--emsdk-cache` argument to the Emscripten build script and an emscripten_version.txt file. If the `--emsdk-cache` argument is passed, the build script will look in `emscripten_version.txt` to get the expected emsdk version is installed in a folder called e.g., 4.0.12 in the directory indicated by the `--emsdk-cache` argument, and run the build with that Emscripten tooling activated. --- Tools/wasm/emscripten/__main__.py | 76 ++++++++++++++++++-- Tools/wasm/emscripten/emscripten_version.txt | 1 + 2 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 Tools/wasm/emscripten/emscripten_version.txt diff --git a/Tools/wasm/emscripten/__main__.py b/Tools/wasm/emscripten/__main__.py index c88e9edba6d..856a7f8252b 100644 --- a/Tools/wasm/emscripten/__main__.py +++ b/Tools/wasm/emscripten/__main__.py @@ -22,6 +22,7 @@ EMSCRIPTEN_DIR = Path(__file__).parent CHECKOUT = EMSCRIPTEN_DIR.parent.parent.parent +EMSCRIPTEN_VERSION_FILE = EMSCRIPTEN_DIR / "emscripten_version.txt" CROSS_BUILD_DIR = CHECKOUT / "cross-build" NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build" @@ -36,7 +37,56 @@ LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n" -def updated_env(updates={}): +@functools.cache +def get_required_emscripten_version(): + """Read the required emscripten version from emscripten_version.txt.""" + return EMSCRIPTEN_VERSION_FILE.read_text().strip() + + +@functools.cache +def get_emsdk_activate_path(emsdk_cache): + required_version = get_required_emscripten_version() + return Path(emsdk_cache) / required_version / "emsdk_env.sh" + + +def validate_emsdk_version(emsdk_cache): + """Validate that the emsdk cache contains the required emscripten version.""" + required_version = get_required_emscripten_version() + emsdk_env = get_emsdk_activate_path(emsdk_cache) + if not emsdk_env.is_file(): + print( + f"Required emscripten version {required_version} not found in {emsdk_cache}", + file=sys.stderr, + ) + sys.exit(1) + print(f"✅ Emscripten version {required_version} found in {emsdk_cache}") + + +def parse_env(text): + result = {} + for line in text.splitlines(): + key, val = line.split("=", 1) + result[key] = val + return result + + +@functools.cache +def get_emsdk_environ(emsdk_cache): + """Returns os.environ updated by sourcing emsdk_env.sh""" + if not emsdk_cache: + return os.environ + env_text = subprocess.check_output( + [ + "bash", + "-c", + f"EMSDK_QUIET=1 source {get_emsdk_activate_path(emsdk_cache)} && env", + ], + text=True, + ) + return parse_env(env_text) + + +def updated_env(updates, emsdk_cache): """Create a new dict representing the environment to use. The changes made to the execution environment are printed out. @@ -52,8 +102,7 @@ def updated_env(updates={}): except subprocess.CalledProcessError: pass # Might be building from a tarball. # This layering lets SOURCE_DATE_EPOCH from os.environ takes precedence. - environment = env_defaults | os.environ | updates - + environment = env_defaults | get_emsdk_environ(emsdk_cache) | updates env_diff = {} for key, value in environment.items(): if os.environ.get(key) != value: @@ -204,7 +253,7 @@ def make_emscripten_libffi(context, working_dir): ) call( [EMSCRIPTEN_DIR / "make_libffi.sh"], - env=updated_env({"PREFIX": PREFIX_DIR}), + env=updated_env({"PREFIX": PREFIX_DIR}, context.emsdk_cache), cwd=libffi_dir, quiet=context.quiet, ) @@ -231,6 +280,7 @@ def make_mpdec(context, working_dir): ], cwd=mpdec_dir, quiet=context.quiet, + env=updated_env({}, context.emsdk_cache), ) call( ["make", "install"], @@ -300,7 +350,7 @@ def configure_emscripten_python(context, working_dir): configure.extend(context.args) call( configure, - env=updated_env(env_additions), + env=updated_env(env_additions, context.emsdk_cache), quiet=context.quiet, ) @@ -358,7 +408,7 @@ def make_emscripten_python(context, working_dir): """Run `make` for the emscripten/host build.""" call( ["make", "--jobs", str(cpu_count()), "all"], - env=updated_env(), + env=updated_env({}, context.emsdk_cache), quiet=context.quiet, ) @@ -439,6 +489,14 @@ def main(): dest="quiet", help="Redirect output from subprocesses to a log file", ) + subcommand.add_argument( + "--emsdk-cache", + action="store", + default=None, + dest="emsdk_cache", + help="Path to emsdk cache directory. If provided, validates that " + "the required emscripten version is installed.", + ) for subcommand in configure_build, configure_host: subcommand.add_argument( "--clean", @@ -463,6 +521,12 @@ def main(): context = parser.parse_args() + if context.emsdk_cache: + validate_emsdk_version(context.emsdk_cache) + context.emsdk_cache = Path(context.emsdk_cache).absolute() + else: + print("Build will use EMSDK from current environment.") + dispatch = { "make-libffi": make_emscripten_libffi, "make-mpdec": make_mpdec, diff --git a/Tools/wasm/emscripten/emscripten_version.txt b/Tools/wasm/emscripten/emscripten_version.txt new file mode 100644 index 00000000000..4c05e4ef57d --- /dev/null +++ b/Tools/wasm/emscripten/emscripten_version.txt @@ -0,0 +1 @@ +4.0.12 From 4fce98a920f47504e834057cd6606bad9b591ea9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 6 Mar 2026 10:23:11 +0100 Subject: [PATCH 017/775] gh-141510: Change marshal version to 6 (#145551) Fix SliceTestCase: test also that version 4 fails with ValueError. --- Doc/library/marshal.rst | 11 +++++++++-- Include/cpython/marshal.h | 2 +- Lib/test/test_marshal.py | 11 ++++++++++- .../2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst | 2 ++ Programs/_freeze_module.c | 2 +- Python/marshal.c | 6 ++++++ 6 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst diff --git a/Doc/library/marshal.rst b/Doc/library/marshal.rst index ed182ea24e8..25902622b87 100644 --- a/Doc/library/marshal.rst +++ b/Doc/library/marshal.rst @@ -51,8 +51,9 @@ this module. The following types are supported: * Strings (:class:`str`) and :class:`bytes`. :term:`Bytes-like objects ` like :class:`bytearray` are marshalled as :class:`!bytes`. -* Containers: :class:`tuple`, :class:`list`, :class:`set`, :class:`frozenset`, - and (since :data:`version` 5), :class:`slice`. +* Containers: :class:`tuple`, :class:`list`, :class:`dict`, :class:`frozendict` + (since :data:`version` 6), :class:`set`, :class:`frozenset`, and + :class:`slice` (since :data:`version` 5). It should be understood that these are supported only if the values contained therein are themselves supported. Recursive containers are supported since :data:`version` 3. @@ -71,6 +72,10 @@ this module. The following types are supported: Added format version 5, which allows marshalling slices. +.. versionchanged:: next + + Added format version 6, which allows marshalling :class:`frozendict`. + The module defines these functions: @@ -173,6 +178,8 @@ In addition, the following constants are defined: 4 Python 3.4 Efficient representation of short strings ------- --------------- ---------------------------------------------------- 5 Python 3.14 Support for :class:`slice` objects + ------- --------------- ---------------------------------------------------- + 6 Python 3.15 Support for :class:`frozendict` objects ======= =============== ==================================================== diff --git a/Include/cpython/marshal.h b/Include/cpython/marshal.h index 6c1f7f96b6a..159459fcaec 100644 --- a/Include/cpython/marshal.h +++ b/Include/cpython/marshal.h @@ -6,7 +6,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const char *, Py_ssize_t); PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int); -#define Py_MARSHAL_VERSION 5 +#define Py_MARSHAL_VERSION 6 PyAPI_FUNC(long) PyMarshal_ReadLongFromFile(FILE *); PyAPI_FUNC(int) PyMarshal_ReadShortFromFile(FILE *); diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py index 28f24d0fc59..78db4219e29 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -570,6 +570,15 @@ def testDict(self): self.helper(dictobj) self.helper3(dictobj) + def testFrozenDict(self): + for obj in self.keys: + dictobj = frozendict({"hello": obj, "goodbye": obj, obj: "hello"}) + self.helper(dictobj) + + for version in range(6): + with self.assertRaises(ValueError): + marshal.dumps(dictobj, version) + def testModule(self): with open(__file__, "rb") as f: code = f.read() @@ -635,7 +644,7 @@ def test_slice(self): with self.subTest(obj=str(obj)): self.helper(obj) - for version in range(4): + for version in range(5): with self.assertRaises(ValueError): marshal.dumps(obj, version) diff --git a/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst b/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst new file mode 100644 index 00000000000..280a7b3632d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst @@ -0,0 +1,2 @@ +:mod:`marshal` now supports :class:`frozendict` objects. The marshal format +version was increased to 6. Patch by Victor Stinner. diff --git a/Programs/_freeze_module.c b/Programs/_freeze_module.c index a5809b37b6b..27a60171f3e 100644 --- a/Programs/_freeze_module.c +++ b/Programs/_freeze_module.c @@ -134,7 +134,7 @@ compile_and_marshal(const char *name, const char *text) return NULL; } - assert(Py_MARSHAL_VERSION >= 5); + assert(Py_MARSHAL_VERSION >= 6); PyObject *marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION); Py_CLEAR(code); if (marshalled == NULL) { diff --git a/Python/marshal.c b/Python/marshal.c index a71909f103e..59db6456552 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -580,6 +580,12 @@ w_complex_object(PyObject *v, char flag, WFILE *p) Py_ssize_t pos; PyObject *key, *value; if (PyFrozenDict_CheckExact(v)) { + if (p->version < 6) { + w_byte(TYPE_UNKNOWN, p); + p->error = WFERR_UNMARSHALLABLE; + return; + } + W_TYPE(TYPE_FROZENDICT, p); } else { From 349639cfa46180b18c2a3299db08cff253c7a959 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 6 Mar 2026 10:25:09 +0100 Subject: [PATCH 018/775] gh-141510: Use frozendict in the stdlib (#144909) Co-authored-by: Donghee Na --- Lib/functools.py | 4 +- Lib/gettext.py | 5 +- Lib/json/decoder.py | 4 +- Lib/json/tool.py | 4 +- Lib/opcode.py | 152 ++++++++++++++++++++++---------------------- Lib/optparse.py | 10 +-- Lib/platform.py | 8 +-- Lib/plistlib.py | 2 +- Lib/ssl.py | 3 +- Lib/symtable.py | 2 +- Lib/tarfile.py | 4 +- 11 files changed, 101 insertions(+), 97 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 9bc2ee7e8c8..cd374631f16 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -170,7 +170,7 @@ def _lt_from_ge(self, other): return op_result return not op_result -_convert = { +_convert = frozendict({ '__lt__': [('__gt__', _gt_from_lt), ('__le__', _le_from_lt), ('__ge__', _ge_from_lt)], @@ -183,7 +183,7 @@ def _lt_from_ge(self, other): '__ge__': [('__le__', _le_from_ge), ('__gt__', _gt_from_ge), ('__lt__', _lt_from_ge)] -} +}) def total_ordering(cls): """Class decorator that fills in missing ordering methods""" diff --git a/Lib/gettext.py b/Lib/gettext.py index 6c11ab2b1eb..2f77f0e849e 100644 --- a/Lib/gettext.py +++ b/Lib/gettext.py @@ -111,8 +111,9 @@ def _error(value): ('+', '-'), ('*', '/', '%'), ) -_binary_ops = {op: i for i, ops in enumerate(_binary_ops, 1) for op in ops} -_c2py_ops = {'||': 'or', '&&': 'and', '/': '//'} +_binary_ops = frozendict({op: i for i, ops in enumerate(_binary_ops, 1) + for op in ops}) +_c2py_ops = frozendict({'||': 'or', '&&': 'and', '/': '//'}) def _parse(tokens, priority=-1): diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py index 92ad6352557..4cd6f8367a1 100644 --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -43,11 +43,11 @@ def __reduce__(self): return self.__class__, (self.msg, self.doc, self.pos) -_CONSTANTS = { +_CONSTANTS = frozendict({ '-Infinity': NegInf, 'Infinity': PosInf, 'NaN': NaN, -} +}) HEXDIGITS = re.compile(r'[0-9A-Fa-f]{4}', FLAGS) diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 050c2fe2161..e0b944b197d 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -22,13 +22,13 @@ (?Pnull) ''', re.VERBOSE) -_group_to_theme_color = { +_group_to_theme_color = frozendict({ "key": "definition", "string": "string", "number": "number", "boolean": "keyword", "null": "keyword", -} +}) def _colorize_json(json_str, theme): diff --git a/Lib/opcode.py b/Lib/opcode.py index f016b8dc4a5..165f42baed9 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -46,81 +46,81 @@ hascompare = [opmap["COMPARE_OP"]] -_cache_format = { - "LOAD_GLOBAL": { - "counter": 1, - "index": 1, - "module_keys_version": 1, - "builtin_keys_version": 1, - }, - "BINARY_OP": { - "counter": 1, - "descr": 4, - }, - "UNPACK_SEQUENCE": { - "counter": 1, - }, - "COMPARE_OP": { - "counter": 1, - }, - "CONTAINS_OP": { - "counter": 1, - }, - "FOR_ITER": { - "counter": 1, - }, - "LOAD_SUPER_ATTR": { - "counter": 1, - }, - "LOAD_ATTR": { - "counter": 1, - "version": 2, - "keys_version": 2, - "descr": 4, - }, - "STORE_ATTR": { - "counter": 1, - "version": 2, - "index": 1, - }, - "CALL": { - "counter": 1, - "func_version": 2, - }, - "CALL_KW": { - "counter": 1, - "func_version": 2, - }, - "CALL_FUNCTION_EX": { - "counter": 1, - }, - "STORE_SUBSCR": { - "counter": 1, - }, - "SEND": { - "counter": 1, - }, - "JUMP_BACKWARD": { - "counter": 1, - }, - "TO_BOOL": { - "counter": 1, - "version": 2, - }, - "POP_JUMP_IF_TRUE": { - "counter": 1, - }, - "POP_JUMP_IF_FALSE": { - "counter": 1, - }, - "POP_JUMP_IF_NONE": { - "counter": 1, - }, - "POP_JUMP_IF_NOT_NONE": { - "counter": 1, - }, -} +_cache_format = frozendict( + LOAD_GLOBAL=frozendict( + counter=1, + index=1, + module_keys_version=1, + builtin_keys_version=1, + ), + BINARY_OP=frozendict( + counter=1, + descr=4, + ), + UNPACK_SEQUENCE=frozendict( + counter=1, + ), + COMPARE_OP=frozendict( + counter=1, + ), + CONTAINS_OP=frozendict( + counter=1, + ), + FOR_ITER=frozendict( + counter=1, + ), + LOAD_SUPER_ATTR=frozendict( + counter=1, + ), + LOAD_ATTR=frozendict( + counter=1, + version=2, + keys_version=2, + descr=4, + ), + STORE_ATTR=frozendict( + counter=1, + version=2, + index=1, + ), + CALL=frozendict( + counter=1, + func_version=2, + ), + CALL_KW=frozendict( + counter=1, + func_version=2, + ), + CALL_FUNCTION_EX=frozendict( + counter=1, + ), + STORE_SUBSCR=frozendict( + counter=1, + ), + SEND=frozendict( + counter=1, + ), + JUMP_BACKWARD=frozendict( + counter=1, + ), + TO_BOOL=frozendict( + counter=1, + version=2, + ), + POP_JUMP_IF_TRUE=frozendict( + counter=1, + ), + POP_JUMP_IF_FALSE=frozendict( + counter=1, + ), + POP_JUMP_IF_NONE=frozendict( + counter=1, + ), + POP_JUMP_IF_NOT_NONE=frozendict( + counter=1, + ), +) -_inline_cache_entries = { +_inline_cache_entries = frozendict({ name : sum(value.values()) for (name, value) in _cache_format.items() -} +}) diff --git a/Lib/optparse.py b/Lib/optparse.py index 5ff7f74754f..de1082442ef 100644 --- a/Lib/optparse.py +++ b/Lib/optparse.py @@ -407,10 +407,12 @@ def _parse_num(val, type): def _parse_int(val): return _parse_num(val, int) -_builtin_cvt = { "int" : (_parse_int, _("integer")), - "long" : (_parse_int, _("integer")), - "float" : (float, _("floating-point")), - "complex" : (complex, _("complex")) } +_builtin_cvt = frozendict({ + "int": (_parse_int, _("integer")), + "long": (_parse_int, _("integer")), + "float": (float, _("floating-point")), + "complex": (complex, _("complex")), +}) def check_builtin(option, opt, value): (cvt, what) = _builtin_cvt[option.type] diff --git a/Lib/platform.py b/Lib/platform.py index 3a71b669985..9d7aa5c66a9 100644 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -127,7 +127,7 @@ # Based on the description of the PHP's version_compare(): # http://php.net/manual/en/function.version-compare.php -_ver_stages = { +_ver_stages = frozendict({ # any string not found in this dict, will get 0 assigned 'dev': 10, 'alpha': 20, 'a': 20, @@ -136,7 +136,7 @@ 'RC': 50, 'rc': 50, # number, will get 100 assigned 'pl': 200, 'p': 200, -} +}) def _comparable_version(version): @@ -705,11 +705,11 @@ def _syscmd_file(target, default=''): # Default values for architecture; non-empty strings override the # defaults given as parameters -_default_architecture = { +_default_architecture = frozendict({ 'win32': ('', 'WindowsPE'), 'win16': ('', 'Windows'), 'dos': ('', 'MSDOS'), -} +}) def architecture(executable=sys.executable, bits='', linkage=''): diff --git a/Lib/plistlib.py b/Lib/plistlib.py index cae38672f64..3c6a6b7bdc4 100644 --- a/Lib/plistlib.py +++ b/Lib/plistlib.py @@ -453,7 +453,7 @@ class InvalidFileException (ValueError): def __init__(self, message="Invalid file"): ValueError.__init__(self, message) -_BINARY_FORMAT = {1: 'B', 2: 'H', 4: 'L', 8: 'Q'} +_BINARY_FORMAT = frozendict({1: 'B', 2: 'H', 4: 'L', 8: 'Q'}) _undefined = object() diff --git a/Lib/ssl.py b/Lib/ssl.py index 612b32cd076..896db17baeb 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -150,7 +150,8 @@ source=_ssl) PROTOCOL_SSLv23 = _SSLMethod.PROTOCOL_SSLv23 = _SSLMethod.PROTOCOL_TLS -_PROTOCOL_NAMES = {value: name for name, value in _SSLMethod.__members__.items()} +_PROTOCOL_NAMES = frozendict({ + value: name for name, value in _SSLMethod.__members__.items()}) _SSLv2_IF_EXISTS = getattr(_SSLMethod, 'PROTOCOL_SSLv2', None) diff --git a/Lib/symtable.py b/Lib/symtable.py index 45610fd5612..c7152a70f5a 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -414,7 +414,7 @@ def get_namespace(self): _flags = [('USE', USE)] _flags.extend(kv for kv in globals().items() if kv[0].startswith('DEF_')) _scopes_names = ('FREE', 'LOCAL', 'GLOBAL_IMPLICIT', 'GLOBAL_EXPLICIT', 'CELL') -_scopes_value_to_name = {globals()[n]: n for n in _scopes_names} +_scopes_value_to_name = frozendict({globals()[n]: n for n in _scopes_names}) def main(args): diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 75984bf8b26..7abda3653e7 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -859,11 +859,11 @@ def data_filter(member, dest_path): return member.replace(**new_attrs, deep=False) return member -_NAMED_FILTERS = { +_NAMED_FILTERS = frozendict({ "fully_trusted": fully_trusted_filter, "tar": tar_filter, "data": data_filter, -} +}) #------------------ # Exported Classes From d3b6faf9758dce236d45c708a450437cdc3e97cd Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:18:11 +0200 Subject: [PATCH 019/775] Docs: `import datetime as dt` in examples (#145315) --- Doc/includes/tzinfo_examples.py | 127 ++++++------- Doc/library/datetime.rst | 303 +++++++++++++++++--------------- 2 files changed, 224 insertions(+), 206 deletions(-) diff --git a/Doc/includes/tzinfo_examples.py b/Doc/includes/tzinfo_examples.py index 1fa6e615e46..762b1b62fc8 100644 --- a/Doc/includes/tzinfo_examples.py +++ b/Doc/includes/tzinfo_examples.py @@ -1,68 +1,70 @@ -from datetime import tzinfo, timedelta, datetime - -ZERO = timedelta(0) -HOUR = timedelta(hours=1) -SECOND = timedelta(seconds=1) +import datetime as dt # A class capturing the platform's idea of local time. # (May result in wrong values on historical times in # timezones where UTC offset and/or the DST rules had # changed in the past.) -import time as _time +import time -STDOFFSET = timedelta(seconds = -_time.timezone) -if _time.daylight: - DSTOFFSET = timedelta(seconds = -_time.altzone) +ZERO = dt.timedelta(0) +HOUR = dt.timedelta(hours=1) +SECOND = dt.timedelta(seconds=1) + +STDOFFSET = dt.timedelta(seconds=-time.timezone) +if time.daylight: + DSTOFFSET = dt.timedelta(seconds=-time.altzone) else: DSTOFFSET = STDOFFSET DSTDIFF = DSTOFFSET - STDOFFSET -class LocalTimezone(tzinfo): - def fromutc(self, dt): - assert dt.tzinfo is self - stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND - args = _time.localtime(stamp)[:6] +class LocalTimezone(dt.tzinfo): + + def fromutc(self, when): + assert when.tzinfo is self + stamp = (when - dt.datetime(1970, 1, 1, tzinfo=self)) // SECOND + args = time.localtime(stamp)[:6] dst_diff = DSTDIFF // SECOND # Detect fold - fold = (args == _time.localtime(stamp - dst_diff)) - return datetime(*args, microsecond=dt.microsecond, - tzinfo=self, fold=fold) + fold = (args == time.localtime(stamp - dst_diff)) + return dt.datetime(*args, microsecond=when.microsecond, + tzinfo=self, fold=fold) - def utcoffset(self, dt): - if self._isdst(dt): + def utcoffset(self, when): + if self._isdst(when): return DSTOFFSET else: return STDOFFSET - def dst(self, dt): - if self._isdst(dt): + def dst(self, when): + if self._isdst(when): return DSTDIFF else: return ZERO - def tzname(self, dt): - return _time.tzname[self._isdst(dt)] + def tzname(self, when): + return time.tzname[self._isdst(when)] - def _isdst(self, dt): - tt = (dt.year, dt.month, dt.day, - dt.hour, dt.minute, dt.second, - dt.weekday(), 0, 0) - stamp = _time.mktime(tt) - tt = _time.localtime(stamp) + def _isdst(self, when): + tt = (when.year, when.month, when.day, + when.hour, when.minute, when.second, + when.weekday(), 0, 0) + stamp = time.mktime(tt) + tt = time.localtime(stamp) return tt.tm_isdst > 0 + Local = LocalTimezone() # A complete implementation of current DST rules for major US time zones. -def first_sunday_on_or_after(dt): - days_to_go = 6 - dt.weekday() +def first_sunday_on_or_after(when): + days_to_go = 6 - when.weekday() if days_to_go: - dt += timedelta(days_to_go) - return dt + when += dt.timedelta(days_to_go) + return when # US DST Rules @@ -75,21 +77,22 @@ def first_sunday_on_or_after(dt): # # In the US, since 2007, DST starts at 2am (standard time) on the second # Sunday in March, which is the first Sunday on or after Mar 8. -DSTSTART_2007 = datetime(1, 3, 8, 2) +DSTSTART_2007 = dt.datetime(1, 3, 8, 2) # and ends at 2am (DST time) on the first Sunday of Nov. -DSTEND_2007 = datetime(1, 11, 1, 2) +DSTEND_2007 = dt.datetime(1, 11, 1, 2) # From 1987 to 2006, DST used to start at 2am (standard time) on the first # Sunday in April and to end at 2am (DST time) on the last # Sunday of October, which is the first Sunday on or after Oct 25. -DSTSTART_1987_2006 = datetime(1, 4, 1, 2) -DSTEND_1987_2006 = datetime(1, 10, 25, 2) +DSTSTART_1987_2006 = dt.datetime(1, 4, 1, 2) +DSTEND_1987_2006 = dt.datetime(1, 10, 25, 2) # From 1967 to 1986, DST used to start at 2am (standard time) on the last # Sunday in April (the one on or after April 24) and to end at 2am (DST time) # on the last Sunday of October, which is the first Sunday # on or after Oct 25. -DSTSTART_1967_1986 = datetime(1, 4, 24, 2) +DSTSTART_1967_1986 = dt.datetime(1, 4, 24, 2) DSTEND_1967_1986 = DSTEND_1987_2006 + def us_dst_range(year): # Find start and end times for US DST. For years before 1967, return # start = end for no DST. @@ -100,17 +103,17 @@ def us_dst_range(year): elif 1966 < year < 1987: dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986 else: - return (datetime(year, 1, 1), ) * 2 + return (dt.datetime(year, 1, 1), ) * 2 start = first_sunday_on_or_after(dststart.replace(year=year)) end = first_sunday_on_or_after(dstend.replace(year=year)) return start, end -class USTimeZone(tzinfo): +class USTimeZone(dt.tzinfo): def __init__(self, hours, reprname, stdname, dstname): - self.stdoffset = timedelta(hours=hours) + self.stdoffset = dt.timedelta(hours=hours) self.reprname = reprname self.stdname = stdname self.dstname = dstname @@ -118,45 +121,45 @@ def __init__(self, hours, reprname, stdname, dstname): def __repr__(self): return self.reprname - def tzname(self, dt): - if self.dst(dt): + def tzname(self, when): + if self.dst(when): return self.dstname else: return self.stdname - def utcoffset(self, dt): - return self.stdoffset + self.dst(dt) + def utcoffset(self, when): + return self.stdoffset + self.dst(when) - def dst(self, dt): - if dt is None or dt.tzinfo is None: + def dst(self, when): + if when is None or when.tzinfo is None: # An exception may be sensible here, in one or both cases. # It depends on how you want to treat them. The default # fromutc() implementation (called by the default astimezone() - # implementation) passes a datetime with dt.tzinfo is self. + # implementation) passes a datetime with when.tzinfo is self. return ZERO - assert dt.tzinfo is self - start, end = us_dst_range(dt.year) + assert when.tzinfo is self + start, end = us_dst_range(when.year) # Can't compare naive to aware objects, so strip the timezone from - # dt first. - dt = dt.replace(tzinfo=None) - if start + HOUR <= dt < end - HOUR: + # when first. + when = when.replace(tzinfo=None) + if start + HOUR <= when < end - HOUR: # DST is in effect. return HOUR - if end - HOUR <= dt < end: - # Fold (an ambiguous hour): use dt.fold to disambiguate. - return ZERO if dt.fold else HOUR - if start <= dt < start + HOUR: + if end - HOUR <= when < end: + # Fold (an ambiguous hour): use when.fold to disambiguate. + return ZERO if when.fold else HOUR + if start <= when < start + HOUR: # Gap (a non-existent hour): reverse the fold rule. - return HOUR if dt.fold else ZERO + return HOUR if when.fold else ZERO # DST is off. return ZERO - def fromutc(self, dt): - assert dt.tzinfo is self - start, end = us_dst_range(dt.year) + def fromutc(self, when): + assert when.tzinfo is self + start, end = us_dst_range(when.year) start = start.replace(tzinfo=self) end = end.replace(tzinfo=self) - std_time = dt + self.stdoffset + std_time = when + self.stdoffset dst_time = std_time + HOUR if end <= dst_time < end + HOUR: # Repeated hour diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index ebe3c3576c0..73217136f14 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -230,8 +230,8 @@ A :class:`timedelta` object represents a duration, the difference between two *days*, *seconds* and *microseconds* are "merged" and normalized into those three resulting attributes:: - >>> from datetime import timedelta - >>> delta = timedelta( + >>> import datetime as dt + >>> delta = dt.timedelta( ... days=50, ... seconds=27, ... microseconds=10, @@ -244,6 +244,12 @@ A :class:`timedelta` object represents a duration, the difference between two >>> delta datetime.timedelta(days=64, seconds=29156, microseconds=10) + .. tip:: + ``import datetime as dt`` instead of ``import datetime`` or + ``from datetime import datetime`` to avoid confusion between the module + and the class. See `How I Import Python’s datetime Module + `__. + If any argument is a float and there are fractional microseconds, the fractional microseconds left over from all arguments are combined and their sum is rounded to the nearest microsecond using @@ -257,8 +263,8 @@ A :class:`timedelta` object represents a duration, the difference between two Note that normalization of negative values may be surprising at first. For example:: - >>> from datetime import timedelta - >>> d = timedelta(microseconds=-1) + >>> import datetime as dt + >>> d = dt.timedelta(microseconds=-1) >>> (d.days, d.seconds, d.microseconds) (-1, 86399, 999999) @@ -321,8 +327,8 @@ Instance attributes (read-only): .. doctest:: - >>> from datetime import timedelta - >>> duration = timedelta(seconds=11235813) + >>> import datetime as dt + >>> duration = dt.timedelta(seconds=11235813) >>> duration.days, duration.seconds (130, 3813) >>> duration.total_seconds() @@ -461,10 +467,10 @@ Examples of usage: :class:`!timedelta` An additional example of normalization:: >>> # Components of another_year add up to exactly 365 days - >>> from datetime import timedelta - >>> year = timedelta(days=365) - >>> another_year = timedelta(weeks=40, days=84, hours=23, - ... minutes=50, seconds=600) + >>> import datetime as dt + >>> year = dt.timedelta(days=365) + >>> another_year = dt.timedelta(weeks=40, days=84, hours=23, + ... minutes=50, seconds=600) >>> year == another_year True >>> year.total_seconds() @@ -472,8 +478,8 @@ An additional example of normalization:: Examples of :class:`timedelta` arithmetic:: - >>> from datetime import timedelta - >>> year = timedelta(days=365) + >>> import datetime as dt + >>> year = dt.timedelta(days=365) >>> ten_years = 10 * year >>> ten_years datetime.timedelta(days=3650) @@ -565,12 +571,12 @@ Other constructors, all class methods: Examples:: - >>> from datetime import date - >>> date.fromisoformat('2019-12-04') + >>> import datetime as dt + >>> dt.date.fromisoformat('2019-12-04') datetime.date(2019, 12, 4) - >>> date.fromisoformat('20191204') + >>> dt.date.fromisoformat('20191204') datetime.date(2019, 12, 4) - >>> date.fromisoformat('2021-W01-1') + >>> dt.date.fromisoformat('2021-W01-1') datetime.date(2021, 1, 4) .. versionadded:: 3.7 @@ -611,9 +617,9 @@ Other constructors, all class methods: .. doctest:: - >>> from datetime import date + >>> import datetime as dt >>> date_string = "02/29" - >>> when = date.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. + >>> when = dt.date.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. >>> when.strftime("%B %d") # doctest: +SKIP 'February 29' @@ -728,8 +734,8 @@ Instance methods: Example:: - >>> from datetime import date - >>> d = date(2002, 12, 31) + >>> import datetime as dt + >>> d = dt.date(2002, 12, 31) >>> d.replace(day=26) datetime.date(2002, 12, 26) @@ -787,10 +793,10 @@ Instance methods: For example, 2004 begins on a Thursday, so the first week of ISO year 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004:: - >>> from datetime import date - >>> date(2003, 12, 29).isocalendar() + >>> import datetime as dt + >>> dt.date(2003, 12, 29).isocalendar() datetime.IsoCalendarDate(year=2004, week=1, weekday=1) - >>> date(2004, 1, 4).isocalendar() + >>> dt.date(2004, 1, 4).isocalendar() datetime.IsoCalendarDate(year=2004, week=1, weekday=7) .. versionchanged:: 3.9 @@ -801,8 +807,8 @@ Instance methods: Return a string representing the date in ISO 8601 format, ``YYYY-MM-DD``:: - >>> from datetime import date - >>> date(2002, 12, 4).isoformat() + >>> import datetime as dt + >>> dt.date(2002, 12, 4).isoformat() '2002-12-04' @@ -815,8 +821,8 @@ Instance methods: Return a string representing the date:: - >>> from datetime import date - >>> date(2002, 12, 4).ctime() + >>> import datetime as dt + >>> dt.date(2002, 12, 4).ctime() 'Wed Dec 4 00:00:00 2002' ``d.ctime()`` is equivalent to:: @@ -849,13 +855,13 @@ Examples of usage: :class:`!date` Example of counting days to an event:: >>> import time - >>> from datetime import date - >>> today = date.today() + >>> import datetime as dt + >>> today = dt.date.today() >>> today datetime.date(2007, 12, 5) - >>> today == date.fromtimestamp(time.time()) + >>> today == dt.date.fromtimestamp(time.time()) True - >>> my_birthday = date(today.year, 6, 24) + >>> my_birthday = dt.date(today.year, 6, 24) >>> if my_birthday < today: ... my_birthday = my_birthday.replace(year=today.year + 1) ... @@ -869,8 +875,8 @@ More examples of working with :class:`date`: .. doctest:: - >>> from datetime import date - >>> d = date.fromordinal(730920) # 730920th day after 1. 1. 0001 + >>> import datetime as dt + >>> d = dt.date.fromordinal(730920) # 730920th day after 1. 1. 0001 >>> d datetime.date(2002, 3, 11) @@ -1123,24 +1129,24 @@ Other constructors, all class methods: Examples:: - >>> from datetime import datetime - >>> datetime.fromisoformat('2011-11-04') + >>> import datetime as dt + >>> dt.datetime.fromisoformat('2011-11-04') datetime.datetime(2011, 11, 4, 0, 0) - >>> datetime.fromisoformat('20111104') + >>> dt.datetime.fromisoformat('20111104') datetime.datetime(2011, 11, 4, 0, 0) - >>> datetime.fromisoformat('2011-11-04T00:05:23') + >>> dt.datetime.fromisoformat('2011-11-04T00:05:23') datetime.datetime(2011, 11, 4, 0, 5, 23) - >>> datetime.fromisoformat('2011-11-04T00:05:23Z') + >>> dt.datetime.fromisoformat('2011-11-04T00:05:23Z') datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc) - >>> datetime.fromisoformat('20111104T000523') + >>> dt.datetime.fromisoformat('20111104T000523') datetime.datetime(2011, 11, 4, 0, 5, 23) - >>> datetime.fromisoformat('2011-W01-2T00:05:23.283') + >>> dt.datetime.fromisoformat('2011-W01-2T00:05:23.283') datetime.datetime(2011, 1, 4, 0, 5, 23, 283000) - >>> datetime.fromisoformat('2011-11-04 00:05:23.283') + >>> dt.datetime.fromisoformat('2011-11-04 00:05:23.283') datetime.datetime(2011, 11, 4, 0, 5, 23, 283000) - >>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00') + >>> dt.datetime.fromisoformat('2011-11-04 00:05:23.283+00:00') datetime.datetime(2011, 11, 4, 0, 5, 23, 283000, tzinfo=datetime.timezone.utc) - >>> datetime.fromisoformat('2011-11-04T00:05:23+04:00') # doctest: +NORMALIZE_WHITESPACE + >>> dt.datetime.fromisoformat('2011-11-04T00:05:23+04:00') # doctest: +NORMALIZE_WHITESPACE datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400))) @@ -1187,9 +1193,9 @@ Other constructors, all class methods: .. doctest:: - >>> from datetime import datetime + >>> import datetime as dt >>> date_string = "02/29" - >>> when = datetime.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. + >>> when = dt.datetime.strptime(f"{date_string};1984", "%m/%d;%Y") # Avoids leap year bug. >>> when.strftime("%B %d") # doctest: +SKIP 'February 29' @@ -1599,24 +1605,24 @@ Instance methods: Examples:: - >>> from datetime import datetime, timezone - >>> datetime(2019, 5, 18, 15, 17, 8, 132263).isoformat() + >>> import datetime as dt + >>> dt.datetime(2019, 5, 18, 15, 17, 8, 132263).isoformat() '2019-05-18T15:17:08.132263' - >>> datetime(2019, 5, 18, 15, 17, tzinfo=timezone.utc).isoformat() + >>> dt.datetime(2019, 5, 18, 15, 17, tzinfo=dt.timezone.utc).isoformat() '2019-05-18T15:17:00+00:00' The optional argument *sep* (default ``'T'``) is a one-character separator, placed between the date and time portions of the result. For example:: - >>> from datetime import tzinfo, timedelta, datetime - >>> class TZ(tzinfo): + >>> import datetime as dt + >>> class TZ(dt.tzinfo): ... """A time zone with an arbitrary, constant -06:39 offset.""" - ... def utcoffset(self, dt): - ... return timedelta(hours=-6, minutes=-39) + ... def utcoffset(self, when): + ... return dt.timedelta(hours=-6, minutes=-39) ... - >>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ') + >>> dt.datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ') '2002-12-25 00:00:00-06:39' - >>> datetime(2009, 11, 27, microsecond=100, tzinfo=TZ()).isoformat() + >>> dt.datetime(2009, 11, 27, microsecond=100, tzinfo=TZ()).isoformat() '2009-11-27T00:00:00.000100-06:39' The optional argument *timespec* specifies the number of additional @@ -1640,11 +1646,11 @@ Instance methods: :exc:`ValueError` will be raised on an invalid *timespec* argument:: - >>> from datetime import datetime - >>> datetime.now().isoformat(timespec='minutes') # doctest: +SKIP + >>> import datetime as dt + >>> dt.datetime.now().isoformat(timespec='minutes') # doctest: +SKIP '2002-12-25T00:00' - >>> dt = datetime(2015, 1, 1, 12, 30, 59, 0) - >>> dt.isoformat(timespec='microseconds') + >>> my_datetime = dt.datetime(2015, 1, 1, 12, 30, 59, 0) + >>> my_datetime.isoformat(timespec='microseconds') '2015-01-01T12:30:59.000000' .. versionchanged:: 3.6 @@ -1661,8 +1667,8 @@ Instance methods: Return a string representing the date and time:: - >>> from datetime import datetime - >>> datetime(2002, 12, 4, 20, 30, 40).ctime() + >>> import datetime as dt + >>> dt.datetime(2002, 12, 4, 20, 30, 40).ctime() 'Wed Dec 4 20:30:40 2002' The output string will *not* include time zone information, regardless @@ -1699,27 +1705,27 @@ Examples of working with :class:`.datetime` objects: .. doctest:: - >>> from datetime import datetime, date, time, timezone + >>> import datetime as dt >>> # Using datetime.combine() - >>> d = date(2005, 7, 14) - >>> t = time(12, 30) - >>> datetime.combine(d, t) + >>> d = dt.date(2005, 7, 14) + >>> t = dt.time(12, 30) + >>> dt.datetime.combine(d, t) datetime.datetime(2005, 7, 14, 12, 30) >>> # Using datetime.now() - >>> datetime.now() # doctest: +SKIP + >>> dt.datetime.now() # doctest: +SKIP datetime.datetime(2007, 12, 6, 16, 29, 43, 79043) # GMT +1 - >>> datetime.now(timezone.utc) # doctest: +SKIP + >>> dt.datetime.now(dt.timezone.utc) # doctest: +SKIP datetime.datetime(2007, 12, 6, 15, 29, 43, 79060, tzinfo=datetime.timezone.utc) >>> # Using datetime.strptime() - >>> dt = datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") - >>> dt + >>> my_datetime = dt.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") + >>> my_datetime datetime.datetime(2006, 11, 21, 16, 30) >>> # Using datetime.timetuple() to get tuple of all attributes - >>> tt = dt.timetuple() + >>> tt = my_datetime.timetuple() >>> for it in tt: # doctest: +SKIP ... print(it) ... @@ -1734,7 +1740,7 @@ Examples of working with :class:`.datetime` objects: -1 # dst - method tzinfo.dst() returned None >>> # Date in ISO format - >>> ic = dt.isocalendar() + >>> ic = my_datetime.isocalendar() >>> for it in ic: # doctest: +SKIP ... print(it) ... @@ -1743,55 +1749,55 @@ Examples of working with :class:`.datetime` objects: 2 # ISO weekday >>> # Formatting a datetime - >>> dt.strftime("%A, %d. %B %Y %I:%M%p") + >>> my_datetime.strftime("%A, %d. %B %Y %I:%M%p") 'Tuesday, 21. November 2006 04:30PM' - >>> 'The {1} is {0:%d}, the {2} is {0:%B}, the {3} is {0:%I:%M%p}.'.format(dt, "day", "month", "time") + >>> 'The {1} is {0:%d}, the {2} is {0:%B}, the {3} is {0:%I:%M%p}.'.format(my_datetime, "day", "month", "time") 'The day is 21, the month is November, the time is 04:30PM.' The example below defines a :class:`tzinfo` subclass capturing time zone information for Kabul, Afghanistan, which used +4 UTC until 1945 and then +4:30 UTC thereafter:: - from datetime import timedelta, datetime, tzinfo, timezone + import datetime as dt - class KabulTz(tzinfo): + class KabulTz(dt.tzinfo): # Kabul used +4 until 1945, when they moved to +4:30 - UTC_MOVE_DATE = datetime(1944, 12, 31, 20, tzinfo=timezone.utc) + UTC_MOVE_DATE = dt.datetime(1944, 12, 31, 20, tzinfo=dt.timezone.utc) - def utcoffset(self, dt): - if dt.year < 1945: - return timedelta(hours=4) - elif (1945, 1, 1, 0, 0) <= dt.timetuple()[:5] < (1945, 1, 1, 0, 30): + def utcoffset(self, when): + if when.year < 1945: + return dt.timedelta(hours=4) + elif (1945, 1, 1, 0, 0) <= when.timetuple()[:5] < (1945, 1, 1, 0, 30): # An ambiguous ("imaginary") half-hour range representing # a 'fold' in time due to the shift from +4 to +4:30. - # If dt falls in the imaginary range, use fold to decide how - # to resolve. See PEP495. - return timedelta(hours=4, minutes=(30 if dt.fold else 0)) + # If when falls in the imaginary range, use fold to decide how + # to resolve. See PEP 495. + return dt.timedelta(hours=4, minutes=(30 if when.fold else 0)) else: - return timedelta(hours=4, minutes=30) + return dt.timedelta(hours=4, minutes=30) - def fromutc(self, dt): + def fromutc(self, when): # Follow same validations as in datetime.tzinfo - if not isinstance(dt, datetime): + if not isinstance(when, dt.datetime): raise TypeError("fromutc() requires a datetime argument") - if dt.tzinfo is not self: - raise ValueError("dt.tzinfo is not self") + if when.tzinfo is not self: + raise ValueError("when.tzinfo is not self") # A custom implementation is required for fromutc as # the input to this function is a datetime with utc values # but with a tzinfo set to self. # See datetime.astimezone or fromtimestamp. - if dt.replace(tzinfo=timezone.utc) >= self.UTC_MOVE_DATE: - return dt + timedelta(hours=4, minutes=30) + if when.replace(tzinfo=dt.timezone.utc) >= self.UTC_MOVE_DATE: + return when + dt.timedelta(hours=4, minutes=30) else: - return dt + timedelta(hours=4) + return when + dt.timedelta(hours=4) - def dst(self, dt): + def dst(self, when): # Kabul does not observe daylight saving time. - return timedelta(0) + return dt.timedelta(0) - def tzname(self, dt): - if dt >= self.UTC_MOVE_DATE: + def tzname(self, when): + if when >= self.UTC_MOVE_DATE: return "+04:30" return "+04" @@ -1800,17 +1806,17 @@ Usage of ``KabulTz`` from above:: >>> tz1 = KabulTz() >>> # Datetime before the change - >>> dt1 = datetime(1900, 11, 21, 16, 30, tzinfo=tz1) + >>> dt1 = dt.datetime(1900, 11, 21, 16, 30, tzinfo=tz1) >>> print(dt1.utcoffset()) 4:00:00 >>> # Datetime after the change - >>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=tz1) + >>> dt2 = dt.datetime(2006, 6, 14, 13, 0, tzinfo=tz1) >>> print(dt2.utcoffset()) 4:30:00 >>> # Convert datetime to another time zone - >>> dt3 = dt2.astimezone(timezone.utc) + >>> dt3 = dt2.astimezone(dt.timezone.utc) >>> dt3 datetime.datetime(2006, 6, 14, 8, 30, tzinfo=datetime.timezone.utc) >>> dt2 @@ -1946,22 +1952,22 @@ Other constructors: .. doctest:: - >>> from datetime import time - >>> time.fromisoformat('04:23:01') + >>> import datetime as dt + >>> dt.time.fromisoformat('04:23:01') datetime.time(4, 23, 1) - >>> time.fromisoformat('T04:23:01') + >>> dt.time.fromisoformat('T04:23:01') datetime.time(4, 23, 1) - >>> time.fromisoformat('T042301') + >>> dt.time.fromisoformat('T042301') datetime.time(4, 23, 1) - >>> time.fromisoformat('04:23:01.000384') + >>> dt.time.fromisoformat('04:23:01.000384') datetime.time(4, 23, 1, 384) - >>> time.fromisoformat('04:23:01,000384') + >>> dt.time.fromisoformat('04:23:01,000384') datetime.time(4, 23, 1, 384) - >>> time.fromisoformat('04:23:01+04:00') + >>> dt.time.fromisoformat('04:23:01+04:00') datetime.time(4, 23, 1, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400))) - >>> time.fromisoformat('04:23:01Z') + >>> dt.time.fromisoformat('04:23:01Z') datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc) - >>> time.fromisoformat('04:23:01+00:00') + >>> dt.time.fromisoformat('04:23:01+00:00') datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc) @@ -2036,13 +2042,13 @@ Instance methods: Example:: - >>> from datetime import time - >>> time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes') + >>> import datetime as dt + >>> dt.time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes') '12:34' - >>> dt = time(hour=12, minute=34, second=56, microsecond=0) - >>> dt.isoformat(timespec='microseconds') + >>> my_time = dt.time(hour=12, minute=34, second=56, microsecond=0) + >>> my_time.isoformat(timespec='microseconds') '12:34:56.000000' - >>> dt.isoformat(timespec='auto') + >>> my_time.isoformat(timespec='auto') '12:34:56' .. versionchanged:: 3.6 @@ -2100,18 +2106,18 @@ Examples of usage: :class:`!time` Examples of working with a :class:`.time` object:: - >>> from datetime import time, tzinfo, timedelta - >>> class TZ1(tzinfo): - ... def utcoffset(self, dt): - ... return timedelta(hours=1) - ... def dst(self, dt): - ... return timedelta(0) - ... def tzname(self,dt): + >>> import datetime as dt + >>> class TZ1(dt.tzinfo): + ... def utcoffset(self, when): + ... return dt.timedelta(hours=1) + ... def dst(self, when): + ... return dt.timedelta(0) + ... def tzname(self, when): ... return "+01:00" ... def __repr__(self): ... return f"{self.__class__.__name__}()" ... - >>> t = time(12, 10, 30, tzinfo=TZ1()) + >>> t = dt.time(12, 10, 30, tzinfo=TZ1()) >>> t datetime.time(12, 10, 30, tzinfo=TZ1()) >>> t.isoformat() @@ -2219,21 +2225,25 @@ Examples of working with a :class:`.time` object:: Most implementations of :meth:`dst` will probably look like one of these two:: - def dst(self, dt): + import datetime as dt + + def dst(self, when): # a fixed-offset class: doesn't account for DST - return timedelta(0) + return dt.timedelta(0) or:: - def dst(self, dt): + import datetime as dt + + def dst(self, when): # Code to set dston and dstoff to the time zone's DST - # transition times based on the input dt.year, and expressed + # transition times based on the input when.year, and expressed # in standard local time. - if dston <= dt.replace(tzinfo=None) < dstoff: - return timedelta(hours=1) + if dston <= when.replace(tzinfo=None) < dstoff: + return dt.timedelta(hours=1) else: - return timedelta(0) + return dt.timedelta(0) The default implementation of :meth:`dst` raises :exc:`NotImplementedError`. @@ -2299,20 +2309,22 @@ There is one more :class:`tzinfo` method that a subclass may wish to override: Skipping code for error cases, the default :meth:`fromutc` implementation acts like:: - def fromutc(self, dt): - # raise ValueError error if dt.tzinfo is not self - dtoff = dt.utcoffset() - dtdst = dt.dst() + import datetime as dt + + def fromutc(self, when): + # raise ValueError error if when.tzinfo is not self + dtoff = when.utcoffset() + dtdst = when.dst() # raise ValueError if dtoff is None or dtdst is None delta = dtoff - dtdst # this is self's standard offset if delta: - dt += delta # convert to standard local time - dtdst = dt.dst() + when += delta # convert to standard local time + dtdst = when.dst() # raise ValueError if dtdst is None if dtdst: - return dt + dtdst + return when + dtdst else: - return dt + return when In the following :download:`tzinfo_examples.py <../includes/tzinfo_examples.py>` file there are some examples of @@ -2339,9 +2351,9 @@ When DST starts (the "start" line), the local wall clock leaps from 1:59 to ``astimezone(Eastern)`` won't deliver a result with ``hour == 2`` on the day DST begins. For example, at the Spring forward transition of 2016, we get:: - >>> from datetime import datetime, timezone + >>> import datetime as dt >>> from tzinfo_examples import HOUR, Eastern - >>> u0 = datetime(2016, 3, 13, 5, tzinfo=timezone.utc) + >>> u0 = dt.datetime(2016, 3, 13, 5, tzinfo=dt.timezone.utc) >>> for i in range(4): ... u = u0 + i*HOUR ... t = u.astimezone(Eastern) @@ -2364,7 +2376,9 @@ form 5:MM and 6:MM both map to 1:MM when converted to Eastern, but earlier times have the :attr:`~.datetime.fold` attribute set to 0 and the later times have it set to 1. For example, at the Fall back transition of 2016, we get:: - >>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc) + >>> import datetime as dt + >>> from tzinfo_examples import HOUR, Eastern + >>> u0 = dt.datetime(2016, 11, 6, 4, tzinfo=dt.timezone.utc) >>> for i in range(4): ... u = u0 + i*HOUR ... t = u.astimezone(Eastern) @@ -2515,8 +2529,9 @@ versus :meth:`~.datetime.strptime`: These methods accept format codes that can be used to parse and format dates:: - >>> datetime.strptime('31/01/22 23:59:59.999999', - ... '%d/%m/%y %H:%M:%S.%f') + >>> import datetime as dt + >>> dt.datetime.strptime('31/01/22 23:59:59.999999', + ... '%d/%m/%y %H:%M:%S.%f') datetime.datetime(2022, 1, 31, 23, 59, 59, 999999) >>> _.strftime('%a %d %b %Y, %I:%M%p') 'Mon 31 Jan 2022, 11:59PM' @@ -2745,13 +2760,13 @@ in the format string will be pulled from the default value. .. doctest:: - >>> from datetime import datetime + >>> import datetime as dt >>> value = "2/29" - >>> datetime.strptime(value, "%m/%d") + >>> dt.datetime.strptime(value, "%m/%d") Traceback (most recent call last): ... ValueError: day 29 must be in range 1..28 for month 2 in year 1900 - >>> datetime.strptime(f"1904 {value}", "%Y %m/%d") + >>> dt.datetime.strptime(f"1904 {value}", "%Y %m/%d") datetime.datetime(1904, 2, 29, 0, 0) Using ``datetime.strptime(date_string, format)`` is equivalent to:: @@ -2897,7 +2912,7 @@ Notes: .. doctest:: >>> month_day = "02/29" - >>> datetime.strptime(f"{month_day};1984", "%m/%d;%Y") # No leap year bug. + >>> dt.datetime.strptime(f"{month_day};1984", "%m/%d;%Y") # No leap year bug. datetime.datetime(1984, 2, 29, 0, 0) .. deprecated-removed:: 3.13 3.15 @@ -2908,7 +2923,7 @@ Notes: .. rubric:: Footnotes -.. [#] If, that is, we ignore the effects of Relativity +.. [#] If, that is, we ignore the effects of relativity. .. [#] This matches the definition of the "proleptic Gregorian" calendar in Dershowitz and Reingold's book *Calendrical Calculations*, From d931725bc850cd096f6703bc285e885f1e015f05 Mon Sep 17 00:00:00 2001 From: Benedikt Johannes Date: Fri, 6 Mar 2026 13:22:21 +0100 Subject: [PATCH 020/775] gh-144370: Disallow usage of control characters in status in wsgiref.handlers for security (#144371) Disallow usage of control characters in status in wsgiref.handlers to prevent HTTP header injections. Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Victor Stinner --- Lib/test/test_wsgiref.py | 19 +++++++++++++++++++ Lib/wsgiref/handlers.py | 4 +++- Misc/ACKS | 1 + ...-01-31-21-56-54.gh-issue-144370.fp9m8t.rst | 2 ++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py index a7a5c5ba33d..3379df37d38 100644 --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -855,6 +855,25 @@ def write(self, b): self.assertIsNotNone(h.status) self.assertIsNotNone(h.environ) + def testRaisesControlCharacters(self): + for c0 in control_characters_c0(): + with self.subTest(c0): + base = BaseHandler() + with self.assertRaises(ValueError): + base.start_response(c0, [('x', 'y')]) + + base = BaseHandler() + with self.assertRaises(ValueError): + base.start_response('200 OK', [(c0, 'y')]) + + # HTAB (\x09) is allowed in header values, but not in names. + base = BaseHandler() + if c0 != "\t": + with self.assertRaises(ValueError): + base.start_response('200 OK', [('x', c0)]) + else: + base.start_response('200 OK', [('x', c0)]) + class TestModule(unittest.TestCase): def test_deprecated__version__(self): diff --git a/Lib/wsgiref/handlers.py b/Lib/wsgiref/handlers.py index 9353fb67862..b82862deea7 100644 --- a/Lib/wsgiref/handlers.py +++ b/Lib/wsgiref/handlers.py @@ -1,7 +1,7 @@ """Base classes for server/gateway implementations""" from .util import FileWrapper, guess_scheme, is_hop_by_hop -from .headers import Headers +from .headers import Headers, _name_disallowed_re import sys, os, time @@ -250,6 +250,8 @@ def start_response(self, status, headers,exc_info=None): return self.write def _validate_status(self, status): + if _name_disallowed_re.search(status): + raise ValueError("Control characters are not allowed in status") if len(status) < 4: raise AssertionError("Status must be at least 4 characters") if not status[:3].isdigit(): diff --git a/Misc/ACKS b/Misc/ACKS index e38bda37bfa..88c0a68f1e6 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1086,6 +1086,7 @@ Wolfgang Langner Detlef Lannert Rémi Lapeyre Soren Larsen +Seth Michael Larson Amos Latteier Keenan Lau Piers Lauder diff --git a/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst b/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst new file mode 100644 index 00000000000..2d13a061132 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst @@ -0,0 +1,2 @@ +Disallow usage of control characters in status in :mod:`wsgiref.handlers` to prevent HTTP header injections. +Patch by Benedikt Johannes. From 6c8c72f7feb4207c62ac857443943e61977d6a94 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 6 Mar 2026 16:51:36 +0100 Subject: [PATCH 021/775] gh-145548: Use VMADDR_CID_LOCAL in VSOCK socket tests (#145589) Prefer VMADDR_CID_LOCAL instead of VMADDR_CID_ANY for bind() in the server. Skip the test if bind() fails with EADDRNOTAVAIL. Log vsock CID in test.pythoninfo. --- Lib/test/pythoninfo.py | 4 ++++ Lib/test/test_socket.py | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 6df59946574..219fbb4bb1b 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -751,6 +751,10 @@ def collect_test_socket(info_add): if name.startswith('HAVE_')] copy_attributes(info_add, test_socket, 'test_socket.%s', attributes) + # Get IOCTL_VM_SOCKETS_GET_LOCAL_CID of /dev/vsock + cid = test_socket.get_cid() + info_add('test_socket.get_cid', cid) + def collect_support(info_add): try: diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 9ad5b29ea58..9e030694943 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -563,8 +563,8 @@ def clientTearDown(self): @unittest.skipIf(WSL, 'VSOCK does not work on Microsoft WSL') @unittest.skipUnless(HAVE_SOCKET_VSOCK, 'VSOCK sockets required for this test.') -@unittest.skipUnless(get_cid() != 2, # VMADDR_CID_HOST - "This test can only be run on a virtual guest.") +@unittest.skipIf(get_cid() == getattr(socket, 'VMADDR_CID_HOST', 2), + "This test can only be run on a virtual guest.") class ThreadedVSOCKSocketStreamTest(unittest.TestCase, ThreadableTest): def __init__(self, methodName='runTest'): @@ -574,7 +574,16 @@ def __init__(self, methodName='runTest'): def setUp(self): self.serv = socket.socket(socket.AF_VSOCK, socket.SOCK_STREAM) self.addCleanup(self.serv.close) - self.serv.bind((socket.VMADDR_CID_ANY, VSOCKPORT)) + cid = get_cid() + if cid in (socket.VMADDR_CID_HOST, socket.VMADDR_CID_ANY): + cid = socket.VMADDR_CID_LOCAL + try: + self.serv.bind((cid, VSOCKPORT)) + except OSError as exc: + if exc.errno == errno.EADDRNOTAVAIL: + self.skipTest(f"bind() failed with {exc!r}") + else: + raise self.serv.listen() self.serverExplicitReady() self.serv.settimeout(support.LOOPBACK_TIMEOUT) From b28e5f58ebf8d9badcc893cd189cb1575d4e3614 Mon Sep 17 00:00:00 2001 From: Andrew Barnes Date: Fri, 6 Mar 2026 11:10:12 -0500 Subject: [PATCH 022/775] gh-69223: Document that add_argument() returns an Action object (#145538) --- Doc/library/argparse.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 8f31e815e0e..5a463ee9821 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -698,6 +698,8 @@ The add_argument() method * deprecated_ - Whether or not use of the argument is deprecated. + The method returns an :class:`Action` object representing the argument. + The following sections describe how each of these are used. From 1d091a336e60b703a7d7ae4124f652eabe144f4e Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Fri, 6 Mar 2026 12:01:06 -0500 Subject: [PATCH 023/775] gh-145566: Skip stop-the-world when reassigning `__class__` on newly created objects (gh-145567) --- ...26-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst | 2 ++ Objects/typeobject.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst new file mode 100644 index 00000000000..723b81ddc5f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst @@ -0,0 +1,2 @@ +In the free threading build, skip the stop-the-world pause when reassigning +``__class__`` on a newly created object. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1fdd3cbdaaa..27ec8bb40a9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -7568,7 +7568,11 @@ object_set_class_world_stopped(PyObject *self, PyTypeObject *newto) assert(_PyObject_GetManagedDict(self) == dict); - if (_PyDict_DetachFromObject(dict, self) < 0) { + int err; + Py_BEGIN_CRITICAL_SECTION(dict); + err = _PyDict_DetachFromObject(dict, self); + Py_END_CRITICAL_SECTION(); + if (err < 0) { return -1; } @@ -7608,10 +7612,15 @@ object_set_class(PyObject *self, PyObject *value, void *closure) return -1; } - types_stop_world(); + int unique = _PyObject_IsUniquelyReferenced(self); + if (!unique) { + types_stop_world(); + } PyTypeObject *oldto = Py_TYPE(self); int res = object_set_class_world_stopped(self, newto); - types_start_world(); + if (!unique) { + types_start_world(); + } if (res == 0) { if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_DECREF(oldto); From c1d77683213c400fca144692654845e6f5418981 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 6 Mar 2026 21:00:06 +0100 Subject: [PATCH 024/775] gh-145376: Fix crashes in `md5module.c` and `hmacmodule.c` (#145422) Fix a possible NULL pointer dereference in `md5module.c` and a double-free in `hmacmodule.c`. Those crashes only occur in error paths taken when the interpreter fails to allocate memory. --- .../Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst | 2 ++ Modules/hmacmodule.c | 4 ++-- Modules/md5module.c | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst diff --git a/Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst b/Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst new file mode 100644 index 00000000000..b6dbda04271 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst @@ -0,0 +1,2 @@ +Fix double free and null pointer dereference in unusual error scenarios +in :mod:`hashlib` and :mod:`hmac` modules. diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 7a040103bcb..1a212fa3d37 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1378,7 +1378,6 @@ static void py_hmac_hinfo_ht_free(void *hinfo) { py_hmac_hinfo *entry = (py_hmac_hinfo *)hinfo; - assert(entry->display_name != NULL); if (--(entry->refcnt) == 0) { Py_CLEAR(entry->display_name); PyMem_Free(hinfo); @@ -1477,7 +1476,8 @@ py_hmac_hinfo_ht_new(void) e->hashlib_name == NULL ? e->name : e->hashlib_name ); if (value->display_name == NULL) { - PyMem_Free(value); + /* 'value' is owned by the table (refcnt > 0), + so _Py_hashtable_destroy() will free it. */ goto error; } } diff --git a/Modules/md5module.c b/Modules/md5module.c index 56e9faf4c62..e598b1fe672 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -87,7 +87,10 @@ static void MD5_dealloc(PyObject *op) { MD5object *ptr = _MD5object_CAST(op); - Hacl_Hash_MD5_free(ptr->hash_state); + if (ptr->hash_state != NULL) { + Hacl_Hash_MD5_free(ptr->hash_state); + ptr->hash_state = NULL; + } PyTypeObject *tp = Py_TYPE(op); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); From 9159287f58f7a5a7e59edffaf3094ea62e1633eb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 6 Mar 2026 22:57:44 +0100 Subject: [PATCH 025/775] gh-144175: Add PyArg_ParseArray() function (#144283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PyArg_ParseArray() and PyArg_ParseArrayAndKeywords() functions to parse arguments of functions using the METH_FASTCALL calling convention. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/c-api/arg.rst | 22 +++ Doc/whatsnew/3.15.rst | 5 + Include/cpython/modsupport.h | 13 ++ Lib/test/test_capi/test_modsupport.py | 19 +++ ...-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst | 3 + Modules/_testcapi/modsupport.c | 28 ++++ Python/getargs.c | 128 ++++++++++++++++-- 7 files changed, 204 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index fd6be6a9b67..4a3a6347239 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -516,6 +516,28 @@ API Functions } +.. c:function:: int PyArg_ParseArray(PyObject *const *args, Py_ssize_t nargs, const char *format, ...) + + Parse the parameters of a function that takes only array parameters into + local variables (that is, a function using the :c:macro:`METH_FASTCALL` + calling convention). + Returns true on success; on failure, it returns false and raises the + appropriate exception. + + .. versionadded:: next + + +.. c:function:: int PyArg_ParseArrayAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, const char *format, const char * const *kwlist, ...) + + Parse the parameters of a function that takes both array and keyword + parameters into local variables (that is, a function using the + :c:macro:`METH_FASTCALL` ``|`` :c:macro:`METH_KEYWORDS` calling convention). + Returns true on success; on failure, it returns false and raises the + appropriate exception. + + .. versionadded:: next + + .. c:function:: int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) A simpler form of parameter retrieval which does not use a format string to diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 0b5902bb013..42b6171c1a8 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1607,6 +1607,11 @@ C API changes New features ------------ +* Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` + functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` + calling convention. + (Contributed by Victor Stinner in :gh:`144175`.) + * Add the following functions for the new :class:`frozendict` type: * :c:func:`PyAnyDict_Check` diff --git a/Include/cpython/modsupport.h b/Include/cpython/modsupport.h index 61344421064..b9f253e06b3 100644 --- a/Include/cpython/modsupport.h +++ b/Include/cpython/modsupport.h @@ -2,6 +2,19 @@ # error "this header file must not be included directly" #endif +PyAPI_FUNC(int) PyArg_ParseArray( + PyObject *const *args, + Py_ssize_t nargs, + const char *format, + ...); +PyAPI_FUNC(int) PyArg_ParseArrayAndKeywords( + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwnames, + const char *format, + const char * const *kwlist, + ...); + // A data structure that can be used to run initialization code once in a // thread-safe manner. The C++11 equivalent is std::call_once. typedef struct { diff --git a/Lib/test/test_capi/test_modsupport.py b/Lib/test/test_capi/test_modsupport.py index 1520489f843..29bebf847aa 100644 --- a/Lib/test/test_capi/test_modsupport.py +++ b/Lib/test/test_capi/test_modsupport.py @@ -152,3 +152,22 @@ def test_negative_freethreading(self, modname, minor, build): msg = "only compatible with free-threaded CPython" with self.assertRaisesRegex(ImportError, msg): _testcapi.pyabiinfo_check(modname, 1, minor, ft_flag, build, 0) + + +class TestModsupport(unittest.TestCase): + def test_pyarg_parsearray(self): + func = _testcapi.pyarg_parsearray + self.assertEqual(func(1, 2), (1, 2, 0)) + self.assertEqual(func(1, 2, 3), (1, 2, 3)) + self.assertRaises(TypeError, func, 1) + self.assertRaises(TypeError, func, "str", 2) + + def test_funcandkeywords(self): + func = _testcapi.pyarg_parsearrayandkeywords + self.assertEqual(func(1, 2), (1, 2, 0)) + self.assertEqual(func(1, 2, 3), (1, 2, 3)) + self.assertEqual(func(1, b=2), (1, 2, 0)) + self.assertEqual(func(1, b=2, c=3), (1, 2, 3)) + self.assertRaises(TypeError, func, 1) + self.assertRaises(TypeError, func, "str", 2) + self.assertRaises(TypeError, func, 1, z=2) diff --git a/Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst b/Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst new file mode 100644 index 00000000000..da1e489bb3d --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst @@ -0,0 +1,3 @@ +Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` +functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` +calling convention. Patch by Victor Stinner. diff --git a/Modules/_testcapi/modsupport.c b/Modules/_testcapi/modsupport.c index 6746eb9eb1e..151e4aa19af 100644 --- a/Modules/_testcapi/modsupport.c +++ b/Modules/_testcapi/modsupport.c @@ -25,8 +25,36 @@ pyabiinfo_check(PyObject *Py_UNUSED(module), PyObject *args) Py_RETURN_NONE; } +static PyObject * +pyarg_parsearray(PyObject* self, PyObject* const* args, Py_ssize_t nargs) +{ + int a, b, c = 0; + if (!PyArg_ParseArray(args, nargs, "ii|i", &a, &b, &c)) { + return NULL; + } + return Py_BuildValue("iii", a, b, c); +} + +static PyObject * +pyarg_parsearrayandkeywords(PyObject* self, PyObject* const* args, + Py_ssize_t nargs, PyObject* kwnames) +{ + int a, b, c = 0; + const char *kwlist[] = {"a", "b", "c", NULL}; + if (!PyArg_ParseArrayAndKeywords(args, nargs, kwnames, + "ii|i", kwlist, + &a, &b, &c)) { + return NULL; + } + return Py_BuildValue("iii", a, b, c); +} + static PyMethodDef TestMethods[] = { {"pyabiinfo_check", pyabiinfo_check, METH_VARARGS}, + {"pyarg_parsearray", _PyCFunction_CAST(pyarg_parsearray), METH_FASTCALL}, + {"pyarg_parsearrayandkeywords", + _PyCFunction_CAST(pyarg_parsearrayandkeywords), + METH_FASTCALL | METH_KEYWORDS}, {NULL}, }; diff --git a/Python/getargs.c b/Python/getargs.c index c119ca5c353..31cd4ad3f65 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -57,8 +57,15 @@ static const char *convertsimple(PyObject *, const char **, va_list *, int, static Py_ssize_t convertbuffer(PyObject *, const void **p, const char **); static int getbuffer(PyObject *, Py_buffer *, const char**); -static int vgetargskeywords(PyObject *, PyObject *, - const char *, const char * const *, va_list *, int); +static int +vgetargskeywords(PyObject *args, PyObject *kwargs, + const char *format, const char * const *kwlist, + va_list *p_va, int flags); +static int +vgetargskeywords_impl(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + const char *format, const char * const *kwlist, + va_list *p_va, int flags); static int vgetargskeywordsfast(PyObject *, PyObject *, struct _PyArg_Parser *, va_list *, int); static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, @@ -129,6 +136,40 @@ _PyArg_ParseStack(PyObject *const *args, Py_ssize_t nargs, const char *format, . return retval; } +int +PyArg_ParseArray(PyObject *const *args, Py_ssize_t nargs, const char *format, ...) +{ + va_list va; + va_start(va, format); + int retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0); + va_end(va); + return retval; +} + +int +PyArg_ParseArrayAndKeywords(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwnames, + const char *format, + const char * const *kwlist, ...) +{ + if ((args == NULL && nargs != 0) || + (kwnames != NULL && !PyTuple_Check(kwnames)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_list va; + va_start(va, kwlist); + int retval = vgetargskeywords_impl(args, nargs, NULL, kwnames, format, + kwlist, &va, 0); + va_end(va); + return retval; +} + + int PyArg_VaParse(PyObject *args, const char *format, va_list va) { @@ -1612,11 +1653,27 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs) static PyObject * new_kwtuple(const char * const *keywords, int total, int pos); +static PyObject* +find_keyword_str(PyObject *kwnames, PyObject *const *kwstack, const char *key) +{ + Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames); + for (Py_ssize_t i = 0; i < nkwargs; i++) { + PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); + assert(PyUnicode_Check(kwname)); + if (PyUnicode_EqualToUTF8(kwname, key)) { + return Py_NewRef(kwstack[i]); + } + } + return NULL; +} + #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') static int -vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, - const char * const *kwlist, va_list *p_va, int flags) +vgetargskeywords_impl(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + const char *format, const char * const *kwlist, + va_list *p_va, int flags) { char msgbuf[512]; int levels[32]; @@ -1625,16 +1682,18 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, int max = INT_MAX; int i, pos, len; int skip = 0; - Py_ssize_t nargs, nkwargs; + Py_ssize_t nkwargs; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; freelist_t freelist; + PyObject * const *kwstack = NULL; freelist.entries = static_entries; freelist.first_available = 0; freelist.entries_malloced = 0; - assert(args != NULL && PyTuple_Check(args)); + assert(args != NULL || nargs == 0); assert(kwargs == NULL || PyDict_Check(kwargs)); + assert(kwnames == NULL || PyTuple_Check(kwnames)); assert(format != NULL); assert(kwlist != NULL); assert(p_va != NULL); @@ -1672,8 +1731,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, freelist.entries_malloced = 1; } - nargs = PyTuple_GET_SIZE(args); - nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs); + if (kwargs != NULL) { + nkwargs = PyDict_GET_SIZE(kwargs); + } + else if (kwnames != NULL) { + nkwargs = PyTuple_GET_SIZE(kwnames); + kwstack = args + nargs; + } + else { + nkwargs = 0; + } if (nargs + nkwargs > len) { /* Adding "keyword" (when nargs == 0) prevents producing wrong error messages in some special cases (see bpo-31229). */ @@ -1757,11 +1824,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, if (!skip) { PyObject *current_arg; if (i < nargs) { - current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i)); + current_arg = Py_NewRef(args[i]); } else if (nkwargs && i >= pos) { - if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { - return cleanreturn(0, &freelist); + if (kwargs != NULL) { + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + return cleanreturn(0, &freelist); + } + } + else { + current_arg = find_keyword_str(kwnames, kwstack, kwlist[i]); } if (current_arg) { --nkwargs; @@ -1846,8 +1918,13 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, /* make sure there are no arguments given by name and position */ for (i = pos; i < nargs; i++) { PyObject *current_arg; - if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { - return cleanreturn(0, &freelist); + if (kwargs != NULL) { + if (PyDict_GetItemStringRef(kwargs, kwlist[i], ¤t_arg) < 0) { + return cleanreturn(0, &freelist); + } + } + else { + current_arg = find_keyword_str(kwnames, kwstack, kwlist[i]); } if (current_arg) { Py_DECREF(current_arg); @@ -1863,7 +1940,20 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, } /* make sure there are no extraneous keyword arguments */ j = 0; - while (PyDict_Next(kwargs, &j, &key, NULL)) { + while (1) { + if (kwargs != NULL) { + if (!PyDict_Next(kwargs, &j, &key, NULL)) { + break; + } + } + else { + if (j >= nkwargs) { + break; + } + key = PyTuple_GET_ITEM(kwnames, j); + j++; + } + int match = 0; if (!PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, @@ -1921,6 +2011,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, return cleanreturn(1, &freelist); } +static int +vgetargskeywords(PyObject *argstuple, PyObject *kwargs, + const char *format, const char * const *kwlist, + va_list *p_va, int flags) +{ + PyObject *const *args = _PyTuple_ITEMS(argstuple); + Py_ssize_t nargs = PyTuple_GET_SIZE(argstuple); + return vgetargskeywords_impl(args, nargs, kwargs, NULL, + format, kwlist, p_va, flags); +} static int scan_keywords(const char * const *keywords, int *ptotal, int *pposonly) From 46761c976060c3e9ddbd33ea64601b54a97ddbe0 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 7 Mar 2026 17:14:44 +0900 Subject: [PATCH 026/775] gh-116738: Make mmap.set_name thread-safe (#145555) * Add critical section around mmap.set_name to make it thread-safe * Add news entry * Apply suggestion from @aisk --- .../2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst | 2 ++ Modules/clinic/mmapmodule.c.h | 4 +++- Modules/mmapmodule.c | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst new file mode 100644 index 00000000000..212fd7b0290 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst @@ -0,0 +1,2 @@ +Make :meth:`!mmap.mmap.set_name` thread-safe on the :term:`free threaded ` build. diff --git a/Modules/clinic/mmapmodule.c.h b/Modules/clinic/mmapmodule.c.h index db640800ad7..98c5bf6a2fb 100644 --- a/Modules/clinic/mmapmodule.c.h +++ b/Modules/clinic/mmapmodule.c.h @@ -556,7 +556,9 @@ mmap_mmap_set_name(PyObject *self, PyObject *arg) PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } + Py_BEGIN_CRITICAL_SECTION(self); return_value = mmap_mmap_set_name_impl((mmap_object *)self, name); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -879,4 +881,4 @@ exit: #ifndef MMAP_MMAP_MADVISE_METHODDEF #define MMAP_MMAP_MADVISE_METHODDEF #endif /* !defined(MMAP_MMAP_MADVISE_METHODDEF) */ -/*[clinic end generated code: output=8389e3c8e3db3a78 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1122b93314aebc5c input=a9049054013a1b77]*/ diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 16e3c0ecefd..61d8a043a04 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1122,6 +1122,7 @@ mmap_mmap_seek_impl(mmap_object *self, Py_ssize_t dist, int how) } /*[clinic input] +@critical_section mmap.mmap.set_name name: str @@ -1131,7 +1132,7 @@ mmap.mmap.set_name static PyObject * mmap_mmap_set_name_impl(mmap_object *self, const char *name) -/*[clinic end generated code: output=1edaf4fd51277760 input=6c7dd91cad205f07]*/ +/*[clinic end generated code: output=1edaf4fd51277760 input=7c0e2a17ca6d1adc]*/ { #if defined(MAP_ANONYMOUS) && defined(__linux__) const char *prefix = "cpython:mmap:"; From 0aeaaafac476119f242fe717ce60d2070172127b Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Sat, 7 Mar 2026 10:05:08 +0100 Subject: [PATCH 027/775] gh-145376: Fix refleak in `queuemodule.c` out-of-memory path (#145543) --- Modules/_queuemodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index a45959346bc..f2246dd36cf 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -165,6 +165,7 @@ RingBuf_Put(RingBuf *buf, PyObject *item) // Buffer is full, grow it. if (resize_ringbuf(buf, buf->items_cap * 2) < 0) { PyErr_NoMemory(); + Py_DECREF(item); return -1; } } From 2cf6b2caade94e75f10363df6f432a3e6515be6c Mon Sep 17 00:00:00 2001 From: Ramin Farajpour Cami Date: Sat, 7 Mar 2026 17:01:45 +0330 Subject: [PATCH 028/775] gh-145623: Fix crashes on uninitialized struct.Struct objects (gh-145624) --- Lib/test/test_struct.py | 2 ++ .../Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst | 3 +++ Modules/_struct.c | 2 ++ 3 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index aa793a2c223..4cbfd7ad8b1 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -836,6 +836,8 @@ def test_operations_on_half_initialized_Struct(self): self.assertRaises(RuntimeError, S.unpack, spam) self.assertRaises(RuntimeError, S.unpack_from, spam) self.assertRaises(RuntimeError, getattr, S, 'format') + self.assertRaises(RuntimeError, S.__sizeof__) + self.assertRaises(RuntimeError, repr, S) self.assertEqual(S.size, -1) diff --git a/Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst b/Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst new file mode 100644 index 00000000000..77b43e79e35 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst @@ -0,0 +1,3 @@ +Fix crash in :mod:`struct` when calling :func:`repr` or +``__sizeof__()`` on an uninitialized :class:`struct.Struct` +object created via ``Struct.__new__()`` without calling ``__init__()``. diff --git a/Modules/_struct.c b/Modules/_struct.c index ae8a8ffb3c0..dcc3c7ec63e 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -2382,6 +2382,7 @@ static PyObject * Struct___sizeof___impl(PyStructObject *self) /*[clinic end generated code: output=2d0d78900b4cdb4e input=faca5925c1f1ffd0]*/ { + ENSURE_STRUCT_IS_READY(self); size_t size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode); for (formatcode *code = self->s_codes; code->fmtdef != NULL; code++) { size += sizeof(formatcode); @@ -2393,6 +2394,7 @@ static PyObject * s_repr(PyObject *op) { PyStructObject *self = PyStructObject_CAST(op); + ENSURE_STRUCT_IS_READY(self); PyObject* fmt = PyUnicode_FromStringAndSize( PyBytes_AS_STRING(self->s_format), PyBytes_GET_SIZE(self->s_format)); if (fmt == NULL) { From 149c4657507d17f78dd0938419a5a24ed71dc07e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:53:13 +0200 Subject: [PATCH 029/775] Fix bug notifier for issues with no body text (#145603) --- .github/workflows/new-bugs-announce-notifier.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/new-bugs-announce-notifier.yml b/.github/workflows/new-bugs-announce-notifier.yml index b25750f0897..9ee38a4fd1c 100644 --- a/.github/workflows/new-bugs-announce-notifier.yml +++ b/.github/workflows/new-bugs-announce-notifier.yml @@ -44,7 +44,7 @@ jobs: // We need to truncate the body size, because the max size for // the whole payload is 16kb. We want to be safe and assume that // body can take up to ~8kb of space. - body : issue.data.body.substring(0, 8000) + body : (issue.data.body || "").substring(0, 8000) }; const data = { From 5a15a52dd1dee37af4f2b3a6b15a9f5735f75c6e Mon Sep 17 00:00:00 2001 From: James Date: Sun, 8 Mar 2026 18:41:47 -0400 Subject: [PATCH 030/775] gh-145642: Docs: Avoid warning for invalid escape sequence in tutorial (#145643) * Match tutorial output to real interpreter output * Avoid invalid escape sequence in example Co-authored-by: Ned Batchelder --------- Co-authored-by: Ned Batchelder --- Doc/tutorial/introduction.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index deabac52530..7778e37a9ad 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -184,11 +184,11 @@ If you don't want characters prefaced by ``\`` to be interpreted as special characters, you can use *raw strings* by adding an ``r`` before the first quote:: - >>> print('C:\some\name') # here \n means newline! - C:\some + >>> print('C:\this\name') # here \t means tab, \n means newline + C: his ame - >>> print(r'C:\some\name') # note the r before the quote - C:\some\name + >>> print(r'C:\this\name') # note the r before the quote + C:\this\name There is one subtle aspect to raw strings: a raw string may not end in an odd number of ``\`` characters; see From 015613384fea7a00bb2077760e325e5baab6814b Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 9 Mar 2026 03:25:21 +0100 Subject: [PATCH 031/775] gh-145219: Add Emscripten cross-build and clean configurability (#145581) Modifies the Emscripten build script to allow for custom cross-build directory names, and to only clean Emscripten-specific paths (optionally including the build python). Co-authored-by: Russell Keith-Magee --- .gitignore | 2 +- Tools/wasm/emscripten/__main__.py | 103 ++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index e234d86e8d5..f9d2cdfc32b 100644 --- a/.gitignore +++ b/.gitignore @@ -137,7 +137,7 @@ Tools/unicode/data/ /config.status /config.status.lineno /.ccache -/cross-build/ +/cross-build*/ /jit_stencils*.h /platform /profile-clean-stamp diff --git a/Tools/wasm/emscripten/__main__.py b/Tools/wasm/emscripten/__main__.py index 856a7f8252b..14d32279a8c 100644 --- a/Tools/wasm/emscripten/__main__.py +++ b/Tools/wasm/emscripten/__main__.py @@ -24,14 +24,25 @@ CHECKOUT = EMSCRIPTEN_DIR.parent.parent.parent EMSCRIPTEN_VERSION_FILE = EMSCRIPTEN_DIR / "emscripten_version.txt" -CROSS_BUILD_DIR = CHECKOUT / "cross-build" -NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build" +DEFAULT_CROSS_BUILD_DIR = CHECKOUT / "cross-build" HOST_TRIPLE = "wasm32-emscripten" -DOWNLOAD_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "build" -HOST_BUILD_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "build" -HOST_DIR = HOST_BUILD_DIR / "python" -PREFIX_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "prefix" + +def get_build_paths(cross_build_dir=None): + """Compute all build paths from the given cross-build directory.""" + if cross_build_dir is None: + cross_build_dir = DEFAULT_CROSS_BUILD_DIR + cross_build_dir = Path(cross_build_dir).absolute() + host_triple_dir = cross_build_dir / HOST_TRIPLE + return { + "cross_build_dir": cross_build_dir, + "native_build_dir": cross_build_dir / "build", + "host_triple_dir": host_triple_dir, + "host_build_dir": host_triple_dir / "build", + "host_dir": host_triple_dir / "build" / "python", + "prefix_dir": host_triple_dir / "prefix", + } + LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local" LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n" @@ -115,12 +126,17 @@ def updated_env(updates, emsdk_cache): return environment -def subdir(working_dir, *, clean_ok=False): - """Decorator to change to a working directory.""" +def subdir(path_key, *, clean_ok=False): + """Decorator to change to a working directory. + + path_key is a key into context.build_paths, used to resolve the working + directory at call time. + """ def decorator(func): @functools.wraps(func) def wrapper(context): + working_dir = context.build_paths[path_key] try: tput_output = subprocess.check_output( ["tput", "cols"], encoding="utf-8" @@ -177,20 +193,21 @@ def build_platform(): return sysconfig.get_config_var("BUILD_GNU_TYPE") -def build_python_path(): +def build_python_path(context): """The path to the build Python binary.""" - binary = NATIVE_BUILD_DIR / "python" + native_build_dir = context.build_paths["native_build_dir"] + binary = native_build_dir / "python" if not binary.is_file(): binary = binary.with_suffix(".exe") if not binary.is_file(): raise FileNotFoundError( - f"Unable to find `python(.exe)` in {NATIVE_BUILD_DIR}" + f"Unable to find `python(.exe)` in {native_build_dir}" ) return binary -@subdir(NATIVE_BUILD_DIR, clean_ok=True) +@subdir("native_build_dir", clean_ok=True) def configure_build_python(context, working_dir): """Configure the build/host Python.""" if LOCAL_SETUP.exists(): @@ -206,12 +223,12 @@ def configure_build_python(context, working_dir): call(configure, quiet=context.quiet) -@subdir(NATIVE_BUILD_DIR) +@subdir("native_build_dir") def make_build_python(context, working_dir): """Make/build the build Python.""" call(["make", "--jobs", str(cpu_count()), "all"], quiet=context.quiet) - binary = build_python_path() + binary = build_python_path(context) cmd = [ binary, "-c", @@ -241,7 +258,7 @@ def download_and_unpack(working_dir: Path, url: str, expected_shasum: str): shutil.unpack_archive(tmp_file.name, working_dir) -@subdir(HOST_BUILD_DIR, clean_ok=True) +@subdir("host_build_dir", clean_ok=True) def make_emscripten_libffi(context, working_dir): ver = "3.4.6" libffi_dir = working_dir / f"libffi-{ver}" @@ -253,13 +270,15 @@ def make_emscripten_libffi(context, working_dir): ) call( [EMSCRIPTEN_DIR / "make_libffi.sh"], - env=updated_env({"PREFIX": PREFIX_DIR}, context.emsdk_cache), + env=updated_env( + {"PREFIX": context.build_paths["prefix_dir"]}, context.emsdk_cache + ), cwd=libffi_dir, quiet=context.quiet, ) -@subdir(HOST_BUILD_DIR, clean_ok=True) +@subdir("host_build_dir", clean_ok=True) def make_mpdec(context, working_dir): ver = "4.0.1" mpdec_dir = working_dir / f"mpdecimal-{ver}" @@ -275,7 +294,7 @@ def make_mpdec(context, working_dir): mpdec_dir / "configure", "CFLAGS=-fPIC", "--prefix", - PREFIX_DIR, + context.build_paths["prefix_dir"], "--disable-shared", ], cwd=mpdec_dir, @@ -289,14 +308,15 @@ def make_mpdec(context, working_dir): ) -@subdir(HOST_DIR, clean_ok=True) +@subdir("host_dir", clean_ok=True) def configure_emscripten_python(context, working_dir): """Configure the emscripten/host build.""" + paths = context.build_paths config_site = os.fsdecode(EMSCRIPTEN_DIR / "config.site-wasm32-emscripten") emscripten_build_dir = working_dir.relative_to(CHECKOUT) - python_build_dir = NATIVE_BUILD_DIR / "build" + python_build_dir = paths["native_build_dir"] / "build" lib_dirs = list(python_build_dir.glob("lib.*")) assert len(lib_dirs) == 1, ( f"Expected a single lib.* directory in {python_build_dir}" @@ -322,13 +342,13 @@ def configure_emscripten_python(context, working_dir): capture_output=True, ) host_runner = res.stdout.strip() - pkg_config_path_dir = (PREFIX_DIR / "lib/pkgconfig/").resolve() + pkg_config_path_dir = (paths["prefix_dir"] / "lib/pkgconfig/").resolve() env_additions = { "CONFIG_SITE": config_site, "HOSTRUNNER": host_runner, "EM_PKG_CONFIG_PATH": str(pkg_config_path_dir), } - build_python = os.fsdecode(build_python_path()) + build_python = os.fsdecode(build_python_path(context)) configure = [ "emconfigure", os.path.relpath(CHECKOUT / "configure", working_dir), @@ -342,7 +362,7 @@ def configure_emscripten_python(context, working_dir): "--disable-ipv6", "--enable-big-digits=30", "--enable-wasm-dynamic-linking", - f"--prefix={PREFIX_DIR}", + f"--prefix={paths['prefix_dir']}", ] if pydebug: configure.append("--with-pydebug") @@ -403,7 +423,7 @@ def configure_emscripten_python(context, working_dir): sys.stdout.flush() -@subdir(HOST_DIR) +@subdir("host_dir") def make_emscripten_python(context, working_dir): """Run `make` for the emscripten/host build.""" call( @@ -432,9 +452,17 @@ def build_all(context): def clean_contents(context): """Delete all files created by this script.""" - if CROSS_BUILD_DIR.exists(): - print(f"🧹 Deleting {CROSS_BUILD_DIR} ...") - shutil.rmtree(CROSS_BUILD_DIR) + if context.target in {"all", "build"}: + build_dir = context.build_paths["native_build_dir"] + if build_dir.exists(): + print(f"🧹 Deleting {build_dir} ...") + shutil.rmtree(build_dir) + + if context.target in {"all", "host"}: + host_triple_dir = context.build_paths["host_triple_dir"] + if host_triple_dir.exists(): + print(f"🧹 Deleting {host_triple_dir} ...") + shutil.rmtree(host_triple_dir) if LOCAL_SETUP.exists(): with LOCAL_SETUP.open("rb") as file: @@ -472,6 +500,17 @@ def main(): clean = subcommands.add_parser( "clean", help="Delete files and directories created by this script" ) + clean.add_argument( + "target", + nargs="?", + default="host", + choices=["all", "host", "build"], + help=( + "What should be cleaned. 'build' for just the build platform, or " + "'host' for the host platform, or 'all' for both. Defaults to 'host'." + ), + ) + for subcommand in ( build, configure_build, @@ -489,6 +528,14 @@ def main(): dest="quiet", help="Redirect output from subprocesses to a log file", ) + subcommand.add_argument( + "--cross-build-dir", + action="store", + default=None, + dest="cross_build_dir", + help="Path to the cross-build directory " + f"(default: {DEFAULT_CROSS_BUILD_DIR})", + ) subcommand.add_argument( "--emsdk-cache", action="store", @@ -521,6 +568,8 @@ def main(): context = parser.parse_args() + context.build_paths = get_build_paths(context.cross_build_dir) + if context.emsdk_cache: validate_emsdk_version(context.emsdk_cache) context.emsdk_cache = Path(context.emsdk_cache).absolute() From b4460925a48f41497857fa2b20fbfb33836ceed8 Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Mon, 9 Mar 2026 10:23:34 +0100 Subject: [PATCH 032/775] Fix intermittent `test_ci_fuzz_stdlib` failures (GH-145641) --- Lib/test/test_tools/test_compute_changes.py | 2 ++ Tools/build/compute-changes.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_tools/test_compute_changes.py b/Lib/test/test_tools/test_compute_changes.py index c4e3ffdb4de..351fb06a885 100644 --- a/Lib/test/test_tools/test_compute_changes.py +++ b/Lib/test/test_tools/test_compute_changes.py @@ -54,6 +54,8 @@ def test_ci_fuzz_stdlib(self): f = p / "file" elif p.is_file(): f = p + else: + self.fail(f"LIBRARY_FUZZER_PATHS contains an invalid entry: {p!r}") result = process_changed_files({f}) self.assertTrue(result.run_ci_fuzz_stdlib) self.assertTrue(is_fuzzable_library_file(f)) diff --git a/Tools/build/compute-changes.py b/Tools/build/compute-changes.py index 981e00e28b4..4d92b083026 100644 --- a/Tools/build/compute-changes.py +++ b/Tools/build/compute-changes.py @@ -90,7 +90,7 @@ # tarfile Path("Lib/tarfile.py"), # tomllib - Path("Modules/tomllib/"), + Path("Lib/tomllib/"), # xml Path("Lib/xml/"), Path("Lib/_markupbase.py"), From 201e18312c01178b34b77a989c7bee7db5f469fe Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 9 Mar 2026 13:50:45 +0100 Subject: [PATCH 033/775] gh-145376: Fix reference leaks in _lprof.c (#145539) --- Modules/_lsprof.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 025a3fac46e..a2d1aefb161 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -702,6 +702,7 @@ PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObje if (PyCFunction_Check(meth)) { return (PyObject*)((PyCFunctionObject *)meth); } + Py_DECREF(meth); } return NULL; } @@ -961,6 +962,8 @@ profiler_traverse(PyObject *op, visitproc visit, void *arg) ProfilerObject *self = ProfilerObject_CAST(op); Py_VISIT(Py_TYPE(op)); Py_VISIT(self->externalTimer); + Py_VISIT(self->missing); + return 0; } @@ -979,6 +982,7 @@ profiler_dealloc(PyObject *op) flush_unmatched(self); clearEntries(self); + Py_XDECREF(self->missing); Py_XDECREF(self->externalTimer); PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); @@ -1017,7 +1021,7 @@ profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, if (!monitoring) { return -1; } - self->missing = PyObject_GetAttrString(monitoring, "MISSING"); + Py_XSETREF(self->missing, PyObject_GetAttrString(monitoring, "MISSING")); if (!self->missing) { Py_DECREF(monitoring); return -1; From 8060aa5d7dd02c22a987e23cf5dbb7049b50b042 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 9 Mar 2026 14:17:27 +0100 Subject: [PATCH 034/775] gh-145376: Fix various refleaks in Objects/ (#145609) --- Modules/_cursesmodule.c | 5 +++++ Modules/binascii.c | 2 +- Objects/genericaliasobject.c | 3 +++ Objects/object.c | 5 +++-- Objects/structseq.c | 3 ++- Objects/typevarobject.c | 3 +-- Objects/unicodeobject.c | 2 +- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 61464348d6f..dd96f9aa62b 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1112,11 +1112,13 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, attr_old = getattrs(self->win); if (curses_wattrset(self, attr, "addstr") < 0) { curses_release_wstr(strtype, wstr); + Py_XDECREF(bytesobj); return NULL; } } #ifdef HAVE_NCURSESW if (strtype == 2) { + assert(bytesobj == NULL); if (use_xy) { rtn = mvwaddwstr(self->win,y,x,wstr); funcname = "mvwaddwstr"; @@ -1130,6 +1132,7 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, else #endif { + assert(wstr == NULL); const char *str = PyBytes_AS_STRING(bytesobj); if (use_xy) { rtn = mvwaddstr(self->win,y,x,str); @@ -1210,6 +1213,7 @@ _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, attr_old = getattrs(self->win); if (curses_wattrset(self, attr, "addnstr") < 0) { curses_release_wstr(strtype, wstr); + Py_XDECREF(bytesobj); return NULL; } } @@ -2212,6 +2216,7 @@ _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, attr_old = getattrs(self->win); if (curses_wattrset(self, attr, "insstr") < 0) { curses_release_wstr(strtype, wstr); + Py_XDECREF(bytesobj); return NULL; } } diff --git a/Modules/binascii.c b/Modules/binascii.c index e6cd6433806..3f3695d50f2 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -924,7 +924,7 @@ binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, } unsigned char *bin_data = PyBytesWriter_GetData(writer); if (bin_data == NULL) { - return NULL; + goto error; } uint32_t leftchar = 0; diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 119dd4b5c2d..7aef56cf4e9 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -299,6 +299,8 @@ subs_tvars(PyObject *obj, PyObject *params, &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg)); if (j < 0) { + Py_DECREF(subparams); + Py_DECREF(subargs); return NULL; } continue; @@ -455,6 +457,7 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje if (is_args_list) { args = tuple_args = PySequence_Tuple(args); if (args == NULL) { + Py_DECREF(item); return NULL; } } diff --git a/Objects/object.c b/Objects/object.c index b537c0d104e..e4059636146 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1295,6 +1295,7 @@ _PyObject_SetAttributeErrorContext(PyObject* v, PyObject* name) // Augment the exception with the name and object if (PyObject_SetAttr(exc, &_Py_ID(name), name) || PyObject_SetAttr(exc, &_Py_ID(obj), v)) { + Py_DECREF(exc); return 1; } restore: @@ -3077,9 +3078,9 @@ Py_ReprEnter(PyObject *obj) list = PyList_New(0); if (list == NULL) return -1; - if (PyDict_SetItem(dict, &_Py_ID(Py_Repr), list) < 0) + if (_PyDict_SetItem_Take2((PyDictObject *)dict, &_Py_ID(Py_Repr), list) < 0) { return -1; - Py_DECREF(list); + } } i = PyList_GET_SIZE(list); while (--i >= 0) { diff --git a/Objects/structseq.c b/Objects/structseq.c index 7a159338b9b..b8bb041f0cf 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -515,7 +515,8 @@ initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict, } if (_PyTuple_Resize(&keys, k) == -1) { - goto error; + assert(keys == NULL); + return -1; } if (PyDict_SetItemString(dict, match_args_key, keys) < 0) { diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 2ec546aff52..0a260f4c102 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -2305,13 +2305,12 @@ generic_class_getitem(PyObject *cls, PyObject *args, PyObject *kwargs) PyObject * _Py_subscript_generic(PyThreadState* unused, PyObject *params) { - params = unpack_typevartuples(params); - PyInterpreterState *interp = _PyInterpreterState_GET(); if (interp->cached_objects.generic_type == NULL) { PyErr_SetString(PyExc_SystemError, "Cannot find Generic type"); return NULL; } + params = unpack_typevartuples(params); PyObject *args[2] = {(PyObject *)interp->cached_objects.generic_type, params}; PyObject *result = call_typing_func_object("_GenericAlias", args, 2); Py_DECREF(params); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 7aa85a942e4..7756f1a8482 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5220,7 +5220,7 @@ unicode_decode_utf8_impl(_PyUnicodeWriter *writer, } if (_PyUnicodeWriter_Prepare(writer, end - s, 127) < 0) { - return -1; + goto onError; } } } From 886bc6e14bf01b615ffa328cd1acb46f9513a7fe Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 9 Mar 2026 14:19:36 +0100 Subject: [PATCH 035/775] gh-145376: Fix various reference leaks in Objects/ and Modules/ (#145385) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Modules/itertoolsmodule.c | 25 ++++++++++++++----------- Objects/enumobject.c | 12 +++++++----- Objects/listobject.c | 4 +++- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index ff0e2fd2b35..bc25bf6bfc1 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -3531,23 +3531,26 @@ count_traverse(PyObject *op, visitproc visit, void *arg) static PyObject * count_nextlong(countobject *lz) { - PyObject *long_cnt; - PyObject *stepped_up; - - long_cnt = lz->long_cnt; - if (long_cnt == NULL) { + if (lz->long_cnt == NULL) { /* Switch to slow_mode */ - long_cnt = PyLong_FromSsize_t(PY_SSIZE_T_MAX); - if (long_cnt == NULL) + lz->long_cnt = PyLong_FromSsize_t(PY_SSIZE_T_MAX); + if (lz->long_cnt == NULL) { return NULL; + } } - assert(lz->cnt == PY_SSIZE_T_MAX && long_cnt != NULL); + assert(lz->cnt == PY_SSIZE_T_MAX && lz->long_cnt != NULL); - stepped_up = PyNumber_Add(long_cnt, lz->long_step); - if (stepped_up == NULL) + // We hold one reference to "result" (a.k.a. the old value of + // lz->long_cnt); we'll either return it or keep it in lz->long_cnt. + PyObject *result = lz->long_cnt; + + PyObject *stepped_up = PyNumber_Add(result, lz->long_step); + if (stepped_up == NULL) { return NULL; + } lz->long_cnt = stepped_up; - return long_cnt; + + return result; } static PyObject * diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 814ce4f9195..70e7cce6aba 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -178,14 +178,16 @@ enum_traverse(PyObject *op, visitproc visit, void *arg) static inline PyObject * increment_longindex_lock_held(enumobject *en) { - PyObject *next_index = en->en_longindex; - if (next_index == NULL) { - next_index = PyLong_FromSsize_t(PY_SSIZE_T_MAX); - if (next_index == NULL) { + if (en->en_longindex == NULL) { + en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX); + if (en->en_longindex == NULL) { return NULL; } } - assert(next_index != NULL); + assert(en->en_longindex != NULL); + // We hold one reference to "next_index" (a.k.a. the old value of + // en->en_longindex); we'll either return it or keep it in en->en_longindex + PyObject *next_index = en->en_longindex; PyObject *stepped_up = PyNumber_Add(next_index, en->one); if (stepped_up == NULL) { return NULL; diff --git a/Objects/listobject.c b/Objects/listobject.c index 3921b7cd7b6..7fc21907fef 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -4294,7 +4294,9 @@ listiter_reduce_general(void *_it, int forward) } /* empty iterator, create an empty list */ list = PyList_New(0); - if (list == NULL) + if (list == NULL) { + Py_DECREF(iter); return NULL; + } return Py_BuildValue("N(N)", iter, list); } From 3a0c716ad4922a84c407b69f8fca10f070007356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Mon, 9 Mar 2026 13:28:00 +0000 Subject: [PATCH 036/775] GH-145278: freeze encodings (partially) and linecache (#145279) --- Makefile.pre.in | 20 +++++++++++++++++++ ...-02-26-21-22-34.gh-issue-145278.DHkYqt.rst | 4 ++++ PCbuild/_freeze_module.vcxproj | 20 +++++++++++++++++++ PCbuild/_freeze_module.vcxproj.filters | 12 +++++++++++ Python/frozen.c | 10 ++++++++++ Tools/build/freeze_modules.py | 10 ++++++---- 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst diff --git a/Makefile.pre.in b/Makefile.pre.in index 120a6add385..4c2426ed283 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1729,6 +1729,9 @@ FROZEN_FILES_IN = \ Lib/zipimport.py \ Lib/abc.py \ Lib/codecs.py \ + Lib/encodings/__init__.py \ + Lib/encodings/aliases.py \ + Lib/encodings/utf_8.py \ Lib/io.py \ Lib/_collections_abc.py \ Lib/_sitebuiltins.py \ @@ -1738,6 +1741,7 @@ FROZEN_FILES_IN = \ Lib/os.py \ Lib/site.py \ Lib/stat.py \ + Lib/linecache.py \ Lib/importlib/util.py \ Lib/importlib/machinery.py \ Lib/runpy.py \ @@ -1754,6 +1758,9 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/zipimport.h \ Python/frozen_modules/abc.h \ Python/frozen_modules/codecs.h \ + Python/frozen_modules/encodings.h \ + Python/frozen_modules/encodings.aliases.h \ + Python/frozen_modules/encodings.utf_8.h \ Python/frozen_modules/io.h \ Python/frozen_modules/_collections_abc.h \ Python/frozen_modules/_sitebuiltins.h \ @@ -1763,6 +1770,7 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/os.h \ Python/frozen_modules/site.h \ Python/frozen_modules/stat.h \ + Python/frozen_modules/linecache.h \ Python/frozen_modules/importlib.util.h \ Python/frozen_modules/importlib.machinery.h \ Python/frozen_modules/runpy.h \ @@ -1802,6 +1810,15 @@ Python/frozen_modules/abc.h: Lib/abc.py $(FREEZE_MODULE_DEPS) Python/frozen_modules/codecs.h: Lib/codecs.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h +Python/frozen_modules/encodings.h: Lib/encodings/__init__.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) encodings $(srcdir)/Lib/encodings/__init__.py Python/frozen_modules/encodings.h + +Python/frozen_modules/encodings.aliases.h: Lib/encodings/aliases.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) encodings.aliases $(srcdir)/Lib/encodings/aliases.py Python/frozen_modules/encodings.aliases.h + +Python/frozen_modules/encodings.utf_8.h: Lib/encodings/utf_8.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) encodings.utf_8 $(srcdir)/Lib/encodings/utf_8.py Python/frozen_modules/encodings.utf_8.h + Python/frozen_modules/io.h: Lib/io.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) io $(srcdir)/Lib/io.py Python/frozen_modules/io.h @@ -1829,6 +1846,9 @@ Python/frozen_modules/site.h: Lib/site.py $(FREEZE_MODULE_DEPS) Python/frozen_modules/stat.h: Lib/stat.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h +Python/frozen_modules/linecache.h: Lib/linecache.py $(FREEZE_MODULE_DEPS) + $(FREEZE_MODULE) linecache $(srcdir)/Lib/linecache.py Python/frozen_modules/linecache.h + Python/frozen_modules/importlib.util.h: Lib/importlib/util.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) importlib.util $(srcdir)/Lib/importlib/util.py Python/frozen_modules/importlib.util.h diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst new file mode 100644 index 00000000000..6b6a9eb9813 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst @@ -0,0 +1,4 @@ +The :mod:`encodings` is now partially frozen, including +the ``aliases`` and ``utf_8`` submodules. + +The :mod:`linecache` is now frozen. diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index cb806459596..40946cafd16 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -310,6 +310,21 @@ $(IntDir)codecs.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\codecs.h + + encodings + $(IntDir)encodings.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.h + + + encodings.aliases + $(IntDir)encodings.aliases.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.aliases.h + + + encodings.utf_8 + $(IntDir)encodings.utf_8.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.utf_8.h + io $(IntDir)io.g.h @@ -355,6 +370,11 @@ $(IntDir)stat.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\stat.h + + linecache + $(IntDir)linecache.g.h + $(GeneratedFrozenModulesDir)Python\frozen_modules\linecache.h + importlib.util $(IntDir)importlib.util.g.h diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 6dcf0e87129..a0e36a4c526 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -537,6 +537,15 @@ Python Files + + Python Files + + + Python Files + + + Python Files + Python Files @@ -564,6 +573,9 @@ Python Files + + Python Files + Python Files diff --git a/Python/frozen.c b/Python/frozen.c index 15d256b6743..72a291d0d43 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -46,6 +46,9 @@ #include "frozen_modules/zipimport.h" #include "frozen_modules/abc.h" #include "frozen_modules/codecs.h" +#include "frozen_modules/encodings.h" +#include "frozen_modules/encodings.aliases.h" +#include "frozen_modules/encodings.utf_8.h" #include "frozen_modules/io.h" #include "frozen_modules/_collections_abc.h" #include "frozen_modules/_sitebuiltins.h" @@ -55,6 +58,7 @@ #include "frozen_modules/os.h" #include "frozen_modules/site.h" #include "frozen_modules/stat.h" +#include "frozen_modules/linecache.h" #include "frozen_modules/importlib.util.h" #include "frozen_modules/importlib.machinery.h" #include "frozen_modules/runpy.h" @@ -76,6 +80,9 @@ static const struct _frozen stdlib_modules[] = { /* stdlib - startup, without site (python -S) */ {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false}, {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false}, + {"encodings", _Py_M__encodings, (int)sizeof(_Py_M__encodings), true}, + {"encodings.aliases", _Py_M__encodings_aliases, (int)sizeof(_Py_M__encodings_aliases), false}, + {"encodings.utf_8", _Py_M__encodings_utf_8, (int)sizeof(_Py_M__encodings_utf_8), false}, {"io", _Py_M__io, (int)sizeof(_Py_M__io), false}, /* stdlib - startup, with site */ @@ -88,6 +95,9 @@ static const struct _frozen stdlib_modules[] = { {"site", _Py_M__site, (int)sizeof(_Py_M__site), false}, {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false}, + /* pythonrun - interactive */ + {"linecache", _Py_M__linecache, (int)sizeof(_Py_M__linecache), false}, + /* runpy - run module with -m */ {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false}, {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false}, diff --git a/Tools/build/freeze_modules.py b/Tools/build/freeze_modules.py index 3c43f7e3bbe..0d1f5968d2a 100644 --- a/Tools/build/freeze_modules.py +++ b/Tools/build/freeze_modules.py @@ -50,10 +50,9 @@ ('stdlib - startup, without site (python -S)', [ 'abc', 'codecs', - # For now we do not freeze the encodings, due # to the noise all - # those extra modules add to the text printed during the build. - # (See https://github.com/python/cpython/pull/28398#pullrequestreview-756856469.) - #'', + '', + 'encodings.aliases', + 'encodings.utf_8', 'io', ]), ('stdlib - startup, with site', [ @@ -66,6 +65,9 @@ 'site', 'stat', ]), + ('pythonrun - interactive', [ + 'linecache', + ]), ('runpy - run module with -m', [ "importlib.util", "importlib.machinery", From 44855458a423569eaea3df53fd5a0c0032da932d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 9 Mar 2026 14:32:28 +0100 Subject: [PATCH 037/775] Document that PyType_GetModule returns a borrowed ref (GH-145612) --- Doc/c-api/type.rst | 4 ++++ Doc/data/refcounts.dat | 3 +++ 2 files changed, 7 insertions(+) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 8cadf26cee3..c9bb5c3f09a 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -274,6 +274,10 @@ Type Objects Return the module object associated with the given type when the type was created using :c:func:`PyType_FromModuleAndSpec`. + The returned reference is :term:`borrowed ` from *type*, + and will be valid as long as you hold a reference to *type*. + Do not release it with :c:func:`Py_DECREF` or similar. + If no module is associated with the given type, sets :py:class:`TypeError` and returns ``NULL``. diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 64399f6ab1f..01b064f3e61 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2427,6 +2427,9 @@ PyType_GetFlags:PyTypeObject*:type:0: PyType_GetName:PyObject*::+1: PyType_GetName:PyTypeObject*:type:0: +PyType_GetModule:PyObject*::0: +PyType_GetModule:PyTypeObject*:type:0: + PyType_GetModuleByToken:PyObject*::+1: PyType_GetModuleByToken:PyTypeObject*:type:0: PyType_GetModuleByToken:PyModuleDef*:def:: From 39aa415296c9ebb488eaf5952be00ef2d7ab306f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 9 Mar 2026 14:53:52 +0100 Subject: [PATCH 038/775] gh-145376: Fix _cursesmodule.c build on FreeBSD/macOS (#145669) --- Modules/_cursesmodule.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index dd96f9aa62b..fe9d6fe2763 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1132,7 +1132,9 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, else #endif { +#ifdef HAVE_NCURSESW assert(wstr == NULL); +#endif const char *str = PyBytes_AS_STRING(bytesobj); if (use_xy) { rtn = mvwaddstr(self->win,y,x,str); From d64f83d07bf587dfd6e4ff9ad9d44541064d5f1c Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 9 Mar 2026 15:02:06 +0100 Subject: [PATCH 039/775] gh-78773: Improve ctypes dynamic library loading docs (GH-145313) --- Doc/library/ctypes.rst | 250 ++++++++++++++++++++++------------------- 1 file changed, 133 insertions(+), 117 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index c23e81e29df..fcbe2122d9f 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -20,10 +20,6 @@ used to wrap these libraries in pure Python. ctypes tutorial --------------- -Note: The code samples in this tutorial use :mod:`doctest` to make sure that -they actually work. Since some code samples behave differently under Linux, -Windows, or macOS, they contain doctest directives in comments. - Note: Some code samples reference the ctypes :class:`c_int` type. On platforms where ``sizeof(long) == sizeof(int)`` it is an alias to :class:`c_long`. So, you should not be confused if :class:`c_long` is printed if you would expect @@ -34,13 +30,16 @@ So, you should not be confused if :class:`c_long` is printed if you would expect Loading dynamic link libraries ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:mod:`!ctypes` exports the *cdll*, and on Windows *windll* and *oledll* +:mod:`!ctypes` exports the :py:data:`~ctypes.cdll`, and on Windows +:py:data:`~ctypes.windll` and :py:data:`~ctypes.oledll` objects, for loading dynamic link libraries. -You load libraries by accessing them as attributes of these objects. *cdll* -loads libraries which export functions using the standard ``cdecl`` calling -convention, while *windll* libraries call functions using the ``stdcall`` -calling convention. *oledll* also uses the ``stdcall`` calling convention, and +You load libraries by accessing them as attributes of these objects. +:py:data:`!cdll` loads libraries which export functions using the +standard ``cdecl`` calling convention, while :py:data:`!windll` +libraries call functions using the ``stdcall`` +calling convention. +:py:data:`~oledll` also uses the ``stdcall`` calling convention, and assumes the functions return a Windows :c:type:`!HRESULT` error code. The error code is used to automatically raise an :class:`OSError` exception when the function call fails. @@ -70,11 +69,13 @@ Windows appends the usual ``.dll`` file suffix automatically. being used by Python. Where possible, use native Python functionality, or else import and use the ``msvcrt`` module. -On Linux, it is required to specify the filename *including* the extension to +Other systems require the filename *including* the extension to load a library, so attribute access can not be used to load libraries. Either the :meth:`~LibraryLoader.LoadLibrary` method of the dll loaders should be used, -or you should load the library by creating an instance of CDLL by calling -the constructor:: +or you should load the library by creating an instance of :py:class:`CDLL` +by calling the constructor. + +For example, on Linux:: >>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX @@ -83,7 +84,14 @@ the constructor:: >>> -.. XXX Add section for macOS. +On macOS:: + + >>> cdll.LoadLibrary("libc.dylib") # doctest: +MACOS + + >>> libc = CDLL("libc.dylib") # doctest: +MACOS + >>> libc # doctest: +MACOS + + .. _ctypes-accessing-functions-from-loaded-dlls: @@ -1456,14 +1464,82 @@ Loading shared libraries ^^^^^^^^^^^^^^^^^^^^^^^^ There are several ways to load shared libraries into the Python process. One -way is to instantiate one of the following classes: +way is to instantiate :py:class:`CDLL` or one of its subclasses: .. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) - Instances of this class represent loaded shared libraries. Functions in these - libraries use the standard C calling convention, and are assumed to return - :c:expr:`int`. + Represents a loaded shared library. + + Functions in this library use the standard C calling convention, and are + assumed to return :c:expr:`int`. + The Python :term:`global interpreter lock` is released before calling any + function exported by these libraries, and reacquired afterwards. + For different function behavior, use a subclass: :py:class:`~ctypes.OleDLL`, + :py:class:`~ctypes.WinDLL`, or :py:class:`~ctypes.PyDLL`. + + If you have an existing :py:attr:`handle ` to an already + loaded shared library, it can be passed as the *handle* argument to wrap + the opened library in a new :py:class:`!CDLL` object. + In this case, *name* is only used to set the :py:attr:`~ctypes.CDLL._name` + attribute, but it may be adjusted and/or validated. + + If *handle* is ``None``, the underlying platform's :manpage:`dlopen(3)` or + :c:func:`!LoadLibrary` function is used to load the library into + the process, and to get a handle to it. + + *name* is the pathname of the shared library to open. + If *name* does not contain a path separator, the library is found + in a platform-specific way. + + On non-Windows systems, *name* can be ``None``. In this case, + :c:func:`!dlopen` is called with ``NULL``, which opens the main program + as a "library". + (Some systems do the same is *name* is empty; ``None``/``NULL`` is more + portable.) + + .. admonition:: CPython implementation detail + + Since CPython is linked to ``libc``, a ``None`` *name* is often used + to access the C standard library:: + + >>> printf = ctypes.CDLL(None).printf + >>> printf.argtypes = [ctypes.c_char_p] + >>> printf(b"hello\n") + hello + 6 + + To access the Python C API, prefer :py:data:`ctypes.pythonapi` which + works across platforms. + + The *mode* parameter can be used to specify how the library is loaded. For + details, consult the :manpage:`dlopen(3)` manpage. On Windows, *mode* is + ignored. On posix systems, RTLD_NOW is always added, and is not + configurable. + + The *use_errno* parameter, when set to true, enables a ctypes mechanism that + allows accessing the system :data:`errno` error number in a safe way. + :mod:`!ctypes` maintains a thread-local copy of the system's :data:`errno` + variable; if you call foreign functions created with ``use_errno=True`` then the + :data:`errno` value before the function call is swapped with the ctypes private + copy, the same happens immediately after the function call. + + The function :func:`ctypes.get_errno` returns the value of the ctypes private + copy, and the function :func:`ctypes.set_errno` changes the ctypes private copy + to a new value and returns the former value. + + The *use_last_error* parameter, when set to true, enables the same mechanism for + the Windows error code which is managed by the :func:`GetLastError` and + :func:`!SetLastError` Windows API functions; :func:`ctypes.get_last_error` and + :func:`ctypes.set_last_error` are used to request and change the ctypes private + copy of the windows error code. + + The *winmode* parameter is used on Windows to specify how the library is loaded + (since *mode* is ignored). It takes any value that is valid for the Win32 API + ``LoadLibraryEx`` flags parameter. When omitted, the default is to use the + flags that result in the most secure DLL load, which avoids issues such as DLL + hijacking. Passing the full path to the DLL is the safest way to ensure the + correct library and dependencies are loaded. On Windows creating a :class:`CDLL` instance may fail even if the DLL name exists. When a dependent DLL of the loaded DLL is not found, a @@ -1475,20 +1551,47 @@ way is to instantiate one of the following classes: DLLs and determine which one is not found using Windows debugging and tracing tools. + .. seealso:: + + `Microsoft DUMPBIN tool `_ + -- A tool to find DLL dependents. + + .. versionchanged:: 3.8 + Added *winmode* parameter. + .. versionchanged:: 3.12 The *name* parameter can now be a :term:`path-like object`. -.. seealso:: + Instances of this class have no public methods. Functions exported by the + shared library can be accessed as attributes or by index. Please note that + accessing the function through an attribute caches the result and therefore + accessing it repeatedly returns the same object each time. On the other hand, + accessing it through an index returns a new object each time:: - `Microsoft DUMPBIN tool `_ - -- A tool to find DLL dependents. + >>> from ctypes import CDLL + >>> libc = CDLL("libc.so.6") # On Linux + >>> libc.time == libc.time + True + >>> libc['time'] == libc['time'] + False + The following public attributes are available. Their name starts with an + underscore to not clash with exported function names: -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) + .. attribute:: _handle - Instances of this class represent loaded shared libraries, - functions in these libraries use the ``stdcall`` calling convention, and are + The system handle used to access the library. + + .. attribute:: _name + + The name of the library passed in the constructor. + +.. class:: OleDLL + + See :py:class:`~ctypes.CDLL`, the superclass, for common information. + + Functions in this library use the ``stdcall`` calling convention, and are assumed to return the windows specific :class:`HRESULT` code. :class:`HRESULT` values contain information specifying whether the function call failed or succeeded, together with additional error code. If the return value signals a @@ -1500,133 +1603,51 @@ way is to instantiate one of the following classes: :exc:`WindowsError` used to be raised, which is now an alias of :exc:`OSError`. - .. versionchanged:: 3.12 - The *name* parameter can now be a :term:`path-like object`. +.. class:: WinDLL + See :py:class:`~ctypes.CDLL`, the superclass, for common information. -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) - - Instances of this class represent loaded shared libraries, - functions in these libraries use the ``stdcall`` calling convention, and are + Functions in these libraries use the ``stdcall`` calling convention, and are assumed to return :c:expr:`int` by default. .. availability:: Windows - .. versionchanged:: 3.12 +.. class:: PyDLL - The *name* parameter can now be a :term:`path-like object`. + See :py:class:`~ctypes.CDLL`, the superclass, for common information. - -The Python :term:`global interpreter lock` is released before calling any -function exported by these libraries, and reacquired afterwards. - - -.. class:: PyDLL(name, mode=DEFAULT_MODE, handle=None) - - Instances of this class behave like :class:`CDLL` instances, except that the + When functions in this library are called, the Python GIL is *not* released during the function call, and after the function execution the Python error flag is checked. If the error flag is set, a Python exception is raised. - Thus, this is only useful to call Python C api functions directly. - - .. versionchanged:: 3.12 - - The *name* parameter can now be a :term:`path-like object`. - -All these classes can be instantiated by calling them with at least one -argument, the pathname of the shared library. If you have an existing handle to -an already loaded shared library, it can be passed as the ``handle`` named -parameter, otherwise the underlying platform's :c:func:`!dlopen` or -:c:func:`!LoadLibrary` function is used to load the library into -the process, and to get a handle to it. - -The *mode* parameter can be used to specify how the library is loaded. For -details, consult the :manpage:`dlopen(3)` manpage. On Windows, *mode* is -ignored. On posix systems, RTLD_NOW is always added, and is not -configurable. - -The *use_errno* parameter, when set to true, enables a ctypes mechanism that -allows accessing the system :data:`errno` error number in a safe way. -:mod:`!ctypes` maintains a thread-local copy of the system's :data:`errno` -variable; if you call foreign functions created with ``use_errno=True`` then the -:data:`errno` value before the function call is swapped with the ctypes private -copy, the same happens immediately after the function call. - -The function :func:`ctypes.get_errno` returns the value of the ctypes private -copy, and the function :func:`ctypes.set_errno` changes the ctypes private copy -to a new value and returns the former value. - -The *use_last_error* parameter, when set to true, enables the same mechanism for -the Windows error code which is managed by the :func:`GetLastError` and -:func:`!SetLastError` Windows API functions; :func:`ctypes.get_last_error` and -:func:`ctypes.set_last_error` are used to request and change the ctypes private -copy of the windows error code. - -The *winmode* parameter is used on Windows to specify how the library is loaded -(since *mode* is ignored). It takes any value that is valid for the Win32 API -``LoadLibraryEx`` flags parameter. When omitted, the default is to use the -flags that result in the most secure DLL load, which avoids issues such as DLL -hijacking. Passing the full path to the DLL is the safest way to ensure the -correct library and dependencies are loaded. - -.. versionchanged:: 3.8 - Added *winmode* parameter. + Thus, this is only useful to call Python C API functions directly. .. data:: RTLD_GLOBAL - :noindex: Flag to use as *mode* parameter. On platforms where this flag is not available, it is defined as the integer zero. .. data:: RTLD_LOCAL - :noindex: Flag to use as *mode* parameter. On platforms where this is not available, it is the same as *RTLD_GLOBAL*. .. data:: DEFAULT_MODE - :noindex: The default mode which is used to load shared libraries. On OSX 10.3, this is *RTLD_GLOBAL*, otherwise it is the same as *RTLD_LOCAL*. -Instances of these classes have no public methods. Functions exported by the -shared library can be accessed as attributes or by index. Please note that -accessing the function through an attribute caches the result and therefore -accessing it repeatedly returns the same object each time. On the other hand, -accessing it through an index returns a new object each time:: - - >>> from ctypes import CDLL - >>> libc = CDLL("libc.so.6") # On Linux - >>> libc.time == libc.time - True - >>> libc['time'] == libc['time'] - False - -The following public attributes are available, their name starts with an -underscore to not clash with exported function names: - - -.. attribute:: PyDLL._handle - - The system handle used to access the library. - - -.. attribute:: PyDLL._name - - The name of the library passed in the constructor. Shared libraries can also be loaded by using one of the prefabricated objects, which are instances of the :class:`LibraryLoader` class, either by calling the :meth:`~LibraryLoader.LoadLibrary` method, or by retrieving the library as attribute of the loader instance. - .. class:: LibraryLoader(dlltype) Class which loads shared libraries. *dlltype* should be one of the @@ -1645,13 +1666,11 @@ attribute of the loader instance. These prefabricated library loaders are available: .. data:: cdll - :noindex: Creates :class:`CDLL` instances. .. data:: windll - :noindex: Creates :class:`WinDLL` instances. @@ -1659,7 +1678,6 @@ These prefabricated library loaders are available: .. data:: oledll - :noindex: Creates :class:`OleDLL` instances. @@ -1667,7 +1685,6 @@ These prefabricated library loaders are available: .. data:: pydll - :noindex: Creates :class:`PyDLL` instances. @@ -1676,7 +1693,6 @@ For accessing the C Python api directly, a ready-to-use Python shared library object is available: .. data:: pythonapi - :noindex: An instance of :class:`PyDLL` that exposes Python C API functions as attributes. Note that all these functions are assumed to return C From 1564e231aae7afad5b9b19a277d1efff2b840ad2 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Mon, 9 Mar 2026 15:07:23 +0100 Subject: [PATCH 040/775] gh-145541: Fix `InvalidStateError` in `BaseSubprocessTransport._call_connection_lost()` (#145554) --- Lib/asyncio/base_subprocess.py | 4 +-- Lib/test/test_asyncio/test_subprocess.py | 31 +++++++++++++++++++ ...-03-05-19-01-28.gh-issue-145551.gItPRl.rst | 1 + 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 321a4e5d5d1..224b1883808 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -265,7 +265,7 @@ def _try_finish(self): # to avoid hanging forever in self._wait as otherwise _exit_waiters # would never be woken up, we wake them up here. for waiter in self._exit_waiters: - if not waiter.cancelled(): + if not waiter.done(): waiter.set_result(self._returncode) if all(p is not None and p.disconnected for p in self._pipes.values()): @@ -278,7 +278,7 @@ def _call_connection_lost(self, exc): finally: # wake up futures waiting for wait() for waiter in self._exit_waiters: - if not waiter.cancelled(): + if not waiter.done(): waiter.set_result(self._returncode) self._exit_waiters = None self._loop = None diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index bf301740741..c08eb7cf261 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -111,6 +111,37 @@ def test_subprocess_repr(self): ) transport.close() + def test_proc_exited_no_invalid_state_error_on_exit_waiters(self): + # gh-145541: when _connect_pipes hasn't completed (so + # _pipes_connected is False) and the process exits, _try_finish() + # sets the result on exit waiters. Then _call_connection_lost() must + # not call set_result() again on the same waiters. + self.loop.set_exception_handler( + lambda loop, context: self.fail( + f"unexpected exception: {context}") + ) + waiter = self.loop.create_future() + transport, protocol = self.create_transport(waiter) + + # Simulate a waiter registered via _wait() before the process exits. + exit_waiter = self.loop.create_future() + transport._exit_waiters.append(exit_waiter) + + # _connect_pipes hasn't completed, so _pipes_connected is False. + self.assertFalse(transport._pipes_connected) + + # Simulate process exit. _try_finish() will set the result on + # exit_waiter because _pipes_connected is False, and then schedule + # _call_connection_lost() because _pipes is empty (vacuously all + # disconnected). _call_connection_lost() must skip exit_waiter + # because it's already done. + transport._process_exited(6) + self.loop.run_until_complete(waiter) + + self.assertEqual(exit_waiter.result(), 6) + + transport.close() + class SubprocessMixin: diff --git a/Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst b/Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst new file mode 100644 index 00000000000..15b70d734ca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst @@ -0,0 +1 @@ +Fix InvalidStateError when cancelling process created by :func:`asyncio.create_subprocess_exec` or :func:`asyncio.create_subprocess_shell`. Patch by Daan De Meyer. From 0dfe649400a0b67318169ec813475f4949ad7b69 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 9 Mar 2026 15:47:02 +0100 Subject: [PATCH 041/775] gh-141510: Optimize frozendict(frozendict) (#145592) Return the same object unmodified if it's exactly the frozendict type. Optimize also PyFrozenDict_New(frozendict). --- Lib/test/test_capi/test_dict.py | 10 +++++++ Lib/test/test_dict.py | 7 +++++ Objects/dictobject.c | 53 ++++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py index 5bdf74ef73a..cd46fea5476 100644 --- a/Lib/test/test_capi/test_dict.py +++ b/Lib/test/test_capi/test_dict.py @@ -619,6 +619,16 @@ def test_frozendict_new(self): self.assertEqual(dct, frozendict(x=1, y=2)) self.assertIs(type(dct), frozendict) + # PyFrozenDict_New(frozendict) returns the same object unmodified + fd = frozendict(a=1, b=2, c=3) + fd2 = frozendict_new(fd) + self.assertIs(fd2, fd) + + fd = FrozenDictSubclass(a=1, b=2, c=3) + fd2 = frozendict_new(fd) + self.assertIsNot(fd2, fd) + self.assertEqual(fd2, fd) + # PyFrozenDict_New(NULL) creates an empty dictionary dct = frozendict_new(NULL) self.assertEqual(dct, frozendict()) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 45448d1264a..b2f4363b23e 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1829,6 +1829,13 @@ def test_constructor(self): with self.assertRaises(TypeError): dict.__init__(d, x=1) + # Avoid copy if it's frozendict type + d2 = frozendict(d) + self.assertIs(d2, d) + d2 = FrozenDict(d) + self.assertIsNot(d2, d) + self.assertEqual(d2, d) + def test_copy(self): d = frozendict(x=1, y=2) d2 = d.copy() diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 61fde37f8d4..b5f2a682c54 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -5169,15 +5169,47 @@ dict_vectorcall(PyObject *type, PyObject * const*args, return NULL; } - PyObject *self; - if (Py_Is((PyTypeObject*)type, &PyFrozenDict_Type) - || PyType_IsSubtype((PyTypeObject*)type, &PyFrozenDict_Type)) + PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL); + if (self == NULL) { + return NULL; + } + if (nargs == 1) { + if (dict_update_arg(self, args[0]) < 0) { + Py_DECREF(self); + return NULL; + } + args++; + } + if (kwnames != NULL) { + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) { + PyObject *key = PyTuple_GET_ITEM(kwnames, i); // borrowed + if (PyDict_SetItem(self, key, args[i]) < 0) { + Py_DECREF(self); + return NULL; + } + } + } + return self; +} + +static PyObject * +frozendict_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) +{ + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (!_PyArg_CheckPositional("frozendict", nargs, 0, 1)) { + return NULL; + } + + if (nargs == 1 && kwnames == NULL + && PyFrozenDict_CheckExact(args[0]) + && Py_Is((PyTypeObject*)type, &PyFrozenDict_Type)) { - self = frozendict_new(_PyType_CAST(type), NULL, NULL); - } - else { - self = dict_new(_PyType_CAST(type), NULL, NULL); + // frozendict(frozendict) returns the same object unmodified + return Py_NewRef(args[0]); } + + PyObject *self = frozendict_new(_PyType_CAST(type), NULL, NULL); if (self == NULL) { return NULL; } @@ -8171,6 +8203,11 @@ PyObject* PyFrozenDict_New(PyObject *iterable) { if (iterable != NULL) { + if (PyFrozenDict_CheckExact(iterable)) { + // PyFrozenDict_New(frozendict) returns the same object unmodified + return Py_NewRef(iterable); + } + PyObject *args = PyTuple_Pack(1, iterable); if (args == NULL) { return NULL; @@ -8228,6 +8265,6 @@ PyTypeObject PyFrozenDict_Type = { .tp_alloc = _PyType_AllocNoTrack, .tp_new = frozendict_new, .tp_free = PyObject_GC_Del, - .tp_vectorcall = dict_vectorcall, + .tp_vectorcall = frozendict_vectorcall, .tp_version_tag = _Py_TYPE_VERSION_FROZENDICT, }; From 27c49707dfd13752791aacd33a3ecfbe780beca2 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 9 Mar 2026 15:21:33 +0000 Subject: [PATCH 042/775] GH-144688: Fix refleaks in JIT when optimization fails (GH-145420) --- Python/optimizer.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Python/optimizer.c b/Python/optimizer.c index f485c27bca2..4387bcb0d67 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1076,12 +1076,19 @@ _PyJit_FinalizeTracing(PyThreadState *tstate, int err) exit->temperature = initial_temperature_backoff_counter(&tstate->interp->opt_config); } } + // Clear all recorded values + _PyJitUopBuffer *buffer = &tracer->code_buffer; + for (_PyUOpInstruction *inst = buffer->start; inst < buffer->next; inst++) { + if (_PyUop_Flags[inst->opcode] & HAS_RECORDS_VALUE_FLAG) { + Py_XDECREF((PyObject *)(uintptr_t)inst->operand0); + } + } Py_CLEAR(tracer->initial_state.code); Py_CLEAR(tracer->initial_state.func); Py_CLEAR(tracer->initial_state.executor); Py_CLEAR(tracer->prev_state.instr_code); Py_CLEAR(tracer->prev_state.recorded_value); - uop_buffer_init(&tracer->code_buffer, &tracer->uop_array[0], UOP_MAX_TRACE_LENGTH); + uop_buffer_init(buffer, &tracer->uop_array[0], UOP_MAX_TRACE_LENGTH); tracer->is_tracing = false; } @@ -1521,6 +1528,11 @@ uop_optimize( } assert(_PyOpcode_uop_name[buffer[pc].opcode]); } + // We've cleaned up the references in the buffer, so discard the code buffer + // to avoid doing it again during tracer cleanup + _PyJitUopBuffer *code_buffer = &_tstate->jit_tracer_state->code_buffer; + code_buffer->next = code_buffer->start; + OPT_HIST(effective_trace_length(buffer, length), optimized_trace_length_hist); _PyUOpInstruction *output = &_tstate->jit_tracer_state->uop_array[0]; length = stack_allocate(buffer, output, length); From fc03cdccc0e88fe60f1ea6d659da1f3764379520 Mon Sep 17 00:00:00 2001 From: Maciej Olko Date: Mon, 9 Mar 2026 12:19:02 -0400 Subject: [PATCH 043/775] gh-139588: Docs: fix PDF build (#145480) --- Doc/Makefile | 7 ++++++- Doc/conf.py | 1 + Doc/library/profiling.sampling.rst | 20 ++++++++++++-------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Doc/Makefile b/Doc/Makefile index 5b7fdf8ec08..7bdabd8bf16 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -88,6 +88,7 @@ htmlhelp: build "build/htmlhelp/pydoc.hhp project file." .PHONY: latex +latex: _ensure-sphinxcontrib-svg2pdfconverter latex: BUILDER = latex latex: build @echo "Build finished; the LaTeX files are in build/latex." @@ -231,7 +232,7 @@ dist-text: @echo "Build finished and archived!" .PHONY: dist-pdf -dist-pdf: +dist-pdf: _ensure-sphinxcontrib-svg2pdfconverter # archive the A4 latex @echo "Building LaTeX (A4 paper)..." mkdir -p dist @@ -292,6 +293,10 @@ _ensure-pre-commit: _ensure-sphinx-autobuild: $(MAKE) _ensure-package PACKAGE=sphinx-autobuild +.PHONY: _ensure-sphinxcontrib-svg2pdfconverter +_ensure-sphinxcontrib-svg2pdfconverter: + $(MAKE) _ensure-package PACKAGE=sphinxcontrib-svg2pdfconverter + .PHONY: check check: _ensure-pre-commit $(VENVDIR)/bin/python3 -m pre_commit run --all-files diff --git a/Doc/conf.py b/Doc/conf.py index 545049bb460..26497083d28 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -46,6 +46,7 @@ 'linklint.ext', 'notfound.extension', 'sphinxext.opengraph', + 'sphinxcontrib.rsvgconverter', ) for optional_ext in _OPTIONAL_EXTENSIONS: try: diff --git a/Doc/library/profiling.sampling.rst b/Doc/library/profiling.sampling.rst index 078062c08c6..d2b7d9669ab 100644 --- a/Doc/library/profiling.sampling.rst +++ b/Doc/library/profiling.sampling.rst @@ -1194,10 +1194,12 @@ data, similar to the ``top`` command for system processes:: python -m profiling.sampling run --live script.py python -m profiling.sampling attach --live 12345 -.. figure:: tachyon-live-mode-2.gif - :alt: Tachyon live mode showing all threads - :align: center - :width: 100% +.. only:: not latex + + .. figure:: tachyon-live-mode-2.gif + :alt: Tachyon live mode showing all threads + :align: center + :width: 100% Live mode displays real-time profiling statistics, showing combined data from multiple threads in a multi-threaded application. @@ -1217,10 +1219,12 @@ main table, showing instruction-level statistics for the currently selected function. This panel displays which bytecode instructions are executing most frequently, including specialized variants and their base opcodes. -.. figure:: tachyon-live-mode-1.gif - :alt: Tachyon live mode with opcode panel - :align: center - :width: 100% +.. only:: not latex + + .. figure:: tachyon-live-mode-1.gif + :alt: Tachyon live mode with opcode panel + :align: center + :width: 100% Live mode with ``--opcodes`` enabled shows an opcode panel with a bytecode instruction breakdown for the selected function. From 171133aa84cd2fa8738bdbb0c76435645810e8d3 Mon Sep 17 00:00:00 2001 From: Yashraj Date: Mon, 9 Mar 2026 22:00:00 +0530 Subject: [PATCH 044/775] gh-141617: clarify `concurrent.futures.ThreadPoolExecutor` deadlock example (#141620) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --------- Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/library/concurrent.futures.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 3ea24ea7700..a32c3828313 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -156,7 +156,9 @@ And:: print(f.result()) executor = ThreadPoolExecutor(max_workers=1) - executor.submit(wait_on_future) + future = executor.submit(wait_on_future) + # Note: calling future.result() would also cause a deadlock because + # the single worker thread is already waiting for wait_on_future(). .. class:: ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=()) From d76df75f51e662fd15ebe00e107058841de94860 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Mon, 9 Mar 2026 13:24:34 -0400 Subject: [PATCH 045/775] gh-145615: Fix mimalloc page leak in the free-threaded build (gh-145626) Fix three issues that caused mimalloc pages to be leaked until the owning thread exited: 1. In _PyMem_mi_page_maybe_free(), move pages out of the full queue when relying on QSBR to defer freeing the page. Pages in the full queue are never searched by mi_page_queue_find_free_ex(), so a page left there is unusable for allocations. 2. Move _PyMem_mi_page_clear_qsbr() from _mi_page_free_collect() to _mi_page_thread_free_collect() where it only fires when all blocks on the page are free (used == 0). The previous placement was too broad: it cleared QSBR state whenever local_free was non-NULL, but _mi_page_free_collect() is called from non-allocation paths (e.g., page visiting in mi_heap_visit_blocks) where the page is not being reused. 3. In _PyMem_mi_page_maybe_free(), use the page's heap tld to find the correct thread state for QSBR list insertion instead of PyThreadState_GET(). During stop-the-world pauses, the function may process pages belonging to other threads, so the current thread state is not necessarily the owner of the page. --- ...3-06-21-05-05.gh-issue-145615.NKXXZgDW.rst | 2 ++ Objects/mimalloc/heap.c | 5 ++- Objects/mimalloc/page.c | 10 ++++-- Objects/mimalloc/segment.c | 2 ++ Objects/obmalloc.c | 31 +++++++++++++++---- 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst new file mode 100644 index 00000000000..2183eef618d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst @@ -0,0 +1,2 @@ +Fixed a memory leak in the :term:`free-threaded build` where mimalloc pages +could become permanently unreclaimable until the owning thread exited. diff --git a/Objects/mimalloc/heap.c b/Objects/mimalloc/heap.c index d92dc768e5e..5fbfb82baa0 100644 --- a/Objects/mimalloc/heap.c +++ b/Objects/mimalloc/heap.c @@ -100,7 +100,10 @@ static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t // note: this will free retired pages as well. bool freed = _PyMem_mi_page_maybe_free(page, pq, collect >= MI_FORCE); if (!freed && collect == MI_ABANDON) { - _mi_page_abandon(page, pq); + // _PyMem_mi_page_maybe_free may have moved the page to a different + // page queue, so we need to re-fetch the correct queue. + uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size)); + _mi_page_abandon(page, &heap->pages[bin]); } } else if (collect == MI_ABANDON) { diff --git a/Objects/mimalloc/page.c b/Objects/mimalloc/page.c index ff7444cce10..ded59f8eb1c 100644 --- a/Objects/mimalloc/page.c +++ b/Objects/mimalloc/page.c @@ -213,6 +213,13 @@ static void _mi_page_thread_free_collect(mi_page_t* page) // update counts now page->used -= count; + + if (page->used == 0) { + // The page may have had a QSBR goal set from a previous point when it + // was all-free. That goal is no longer valid because the page was + // allocated from and then freed again by other threads. + _PyMem_mi_page_clear_qsbr(page); + } } void _mi_page_free_collect(mi_page_t* page, bool force) { @@ -225,9 +232,6 @@ void _mi_page_free_collect(mi_page_t* page, bool force) { // and the local free list if (page->local_free != NULL) { - // any previous QSBR goals are no longer valid because we reused the page - _PyMem_mi_page_clear_qsbr(page); - if mi_likely(page->free == NULL) { // usual case page->free = page->local_free; diff --git a/Objects/mimalloc/segment.c b/Objects/mimalloc/segment.c index 9b092b9b734..9dad69c995e 100644 --- a/Objects/mimalloc/segment.c +++ b/Objects/mimalloc/segment.c @@ -1286,6 +1286,7 @@ static bool mi_segment_check_free(mi_segment_t* segment, size_t slices_needed, s _mi_stat_decrease(&tld->stats->pages_abandoned, 1); #ifdef Py_GIL_DISABLED page->qsbr_goal = 0; + mi_assert_internal(page->qsbr_node.next == NULL); #endif segment->abandoned--; slice = mi_segment_page_clear(page, tld); // re-assign slice due to coalesce! @@ -1361,6 +1362,7 @@ static mi_segment_t* mi_segment_reclaim(mi_segment_t* segment, mi_heap_t* heap, // if everything free by now, free the page #ifdef Py_GIL_DISABLED page->qsbr_goal = 0; + mi_assert_internal(page->qsbr_node.next == NULL); #endif slice = mi_segment_page_clear(page, tld); // set slice again due to coalesceing } diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index b59ebdfbda3..983bdddbf02 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -151,6 +151,12 @@ should_advance_qsbr_for_page(struct _qsbr_thread_state *qsbr, mi_page_t *page) } return false; } + +static _PyThreadStateImpl * +tstate_from_heap(mi_heap_t *heap) +{ + return _Py_CONTAINER_OF(heap->tld, _PyThreadStateImpl, mimalloc.tld); +} #endif static bool @@ -159,23 +165,35 @@ _PyMem_mi_page_maybe_free(mi_page_t *page, mi_page_queue_t *pq, bool force) #ifdef Py_GIL_DISABLED assert(mi_page_all_free(page)); if (page->use_qsbr) { - _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)PyThreadState_GET(); - if (page->qsbr_goal != 0 && _Py_qbsr_goal_reached(tstate->qsbr, page->qsbr_goal)) { + struct _qsbr_thread_state *qsbr = ((_PyThreadStateImpl *)PyThreadState_GET())->qsbr; + if (page->qsbr_goal != 0 && _Py_qbsr_goal_reached(qsbr, page->qsbr_goal)) { _PyMem_mi_page_clear_qsbr(page); _mi_page_free(page, pq, force); return true; } + // gh-145615: since we are not freeing this page yet, we want to + // make it available for allocations. Note that the QSBR goal and + // linked list node remain set even if the page is later used for + // an allocation. We only detect and clear the QSBR goal when the + // page becomes empty again (used == 0). + if (mi_page_is_in_full(page)) { + _mi_page_unfull(page); + } + _PyMem_mi_page_clear_qsbr(page); page->retire_expire = 0; - if (should_advance_qsbr_for_page(tstate->qsbr, page)) { - page->qsbr_goal = _Py_qsbr_advance(tstate->qsbr->shared); + if (should_advance_qsbr_for_page(qsbr, page)) { + page->qsbr_goal = _Py_qsbr_advance(qsbr->shared); } else { - page->qsbr_goal = _Py_qsbr_shared_next(tstate->qsbr->shared); + page->qsbr_goal = _Py_qsbr_shared_next(qsbr->shared); } + // We may be freeing a page belonging to a different thread during a + // stop-the-world event. Find the _PyThreadStateImpl for the page. + _PyThreadStateImpl *tstate = tstate_from_heap(mi_page_heap(page)); llist_insert_tail(&tstate->mimalloc.page_list, &page->qsbr_node); return false; } @@ -192,7 +210,8 @@ _PyMem_mi_page_reclaimed(mi_page_t *page) if (page->qsbr_goal != 0) { if (mi_page_all_free(page)) { assert(page->qsbr_node.next == NULL); - _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)PyThreadState_GET(); + _PyThreadStateImpl *tstate = tstate_from_heap(mi_page_heap(page)); + assert(tstate == (_PyThreadStateImpl *)_PyThreadState_GET()); page->retire_expire = 0; llist_insert_tail(&tstate->mimalloc.page_list, &page->qsbr_node); } From 255e79fa955ac5ffef9eb27087e8b1373e98e3bd Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:37:23 +0000 Subject: [PATCH 046/775] gh-143055: Fix crash in AST unparser when unparsing dict comprehension unpacking (#145556) --- Doc/conf.py | 1 + Lib/_ast_unparse.py | 10 +++++++--- Lib/test/test_future_stmt/test_future.py | 2 ++ Lib/test/test_unparse.py | 5 +++++ .../2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst | 2 ++ Python/ast_unparse.c | 12 +++++++++--- 6 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst diff --git a/Doc/conf.py b/Doc/conf.py index 26497083d28..6f66ed68c52 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -557,6 +557,7 @@ # mapping unique short aliases to a base URL and a prefix. # https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html extlinks = { + "oss-fuzz": ("https://issues.oss-fuzz.com/issues/%s", "#%s"), "pypi": ("https://pypi.org/project/%s/", "%s"), "source": (SOURCE_URI, "%s"), } diff --git a/Lib/_ast_unparse.py b/Lib/_ast_unparse.py index 0c3b1d3a910..916bb25d74d 100644 --- a/Lib/_ast_unparse.py +++ b/Lib/_ast_unparse.py @@ -738,9 +738,13 @@ def visit_SetComp(self, node): def visit_DictComp(self, node): with self.delimit("{", "}"): - self.traverse(node.key) - self.write(": ") - self.traverse(node.value) + if node.value: + self.traverse(node.key) + self.write(": ") + self.traverse(node.value) + else: + self.write("**") + self.traverse(node.key) for gen in node.generators: self.traverse(gen) diff --git a/Lib/test/test_future_stmt/test_future.py b/Lib/test/test_future_stmt/test_future.py index 71f1e616116..faa3a2bfe12 100644 --- a/Lib/test/test_future_stmt/test_future.py +++ b/Lib/test/test_future_stmt/test_future.py @@ -349,6 +349,8 @@ def test_annotations(self): eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") eq("{i: 0 for i in (1, 2, 3)}") eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("{**x for x in ()}") + eq("[*x for x in ()]") eq("[(x, y) for x, y in (a, b)]") eq("[(x,) for x, in (a,)]") eq("Python3 > Python2 > COBOL") diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index 35e4652a87b..dcaad49ffab 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -403,6 +403,11 @@ def test_set_comprehension(self): def test_dict_comprehension(self): self.check_ast_roundtrip("{x: x*x for x in range(10)}") + def test_dict_comprehension_unpacking(self): + self.check_ast_roundtrip("{**x for x in ()}") + self.check_ast_roundtrip("{**x for x in range(10)}") + self.check_ast_roundtrip("[*x for x in ()]") + def test_class_decorators(self): self.check_ast_roundtrip(class_decorator) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst new file mode 100644 index 00000000000..9b55459bffd --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst @@ -0,0 +1,2 @@ +Fix crash in AST unparser when unparsing dict comprehension unpacking. +Found by OSS Fuzz in :oss-fuzz:`489790200`. diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index c25699978cf..6050c351cff 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -464,9 +464,15 @@ static int append_ast_dictcomp(PyUnicodeWriter *writer, expr_ty e) { APPEND_CHAR('{'); - APPEND_EXPR(e->v.DictComp.key, PR_TEST); - APPEND_STR(": "); - APPEND_EXPR(e->v.DictComp.value, PR_TEST); + if (e->v.DictComp.value) { + APPEND_EXPR(e->v.DictComp.key, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR(e->v.DictComp.value, PR_TEST); + } + else { + APPEND_STR("**"); + APPEND_EXPR(e->v.DictComp.key, PR_TEST); + } APPEND(comprehensions, e->v.DictComp.generators); APPEND_CHAR_FINISH('}'); } From 07a39ca07e4cbacb2941d22c9901047df292059b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 9 Mar 2026 19:18:14 +0100 Subject: [PATCH 047/775] gh-145278: Revert "freeze encodings (partially) and linecache (#145279)" (#145689) --- Makefile.pre.in | 20 ------------------- ...-02-26-21-22-34.gh-issue-145278.DHkYqt.rst | 4 ---- PCbuild/_freeze_module.vcxproj | 20 ------------------- PCbuild/_freeze_module.vcxproj.filters | 12 ----------- Python/frozen.c | 10 ---------- Tools/build/freeze_modules.py | 10 ++++------ 6 files changed, 4 insertions(+), 72 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst diff --git a/Makefile.pre.in b/Makefile.pre.in index 4c2426ed283..120a6add385 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1729,9 +1729,6 @@ FROZEN_FILES_IN = \ Lib/zipimport.py \ Lib/abc.py \ Lib/codecs.py \ - Lib/encodings/__init__.py \ - Lib/encodings/aliases.py \ - Lib/encodings/utf_8.py \ Lib/io.py \ Lib/_collections_abc.py \ Lib/_sitebuiltins.py \ @@ -1741,7 +1738,6 @@ FROZEN_FILES_IN = \ Lib/os.py \ Lib/site.py \ Lib/stat.py \ - Lib/linecache.py \ Lib/importlib/util.py \ Lib/importlib/machinery.py \ Lib/runpy.py \ @@ -1758,9 +1754,6 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/zipimport.h \ Python/frozen_modules/abc.h \ Python/frozen_modules/codecs.h \ - Python/frozen_modules/encodings.h \ - Python/frozen_modules/encodings.aliases.h \ - Python/frozen_modules/encodings.utf_8.h \ Python/frozen_modules/io.h \ Python/frozen_modules/_collections_abc.h \ Python/frozen_modules/_sitebuiltins.h \ @@ -1770,7 +1763,6 @@ FROZEN_FILES_OUT = \ Python/frozen_modules/os.h \ Python/frozen_modules/site.h \ Python/frozen_modules/stat.h \ - Python/frozen_modules/linecache.h \ Python/frozen_modules/importlib.util.h \ Python/frozen_modules/importlib.machinery.h \ Python/frozen_modules/runpy.h \ @@ -1810,15 +1802,6 @@ Python/frozen_modules/abc.h: Lib/abc.py $(FREEZE_MODULE_DEPS) Python/frozen_modules/codecs.h: Lib/codecs.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h -Python/frozen_modules/encodings.h: Lib/encodings/__init__.py $(FREEZE_MODULE_DEPS) - $(FREEZE_MODULE) encodings $(srcdir)/Lib/encodings/__init__.py Python/frozen_modules/encodings.h - -Python/frozen_modules/encodings.aliases.h: Lib/encodings/aliases.py $(FREEZE_MODULE_DEPS) - $(FREEZE_MODULE) encodings.aliases $(srcdir)/Lib/encodings/aliases.py Python/frozen_modules/encodings.aliases.h - -Python/frozen_modules/encodings.utf_8.h: Lib/encodings/utf_8.py $(FREEZE_MODULE_DEPS) - $(FREEZE_MODULE) encodings.utf_8 $(srcdir)/Lib/encodings/utf_8.py Python/frozen_modules/encodings.utf_8.h - Python/frozen_modules/io.h: Lib/io.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) io $(srcdir)/Lib/io.py Python/frozen_modules/io.h @@ -1846,9 +1829,6 @@ Python/frozen_modules/site.h: Lib/site.py $(FREEZE_MODULE_DEPS) Python/frozen_modules/stat.h: Lib/stat.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h -Python/frozen_modules/linecache.h: Lib/linecache.py $(FREEZE_MODULE_DEPS) - $(FREEZE_MODULE) linecache $(srcdir)/Lib/linecache.py Python/frozen_modules/linecache.h - Python/frozen_modules/importlib.util.h: Lib/importlib/util.py $(FREEZE_MODULE_DEPS) $(FREEZE_MODULE) importlib.util $(srcdir)/Lib/importlib/util.py Python/frozen_modules/importlib.util.h diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst deleted file mode 100644 index 6b6a9eb9813..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-22-34.gh-issue-145278.DHkYqt.rst +++ /dev/null @@ -1,4 +0,0 @@ -The :mod:`encodings` is now partially frozen, including -the ``aliases`` and ``utf_8`` submodules. - -The :mod:`linecache` is now frozen. diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 40946cafd16..cb806459596 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -310,21 +310,6 @@ $(IntDir)codecs.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\codecs.h - - encodings - $(IntDir)encodings.g.h - $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.h - - - encodings.aliases - $(IntDir)encodings.aliases.g.h - $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.aliases.h - - - encodings.utf_8 - $(IntDir)encodings.utf_8.g.h - $(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.utf_8.h - io $(IntDir)io.g.h @@ -370,11 +355,6 @@ $(IntDir)stat.g.h $(GeneratedFrozenModulesDir)Python\frozen_modules\stat.h - - linecache - $(IntDir)linecache.g.h - $(GeneratedFrozenModulesDir)Python\frozen_modules\linecache.h - importlib.util $(IntDir)importlib.util.g.h diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index a0e36a4c526..6dcf0e87129 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -537,15 +537,6 @@ Python Files - - Python Files - - - Python Files - - - Python Files - Python Files @@ -573,9 +564,6 @@ Python Files - - Python Files - Python Files diff --git a/Python/frozen.c b/Python/frozen.c index 72a291d0d43..15d256b6743 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -46,9 +46,6 @@ #include "frozen_modules/zipimport.h" #include "frozen_modules/abc.h" #include "frozen_modules/codecs.h" -#include "frozen_modules/encodings.h" -#include "frozen_modules/encodings.aliases.h" -#include "frozen_modules/encodings.utf_8.h" #include "frozen_modules/io.h" #include "frozen_modules/_collections_abc.h" #include "frozen_modules/_sitebuiltins.h" @@ -58,7 +55,6 @@ #include "frozen_modules/os.h" #include "frozen_modules/site.h" #include "frozen_modules/stat.h" -#include "frozen_modules/linecache.h" #include "frozen_modules/importlib.util.h" #include "frozen_modules/importlib.machinery.h" #include "frozen_modules/runpy.h" @@ -80,9 +76,6 @@ static const struct _frozen stdlib_modules[] = { /* stdlib - startup, without site (python -S) */ {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false}, {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false}, - {"encodings", _Py_M__encodings, (int)sizeof(_Py_M__encodings), true}, - {"encodings.aliases", _Py_M__encodings_aliases, (int)sizeof(_Py_M__encodings_aliases), false}, - {"encodings.utf_8", _Py_M__encodings_utf_8, (int)sizeof(_Py_M__encodings_utf_8), false}, {"io", _Py_M__io, (int)sizeof(_Py_M__io), false}, /* stdlib - startup, with site */ @@ -95,9 +88,6 @@ static const struct _frozen stdlib_modules[] = { {"site", _Py_M__site, (int)sizeof(_Py_M__site), false}, {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false}, - /* pythonrun - interactive */ - {"linecache", _Py_M__linecache, (int)sizeof(_Py_M__linecache), false}, - /* runpy - run module with -m */ {"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false}, {"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false}, diff --git a/Tools/build/freeze_modules.py b/Tools/build/freeze_modules.py index 0d1f5968d2a..3c43f7e3bbe 100644 --- a/Tools/build/freeze_modules.py +++ b/Tools/build/freeze_modules.py @@ -50,9 +50,10 @@ ('stdlib - startup, without site (python -S)', [ 'abc', 'codecs', - '', - 'encodings.aliases', - 'encodings.utf_8', + # For now we do not freeze the encodings, due # to the noise all + # those extra modules add to the text printed during the build. + # (See https://github.com/python/cpython/pull/28398#pullrequestreview-756856469.) + #'', 'io', ]), ('stdlib - startup, with site', [ @@ -65,9 +66,6 @@ 'site', 'stat', ]), - ('pythonrun - interactive', [ - 'linecache', - ]), ('runpy - run module with -m', [ "importlib.util", "importlib.machinery", From f31ac36df6e9cddb4f498a7696e595f9f667c7b9 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:23:11 +0200 Subject: [PATCH 048/775] Docs: Update programming FAQ (#144573) Co-authored-by: Savannah Ostrowski Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Co-authored-by: Stan Ulbrych --- Doc/faq/programming.rst | 130 +++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 62 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 7a6f88d90a9..8bd2bc99d74 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -8,11 +8,11 @@ Programming FAQ .. contents:: -General Questions +General questions ================= -Is there a source code level debugger with breakpoints, single-stepping, etc.? ------------------------------------------------------------------------------- +Is there a source code-level debugger with breakpoints and single-stepping? +--------------------------------------------------------------------------- Yes. @@ -25,8 +25,7 @@ Reference Manual `. You can also write your own debugger by using the code for pdb as an example. The IDLE interactive development environment, which is part of the standard -Python distribution (normally available as -`Tools/scripts/idle3 `_), +Python distribution (normally available as :mod:`idlelib`), includes a graphical debugger. PythonWin is a Python IDE that includes a GUI debugger based on pdb. The @@ -48,7 +47,6 @@ There are a number of commercial Python IDEs that include graphical debuggers. They include: * `Wing IDE `_ -* `Komodo IDE `_ * `PyCharm `_ @@ -57,13 +55,15 @@ Are there tools to help find bugs or perform static analysis? Yes. -`Pylint `_ and -`Pyflakes `_ do basic checking that will +`Ruff `__, +`Pylint `__ and +`Pyflakes `__ do basic checking that will help you catch bugs sooner. -Static type checkers such as `Mypy `_, -`Pyre `_, and -`Pytype `_ can check type hints in Python +Static type checkers such as `mypy `__, +`ty `__, +`Pyrefly `__, and +`pytype `__ can check type hints in Python source code. @@ -79,7 +79,7 @@ set of modules required by a program and bind these modules together with a Python binary to produce a single executable. One is to use the freeze tool, which is included in the Python source tree as -`Tools/freeze `_. +:source:`Tools/freeze`. It converts Python byte code to C arrays; with a C compiler you can embed all your modules into a new program, which is then linked with the standard Python modules. @@ -103,6 +103,7 @@ executables: * `py2app `_ (macOS only) * `py2exe `_ (Windows only) + Are there coding standards or a style guide for Python programs? ---------------------------------------------------------------- @@ -110,7 +111,7 @@ Yes. The coding style required for standard library modules is documented as :pep:`8`. -Core Language +Core language ============= .. _faq-unboundlocalerror: @@ -143,7 +144,7 @@ results in an :exc:`!UnboundLocalError`: >>> foo() Traceback (most recent call last): ... - UnboundLocalError: local variable 'x' referenced before assignment + UnboundLocalError: cannot access local variable 'x' where it is not associated with a value This is because when you make an assignment to a variable in a scope, that variable becomes local to that scope and shadows any similarly named variable @@ -208,7 +209,7 @@ Why do lambdas defined in a loop with different values all return the same resul ---------------------------------------------------------------------------------- Assume you use a for loop to define a few different lambdas (or even plain -functions), e.g.:: +functions), for example:: >>> squares = [] >>> for x in range(5): @@ -227,7 +228,7 @@ they all return ``16``:: This happens because ``x`` is not local to the lambdas, but is defined in the outer scope, and it is accessed when the lambda is called --- not when it is defined. At the end of the loop, the value of ``x`` is ``4``, so all the -functions now return ``4**2``, i.e. ``16``. You can also verify this by +functions now return ``4**2``, that is ``16``. You can also verify this by changing the value of ``x`` and see how the results of the lambdas change:: >>> x = 8 @@ -298,9 +299,9 @@ using multiple imports per line uses less screen space. It's good practice if you import modules in the following order: -1. standard library modules -- e.g. :mod:`sys`, :mod:`os`, :mod:`argparse`, :mod:`re` +1. standard library modules -- such as :mod:`sys`, :mod:`os`, :mod:`argparse`, :mod:`re` 2. third-party library modules (anything installed in Python's site-packages - directory) -- e.g. :mod:`!dateutil`, :mod:`!requests`, :mod:`!PIL.Image` + directory) -- such as :pypi:`dateutil`, :pypi:`requests`, :pypi:`tzdata` 3. locally developed modules It is sometimes necessary to move imports to a function or class to avoid @@ -494,11 +495,11 @@ new objects). In other words: -* If we have a mutable object (:class:`list`, :class:`dict`, :class:`set`, - etc.), we can use some specific operations to mutate it and all the variables +* If we have a mutable object (such as :class:`list`, :class:`dict`, :class:`set`), + we can use some specific operations to mutate it and all the variables that refer to it will see the change. -* If we have an immutable object (:class:`str`, :class:`int`, :class:`tuple`, - etc.), all the variables that refer to it will always see the same value, +* If we have an immutable object (such as :class:`str`, :class:`int`, :class:`tuple`), + all the variables that refer to it will always see the same value, but operations that transform that value into a new value always return a new object. @@ -511,7 +512,7 @@ How do I write a function with output parameters (call by reference)? Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there's no alias between an argument name in -the caller and callee, and so no call-by-reference per se. You can achieve the +the caller and callee, and consequently no call-by-reference. You can achieve the desired effect in a number of ways. 1) By returning a tuple of the results:: @@ -714,8 +715,8 @@ not:: "a" in ("b", "a") -The same is true of the various assignment operators (``=``, ``+=`` etc). They -are not truly operators but syntactic delimiters in assignment statements. +The same is true of the various assignment operators (``=``, ``+=``, and so on). +They are not truly operators but syntactic delimiters in assignment statements. Is there an equivalent of C's "?:" ternary operator? @@ -868,9 +869,9 @@ with either a space or parentheses. How do I convert a string to a number? -------------------------------------- -For integers, use the built-in :func:`int` type constructor, e.g. ``int('144') +For integers, use the built-in :func:`int` type constructor, for example, ``int('144') == 144``. Similarly, :func:`float` converts to a floating-point number, -e.g. ``float('144') == 144.0``. +for example, ``float('144') == 144.0``. By default, these interpret the number as decimal, so that ``int('0144') == 144`` holds true, and ``int('0x144')`` raises :exc:`ValueError`. ``int(string, @@ -887,18 +888,18 @@ unwanted side effects. For example, someone could pass directory. :func:`eval` also has the effect of interpreting numbers as Python expressions, -so that e.g. ``eval('09')`` gives a syntax error because Python does not allow +so that, for example, ``eval('09')`` gives a syntax error because Python does not allow leading '0' in a decimal number (except '0'). How do I convert a number to a string? -------------------------------------- -To convert, e.g., the number ``144`` to the string ``'144'``, use the built-in type +For example, to convert the number ``144`` to the string ``'144'``, use the built-in type constructor :func:`str`. If you want a hexadecimal or octal representation, use the built-in functions :func:`hex` or :func:`oct`. For fancy formatting, see -the :ref:`f-strings` and :ref:`formatstrings` sections, -e.g. ``"{:04d}".format(144)`` yields +the :ref:`f-strings` and :ref:`formatstrings` sections. +For example, ``"{:04d}".format(144)`` yields ``'0144'`` and ``"{:.3f}".format(1.0/3.0)`` yields ``'0.333'``. @@ -908,7 +909,7 @@ How do I modify a string in place? You can't, because strings are immutable. In most situations, you should simply construct a new string from the various parts you want to assemble it from. However, if you need an object with the ability to modify in-place -unicode data, try using an :class:`io.StringIO` object or the :mod:`array` +Unicode data, try using an :class:`io.StringIO` object or the :mod:`array` module:: >>> import io @@ -1066,13 +1067,14 @@ the raw string:: Also see the specification in the :ref:`language reference `. + Performance =========== My program is too slow. How do I speed it up? --------------------------------------------- -That's a tough one, in general. First, here are a list of things to +That's a tough one, in general. First, here is list of things to remember before diving further: * Performance characteristics vary across Python implementations. This FAQ @@ -1125,6 +1127,7 @@ yourself. The wiki page devoted to `performance tips `_. + .. _efficient_string_concatenation: What is the most efficient way to concatenate many strings together? @@ -1143,7 +1146,7 @@ them into a list and call :meth:`str.join` at the end:: chunks.append(s) result = ''.join(chunks) -(another reasonably efficient idiom is to use :class:`io.StringIO`) +(Another reasonably efficient idiom is to use :class:`io.StringIO`.) To accumulate many :class:`bytes` objects, the recommended idiom is to extend a :class:`bytearray` object using in-place concatenation (the ``+=`` operator):: @@ -1153,7 +1156,7 @@ a :class:`bytearray` object using in-place concatenation (the ``+=`` operator):: result += b -Sequences (Tuples/Lists) +Sequences (tuples/lists) ======================== How do I convert between tuples and lists? @@ -1217,8 +1220,8 @@ list, deleting duplicates as you go:: else: last = mylist[i] -If all elements of the list may be used as set keys (i.e. they are all -:term:`hashable`) this is often faster :: +If all elements of the list may be used as set keys (that is, they are all +:term:`hashable`) this is often faster:: mylist = list(set(mylist)) @@ -1254,7 +1257,7 @@ difference is that a Python list can contain objects of many different types. The ``array`` module also provides methods for creating arrays of fixed types with compact representations, but they are slower to index than lists. Also note that `NumPy `_ -and other third party packages define array-like structures with +and other third-party packages define array-like structures with various characteristics as well. To get Lisp-style linked lists, you can emulate *cons cells* using tuples:: @@ -1324,7 +1327,7 @@ Or, you can use an extension that provides a matrix datatype; `NumPy How do I apply a method or function to a sequence of objects? ------------------------------------------------------------- -To call a method or function and accumulate the return values is a list, +To call a method or function and accumulate the return values in a list, a :term:`list comprehension` is an elegant solution:: result = [obj.method() for obj in mylist] @@ -1340,6 +1343,7 @@ a plain :keyword:`for` loop will suffice:: for obj in mylist: function(obj) + .. _faq-augmented-assignment-tuple-error: Why does a_tuple[i] += ['item'] raise an exception when the addition works? @@ -1444,7 +1448,7 @@ How can I sort one list by values from another list? ---------------------------------------------------- Merge them into an iterator of tuples, sort the resulting list, and then pick -out the element you want. :: +out the element you want. >>> list1 = ["what", "I'm", "sorting", "by"] >>> list2 = ["something", "else", "to", "sort"] @@ -1504,14 +1508,15 @@ How do I check if an object is an instance of a given class or of a subclass of Use the built-in function :func:`isinstance(obj, cls) `. You can check if an object is an instance of any of a number of classes by providing a tuple instead of a -single class, e.g. ``isinstance(obj, (class1, class2, ...))``, and can also -check whether an object is one of Python's built-in types, e.g. +single class, for example, ``isinstance(obj, (class1, class2, ...))``, and can also +check whether an object is one of Python's built-in types, for example, ``isinstance(obj, str)`` or ``isinstance(obj, (int, float, complex))``. Note that :func:`isinstance` also checks for virtual inheritance from an :term:`abstract base class`. So, the test will return ``True`` for a registered class even if hasn't directly or indirectly inherited from it. To -test for "true inheritance", scan the :term:`MRO` of the class: +test for "true inheritance", scan the :term:`method resolution order` (MRO) of +the class: .. testcode:: @@ -1574,7 +1579,7 @@ call it:: What is delegation? ------------------- -Delegation is an object oriented technique (also called a design pattern). +Delegation is an object-oriented technique (also called a design pattern). Let's say you have an object ``x`` and want to change the behaviour of just one of its methods. You can create a new class that provides a new implementation of the method you're interested in changing and delegates all other methods to @@ -1645,7 +1650,7 @@ How can I organize my code to make it easier to change the base class? You could assign the base class to an alias and derive from the alias. Then all you have to change is the value assigned to the alias. Incidentally, this trick -is also handy if you want to decide dynamically (e.g. depending on availability +is also handy if you want to decide dynamically (such as depending on availability of resources) which base class to use. Example:: class Base: @@ -1710,9 +1715,9 @@ How can I overload constructors (or methods) in Python? This answer actually applies to all methods, but the question usually comes up first in the context of constructors. -In C++ you'd write +In C++ you'd write: -.. code-block:: c +.. code-block:: c++ class C { C() { cout << "No arguments\n"; } @@ -1731,7 +1736,7 @@ default arguments. For example:: This is not entirely equivalent, but close enough in practice. -You could also try a variable-length argument list, e.g. :: +You could also try a variable-length argument list, for example:: def __init__(self, *args): ... @@ -1774,6 +1779,7 @@ to use private variable names at all. The :ref:`private name mangling specifications ` for details and special cases. + My class defines __del__ but it is not called when I delete the object. ----------------------------------------------------------------------- @@ -1783,7 +1789,7 @@ The :keyword:`del` statement does not necessarily call :meth:`~object.__del__` - decrements the object's reference count, and if this reaches zero :meth:`!__del__` is called. -If your data structures contain circular links (e.g. a tree where each child has +If your data structures contain circular links (for example, a tree where each child has a parent reference and each parent has a list of children) the reference counts will never go back to zero. Once in a while Python runs an algorithm to detect such cycles, but the garbage collector might run some time after the last @@ -1885,9 +1891,9 @@ are preferred. In particular, identity tests should not be used to check constants such as :class:`int` and :class:`str` which aren't guaranteed to be singletons:: - >>> a = 1000 - >>> b = 500 - >>> c = b + 500 + >>> a = 10_000_000 + >>> b = 5_000_000 + >>> c = b + 5_000_000 >>> a is c False @@ -1956,9 +1962,9 @@ parent class: .. testcode:: - from datetime import date + import datetime as dt - class FirstOfMonthDate(date): + class FirstOfMonthDate(dt.date): "Always choose the first day of the month" def __new__(cls, year, month, day): return super().__new__(cls, year, month, 1) @@ -2001,7 +2007,7 @@ The two principal tools for caching methods are former stores results at the instance level and the latter at the class level. -The *cached_property* approach only works with methods that do not take +The ``cached_property`` approach only works with methods that do not take any arguments. It does not create a reference to the instance. The cached method result will be kept only as long as the instance is alive. @@ -2010,7 +2016,7 @@ method result will be released right away. The disadvantage is that if instances accumulate, so too will the accumulated method results. They can grow without bound. -The *lru_cache* approach works with methods that have :term:`hashable` +The ``lru_cache`` approach works with methods that have :term:`hashable` arguments. It creates a reference to the instance unless special efforts are made to pass in weak references. @@ -2044,11 +2050,11 @@ This example shows the various techniques:: # Depends on the station_id, date, and units. The above example assumes that the *station_id* never changes. If the -relevant instance attributes are mutable, the *cached_property* approach +relevant instance attributes are mutable, the ``cached_property`` approach can't be made to work because it cannot detect changes to the attributes. -To make the *lru_cache* approach work when the *station_id* is mutable, +To make the ``lru_cache`` approach work when the *station_id* is mutable, the class needs to define the :meth:`~object.__eq__` and :meth:`~object.__hash__` methods so that the cache can detect relevant attribute updates:: @@ -2094,10 +2100,10 @@ one user but run as another, such as if you are testing with a web server. Unless the :envvar:`PYTHONDONTWRITEBYTECODE` environment variable is set, creation of a .pyc file is automatic if you're importing a module and Python -has the ability (permissions, free space, etc...) to create a ``__pycache__`` +has the ability (permissions, free space, and so on) to create a ``__pycache__`` subdirectory and write the compiled module to that subdirectory. -Running Python on a top level script is not considered an import and no +Running Python on a top-level script is not considered an import and no ``.pyc`` will be created. For example, if you have a top-level module ``foo.py`` that imports another module ``xyz.py``, when you run ``foo`` (by typing ``python foo.py`` as a shell command), a ``.pyc`` will be created for @@ -2116,7 +2122,7 @@ the ``compile()`` function in that module interactively:: This will write the ``.pyc`` to a ``__pycache__`` subdirectory in the same location as ``foo.py`` (or you can override that with the optional parameter -``cfile``). +*cfile*). You can also automatically compile all files in a directory or directories using the :mod:`compileall` module. You can do it from the shell prompt by running @@ -2221,7 +2227,7 @@ changed module, do this:: importlib.reload(modname) Warning: this technique is not 100% fool-proof. In particular, modules -containing statements like :: +containing statements like:: from modname import some_objects From 64d6c75dd02718e3554657a0c58c39122bf229ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Mon, 9 Mar 2026 19:37:33 +0000 Subject: [PATCH 049/775] GH-145273: don't skip missing platstdlib warning if stdlib_zip is found (#145544) --- Modules/getpath.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/getpath.py b/Modules/getpath.py index 2f4d635a295..4dceb5cdc8d 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -776,9 +776,9 @@ def search_up(prefix, *landmarks, test=isfile): # Warn if the standard library is missing, unless pythonpath_was_set was set, as # that skips parts of the stdlib directories calculation — assume the provided # pythonpath is correct. This is how subinterpreters initialize the path for eg. -if not py_setpath and not pythonpath_was_set and (not stdlib_zip or not isfile(stdlib_zip)): +if not py_setpath and not pythonpath_was_set: home_hint = f"The Python 'home' directory was set to {home!r}, is this correct?" - if not stdlib_dir or not isdir(stdlib_dir): + if (not stdlib_zip or not isfile(stdlib_zip)) and (not stdlib_dir or not isdir(stdlib_dir)): hint = home_hint if home else f'sys.prefix is set to {prefix}, is this correct?' warn('WARN: Could not find the standard library directory! ' + hint) elif not platstdlib_dir or not isdir(platstdlib_dir): From d6c1763a08d7679ee4b11466c7fa088692c6903e Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:43:13 +0000 Subject: [PATCH 050/775] Remove the `distutils-sig@python.org` email in 'Installing Python Modules' (#145613) --- Doc/installing/index.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index 3a485a43a5a..412005f3ec8 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -6,8 +6,6 @@ Installing Python Modules ************************* -:Email: distutils-sig@python.org - As a popular open source development project, Python has an active supporting community of contributors and users that also make their software available for other Python developers to use under open source license terms. From 63eaaf95999c530cbd75b3addc3e660499d3adbe Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:56:41 +0000 Subject: [PATCH 051/775] gh-145701: Fix `__classdict__` & `__conditional_annotations__` in class-scope inlined comprehensions (GH-145702) --- Lib/test/test_listcomps.py | 12 +++++++++ ...-03-09-18-52-03.gh-issue-145701.79KQyO.rst | 3 +++ Python/symtable.c | 26 ++++++++++++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py index 70148dc30fc..cee528722b8 100644 --- a/Lib/test/test_listcomps.py +++ b/Lib/test/test_listcomps.py @@ -180,6 +180,18 @@ def test_references___class___defined(self): code, outputs={"res": [2]}, scopes=["module", "function"]) self._check_in_scopes(code, raises=NameError, scopes=["class"]) + def test_references___classdict__(self): + code = """ + class i: [__classdict__ for x in y] + """ + self._check_in_scopes(code, raises=NameError) + + def test_references___conditional_annotations__(self): + code = """ + class i: [__conditional_annotations__ for x in y] + """ + self._check_in_scopes(code, raises=NameError) + def test_references___class___enclosing(self): code = """ __class__ = 2 diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst new file mode 100644 index 00000000000..23796082fb6 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst @@ -0,0 +1,3 @@ +Fix :exc:`SystemError` when ``__classdict__`` or +``__conditional_annotations__`` is in a class-scope inlined comprehension. +Found by OSS Fuzz in :oss-fuzz:`491105000`. diff --git a/Python/symtable.c b/Python/symtable.c index beb6df88d09..4b695e4b258 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -807,6 +807,8 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, PyObject *k, *v; Py_ssize_t pos = 0; int remove_dunder_class = 0; + int remove_dunder_classdict = 0; + int remove_dunder_cond_annotations = 0; while (PyDict_Next(comp->ste_symbols, &pos, &k, &v)) { // skip comprehension parameter @@ -829,15 +831,27 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, if (existing == NULL && PyErr_Occurred()) { return 0; } - // __class__ is never allowed to be free through a class scope (see + // __class__, __classdict__ and __conditional_annotations__ are + // never allowed to be free through a class scope (see // drop_class_free) if (scope == FREE && ste->ste_type == ClassBlock && - _PyUnicode_EqualToASCIIString(k, "__class__")) { + (_PyUnicode_EqualToASCIIString(k, "__class__") || + _PyUnicode_EqualToASCIIString(k, "__classdict__") || + _PyUnicode_EqualToASCIIString(k, "__conditional_annotations__"))) { scope = GLOBAL_IMPLICIT; if (PySet_Discard(comp_free, k) < 0) { return 0; } - remove_dunder_class = 1; + + if (_PyUnicode_EqualToASCIIString(k, "__class__")) { + remove_dunder_class = 1; + } + else if (_PyUnicode_EqualToASCIIString(k, "__conditional_annotations__")) { + remove_dunder_cond_annotations = 1; + } + else { + remove_dunder_classdict = 1; + } } if (!existing) { // name does not exist in scope, copy from comprehension @@ -877,6 +891,12 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, if (remove_dunder_class && PyDict_DelItemString(comp->ste_symbols, "__class__") < 0) { return 0; } + if (remove_dunder_classdict && PyDict_DelItemString(comp->ste_symbols, "__classdict__") < 0) { + return 0; + } + if (remove_dunder_cond_annotations && PyDict_DelItemString(comp->ste_symbols, "__conditional_annotations__") < 0) { + return 0; + } return 1; } From 0b65c88c2af6e09530a9aa21800771aa687371db Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Mon, 9 Mar 2026 18:41:07 -0400 Subject: [PATCH 052/775] gh-145685: Stop the world when updating MRO of existing types (gh-145707) We already have a stop-the-world pause elsewhere in this code path (type_set_bases) and this makes will make it easier to avoid contention on the TYPE_LOCK when looking up names in the MRO hierarchy. Also use deferred reference counting for non-immortal MROs. --- Objects/typeobject.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 27ec8bb40a9..81abb0990ee 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -647,7 +647,6 @@ clear_tp_bases(PyTypeObject *self, int final) static inline PyObject * lookup_tp_mro(PyTypeObject *self) { - ASSERT_NEW_TYPE_OR_LOCKED(self); return self->tp_mro; } @@ -664,8 +663,19 @@ set_tp_mro(PyTypeObject *self, PyObject *mro, int initial) /* Other checks are done via set_tp_bases. */ _Py_SetImmortal(mro); } + else { + PyUnstable_Object_EnableDeferredRefcount(mro); + } + } + if (!initial) { + type_lock_prevent_release(); + types_stop_world(); } self->tp_mro = mro; + if (!initial) { + types_start_world(); + type_lock_allow_release(); + } } static inline void @@ -1728,18 +1738,11 @@ static PyObject * type_get_mro(PyObject *tp, void *Py_UNUSED(closure)) { PyTypeObject *type = PyTypeObject_CAST(tp); - PyObject *mro; - - BEGIN_TYPE_LOCK(); - mro = lookup_tp_mro(type); + PyObject *mro = lookup_tp_mro(type); if (mro == NULL) { - mro = Py_None; - } else { - Py_INCREF(mro); + Py_RETURN_NONE; } - - END_TYPE_LOCK(); - return mro; + return Py_NewRef(mro); } static PyTypeObject *find_best_base(PyObject *); From 099943b122cda2548ad7e9cb4b327706929af7d0 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:51:00 +0000 Subject: [PATCH 053/775] Vary compiler flags in `fuzz_pycompile` (#145236) * Vary compiler flags in fuzz_pycompile * Drop `PyCF_SOURCE_IS_UTF8` --- Modules/_xxtestfuzz/fuzzer.c | 46 +++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index 14da472c1bb..f3a22f3f6a8 100644 --- a/Modules/_xxtestfuzz/fuzzer.c +++ b/Modules/_xxtestfuzz/fuzzer.c @@ -517,8 +517,8 @@ static int fuzz_pycompile(const char* data, size_t size) { return 0; } - // Need 2 bytes for parameter selection - if (size < 2) { + // Need 3 bytes for parameter selection + if (size < 3) { return 0; } @@ -530,25 +530,39 @@ static int fuzz_pycompile(const char* data, size_t size) { unsigned char optimize_idx = (unsigned char) data[1]; int optimize = optimize_vals[optimize_idx % NUM_OPTIMIZE_VALS]; + // Use third byte to determine compiler flags to use. + unsigned char flags_byte = (unsigned char) data[2]; + PyCompilerFlags flags = _PyCompilerFlags_INIT; + if (flags_byte & 0x01) { + flags.cf_flags |= PyCF_DONT_IMPLY_DEDENT; + } + if (flags_byte & 0x02) { + flags.cf_flags |= PyCF_ONLY_AST; + } + if (flags_byte & 0x04) { + flags.cf_flags |= PyCF_IGNORE_COOKIE; + } + if (flags_byte & 0x08) { + flags.cf_flags |= PyCF_TYPE_COMMENTS; + } + if (flags_byte & 0x10) { + flags.cf_flags |= PyCF_ALLOW_TOP_LEVEL_AWAIT; + } + if (flags_byte & 0x20) { + flags.cf_flags |= PyCF_ALLOW_INCOMPLETE_INPUT; + } + if (flags_byte & 0x40) { + flags.cf_flags |= PyCF_OPTIMIZED_AST; + } + char pycompile_scratch[MAX_PYCOMPILE_TEST_SIZE]; // Create a NUL-terminated C string from the remaining input - memcpy(pycompile_scratch, data + 2, size - 2); + memcpy(pycompile_scratch, data + 3, size - 3); // Put a NUL terminator just after the copied data. (Space was reserved already.) - pycompile_scratch[size - 2] = '\0'; + pycompile_scratch[size - 3] = '\0'; - // XXX: instead of always using NULL for the `flags` value to - // `Py_CompileStringExFlags`, there are many flags that conditionally - // change parser behavior: - // - // #define PyCF_TYPE_COMMENTS 0x1000 - // #define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000 - // #define PyCF_ONLY_AST 0x0400 - // - // It would be good to test various combinations of these, too. - PyCompilerFlags *flags = NULL; - - PyObject *result = Py_CompileStringExFlags(pycompile_scratch, "", start, flags, optimize); + PyObject *result = Py_CompileStringExFlags(pycompile_scratch, "", start, &flags, optimize); if (result == NULL) { /* Compilation failed, most likely from a syntax error. If it was a SystemError we abort. There's no non-bug reason to raise a From 66eafc9ea74e5233f2c46b424729d6dadfbb3111 Mon Sep 17 00:00:00 2001 From: Hai Zhu Date: Tue, 10 Mar 2026 12:12:48 +0800 Subject: [PATCH 054/775] gh-144681: Fix JIT trace builder assertion failure when conditional branch jump target coincides with fallthrough target (GH-144742) --- Lib/test/test_capi/test_opt.py | 13 +++++++++++++ .../2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst | 1 + Python/optimizer.c | 4 ++-- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 90e2ed20d1f..8fa4f02afb5 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -461,6 +461,19 @@ def testfunc(n): uops = get_opnames(ex) self.assertIn(self.guard_is_false, uops) + def test_branch_coincident_targets(self): + # test for gh-144681: https://github.com/python/cpython/issues/144681 + def testfunc(n): + for _ in range(n): + r = [x for x in range(10) if [].append(x) or True] + return r + + res = testfunc(TIER2_THRESHOLD) + ex = get_first_executor(testfunc) + + self.assertEqual(res, list(range(10))) + self.assertIsNotNone(ex) + def test_for_iter_tier_two(self): class MyIter: def __init__(self, n): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst new file mode 100644 index 00000000000..c8ca7a7fa19 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst @@ -0,0 +1 @@ +Fix a JIT assertion failure when a conditional branch jumps to the same target as the fallthrough path. diff --git a/Python/optimizer.c b/Python/optimizer.c index 4387bcb0d67..7315bb6b9f6 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -786,8 +786,8 @@ _PyJit_translate_single_bytecode_to_trace( _Py_CODEUNIT *computed_next_instr = computed_next_instr_without_modifiers + (computed_next_instr_without_modifiers->op.code == NOT_TAKEN); _Py_CODEUNIT *computed_jump_instr = computed_next_instr_without_modifiers + oparg; assert(next_instr == computed_next_instr || next_instr == computed_jump_instr); - int jump_happened = computed_jump_instr == next_instr; - assert(jump_happened == (target_instr[1].cache & 1)); + int jump_happened = target_instr[1].cache & 1; + assert(jump_happened ? (next_instr == computed_jump_instr) : (next_instr == computed_next_instr)); uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_happened]; ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(jump_happened ? computed_next_instr : computed_jump_instr, old_code)); break; From 170d85a37deb77a1711ab86288a33fda5c0a381a Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:45:07 +0200 Subject: [PATCH 055/775] gh-145731: Fix negative timestamp during DST on Windows (GH-145728) --- ...-03-10-09-46-44.gh-issue-145731.5uEGgb.rst | 1 + Python/pytime.c | 24 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst diff --git a/Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst b/Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst new file mode 100644 index 00000000000..676a68e5a91 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst @@ -0,0 +1 @@ +Fix negative timestamp during DST on Windows. Patch by Hugo van Kemenade. diff --git a/Python/pytime.c b/Python/pytime.c index 2b1488911ef..399ff59ad01 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -320,23 +320,27 @@ _PyTime_windows_filetime(time_t timer, struct tm *tm, int is_local) ft.dwLowDateTime = (DWORD)(ticks); // cast to DWORD truncates to low 32 bits ft.dwHighDateTime = (DWORD)(ticks >> 32); - /* Convert FILETIME to SYSTEMTIME */ + /* Convert FILETIME to SYSTEMTIME (UTC) */ + SYSTEMTIME st_utc; + if (!FileTimeToSystemTime(&ft, &st_utc)) { + PyErr_SetFromWindowsErr(0); + return -1; + } + SYSTEMTIME st_result; if (is_local) { - /* Convert to local time */ - FILETIME ft_local; - if (!FileTimeToLocalFileTime(&ft, &ft_local) || - !FileTimeToSystemTime(&ft_local, &st_result)) { + /* Convert UTC SYSTEMTIME to local SYSTEMTIME. + * We use SystemTimeToTzSpecificLocalTime instead of + * FileTimeToLocalFileTime because the latter always applies the + * _current_ DST bias, whereas the former applies the correct + * DST rules for the date being converted (gh-80620). */ + if (!SystemTimeToTzSpecificLocalTime(NULL, &st_utc, &st_result)) { PyErr_SetFromWindowsErr(0); return -1; } } else { - /* Convert to UTC */ - if (!FileTimeToSystemTime(&ft, &st_result)) { - PyErr_SetFromWindowsErr(0); - return -1; - } + st_result = st_utc; } /* Convert SYSTEMTIME to struct tm */ From bdf0105291061f9c89b2a3d4af4f465c54c8874a Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Tue, 10 Mar 2026 08:56:00 +0000 Subject: [PATCH 056/775] gh-103997: Remove incorrect statements about `-c` dedenting (gh-138624) --- Doc/using/cmdline.rst | 2 +- Doc/whatsnew/3.14.rst | 3 +-- Include/internal/pycore_unicodeobject.h | 3 ++- Misc/NEWS.d/3.14.0b1.rst | 4 ++-- Objects/unicodeobject.c | 3 ++- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 84b8575284b..cc3d2f154ed 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -49,7 +49,7 @@ additional methods of invocation: appropriately named script from that directory. * When called with ``-c command``, it executes the Python statement(s) given as *command*. Here *command* may contain multiple statements separated by - newlines. Leading whitespace is significant in Python statements! + newlines. * When called with ``-m module-name``, the given module is located on the Python module path and executed as a script. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index d4517183d69..772334f40a5 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -897,8 +897,7 @@ Command line and environment (Contributed by Noah Kim and Adam Turner in :gh:`118655`.) * The command-line option :option:`-c` now automatically dedents its code - argument before execution. The auto-dedentation behavior mirrors - :func:`textwrap.dedent`. + argument before execution. (Contributed by Jon Crall and Steven Sun in :gh:`103998`.) * :option:`!-J` is no longer a reserved flag for Jython_, diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index af6cb84e9ff..74d84052a2b 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -326,7 +326,8 @@ extern PyObject* _PyUnicode_XStrip( /* Dedent a string. - Behaviour is expected to be an exact match of `textwrap.dedent`. + Intended to dedent Python source. Unlike `textwrap.dedent`, this + only supports spaces and tabs and doesn't normalize empty lines. Return a new reference on success, NULL with exception set on error. */ extern PyObject* _PyUnicode_Dedent(PyObject *unicode); diff --git a/Misc/NEWS.d/3.14.0b1.rst b/Misc/NEWS.d/3.14.0b1.rst index 045c47ce5ad..cb86c95a672 100644 --- a/Misc/NEWS.d/3.14.0b1.rst +++ b/Misc/NEWS.d/3.14.0b1.rst @@ -1881,8 +1881,8 @@ Improve error message when :exc:`TypeError` occurs during .. nonce: BS3uVt .. section: Core and Builtins -String arguments passed to "-c" are now automatically dedented as if by -:func:`textwrap.dedent`. This allows "python -c" invocations to be indented +String arguments passed to "-c" are now automatically dedented. +This allows "python -c" invocations to be indented in shell scripts without causing indentation errors. (Patch by Jon Crall and Steven Sun) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 7756f1a8482..a65c43874e8 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13581,7 +13581,8 @@ search_longest_common_leading_whitespace( } /* Dedent a string. - Behaviour is expected to be an exact match of `textwrap.dedent`. + Intended to dedent Python source. Unlike `textwrap.dedent`, this + only supports spaces and tabs and doesn't normalize empty lines. Return a new reference on success, NULL with exception set on error. */ PyObject * From 19676e5fc28bdee8325a062a31ddeee60960cf75 Mon Sep 17 00:00:00 2001 From: Emma Smith Date: Tue, 10 Mar 2026 02:21:57 -0700 Subject: [PATCH 057/775] gh-145607: Ensure BIG_DATA has two compressed blocks in test_bz2 (#145730) --- Lib/test/test_bz2.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index 3b7897b8a88..d8e3b671ec2 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -66,18 +66,28 @@ class BaseTest(unittest.TestCase): EMPTY_DATA = b'BZh9\x17rE8P\x90\x00\x00\x00\x00' BAD_DATA = b'this is not a valid bzip2 file' - # Some tests need more than one block of uncompressed data. Since one block - # is at least 100,000 bytes, we gather some data dynamically and compress it. - # Note that this assumes that compression works correctly, so we cannot - # simply use the bigger test data for all tests. + # Some tests need more than one block of data. The bz2 module does not + # support flushing a block during compression, so we must read in data until + # there are at least 2 blocks. Since different orderings of Python files may + # be compressed differently, we need to check the compression output for + # more than one bzip2 block header magic, a hex encoding of Pi + # (0x314159265359) + bz2_block_magic = bytes.fromhex('314159265359') test_size = 0 - BIG_TEXT = bytearray(128*1024) + BIG_TEXT = b'' + BIG_DATA = b'' + compressor = BZ2Compressor(1) for fname in glob.glob(os.path.join(glob.escape(os.path.dirname(__file__)), '*.py')): with open(fname, 'rb') as fh: - test_size += fh.readinto(memoryview(BIG_TEXT)[test_size:]) - if test_size > 128*1024: + data = fh.read() + BIG_DATA += compressor.compress(data) + BIG_TEXT += data + # TODO(emmatyping): if it is impossible for a block header to cross + # multiple outputs, we can just search the output of each compress call + # which should be more efficient + if BIG_DATA.count(bz2_block_magic) > 1: + BIG_DATA += compressor.flush() break - BIG_DATA = bz2.compress(BIG_TEXT, compresslevel=1) def setUp(self): fd, self.filename = tempfile.mkstemp() From 3f7141dac90d06795293ca2d071198ab6b2318b2 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Tue, 10 Mar 2026 10:46:13 +0100 Subject: [PATCH 058/775] gh-145376: Fix refleaks and double decref for code in Python/ (#145666) --- Python/ceval.c | 1 + Python/crossinterp.c | 8 ++++---- Python/sysmodule.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 1e5142f4b45..950050a6027 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2243,6 +2243,7 @@ _PyEval_ExceptionGroupMatch(_PyInterpreterFrame *frame, PyObject* exc_value, if (f != NULL) { PyObject *tb = _PyTraceBack_FromFrame(NULL, f); if (tb == NULL) { + Py_DECREF(wrapped); return -1; } PyException_SetTraceback(wrapped, tb); diff --git a/Python/crossinterp.c b/Python/crossinterp.c index c8a80e7a986..f92927da475 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -1103,12 +1103,12 @@ _convert_exc_to_TracebackException(PyObject *exc, PyObject **p_tbexc) } PyObject *tbexc = PyObject_Call(create, args, kwargs); - Py_DECREF(args); - Py_DECREF(kwargs); - Py_DECREF(create); if (tbexc == NULL) { goto error; } + Py_DECREF(args); + Py_DECREF(kwargs); + Py_DECREF(create); *p_tbexc = tbexc; return 0; @@ -1497,7 +1497,7 @@ _PyXI_excinfo_Apply(_PyXI_excinfo *info, PyObject *exctype) PyObject *formatted = _PyXI_excinfo_format(info); PyErr_SetObject(exctype, formatted); - Py_DECREF(formatted); + Py_XDECREF(formatted); if (tbexc != NULL) { PyObject *exc = PyErr_GetRaisedException(); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 55b4072213d..893a116565e 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2499,7 +2499,7 @@ sys_remote_exec_impl(PyObject *module, int pid, PyObject *script) } if (PySys_Audit("sys.remote_exec", "iO", pid, script) < 0) { - return NULL; + goto error; } debugger_script_path = PyBytes_AS_STRING(path); From 478a315b7a22bd09b97431697d0832879631f7f1 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Tue, 10 Mar 2026 15:44:20 +0500 Subject: [PATCH 059/775] GH-145247: Implement _PyTuple_FromPair() (#145325) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement _PyTuple_FromPair() and _PyTuple_FromPairSteal(). Co-authored-by: Pieter Eendebak Co-authored-by: Victor Stinner Co-authored-by: Bartosz Sławecki Co-authored-by: Kumar Aditya --- Include/internal/pycore_tuple.h | 3 ++ Lib/test/test_capi/test_tuple.py | 37 +++++++++++++++++++++ Modules/Setup.stdlib.in | 2 +- Modules/_testinternalcapi.c | 3 ++ Modules/_testinternalcapi/parts.h | 1 + Modules/_testinternalcapi/tuple.c | 39 +++++++++++++++++++++++ Objects/tupleobject.c | 29 +++++++++++++++++ PCbuild/_testinternalcapi.vcxproj | 1 + PCbuild/_testinternalcapi.vcxproj.filters | 3 ++ 9 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Modules/_testinternalcapi/tuple.c diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 00562bef769..b3fa28f5bf2 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -27,6 +27,9 @@ PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRe PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t); PyAPI_FUNC(PyObject *) _PyTuple_BinarySlice(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyTuple_FromPair(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyTuple_FromPairSteal(PyObject *, PyObject *); + typedef struct { PyObject_HEAD Py_ssize_t it_index; diff --git a/Lib/test/test_capi/test_tuple.py b/Lib/test/test_capi/test_tuple.py index d6669d7802c..0c27e81168f 100644 --- a/Lib/test/test_capi/test_tuple.py +++ b/Lib/test/test_capi/test_tuple.py @@ -1,9 +1,11 @@ import unittest import gc +from sys import getrefcount from test.support import import_helper _testcapi = import_helper.import_module('_testcapi') _testlimitedcapi = import_helper.import_module('_testlimitedcapi') +_testinternalcapi = import_helper.import_module('_testinternalcapi') NULL = None PY_SSIZE_T_MIN = _testcapi.PY_SSIZE_T_MIN @@ -118,6 +120,41 @@ def test_tuple_pack(self): # CRASHES pack(1, NULL) # CRASHES pack(2, [1]) + def check_tuple_from_pair(self, from_pair): + self.assertEqual(type(from_pair(1, 2)), tuple) + self.assertEqual(from_pair(1, 145325), (1, 145325)) + self.assertEqual(from_pair(None, None), (None, None)) + self.assertEqual(from_pair(True, False), (True, False)) + + # user class supports gc + class Temp: + pass + temp = Temp() + temp_rc = getrefcount(temp) + self.assertEqual(from_pair(temp, temp), (temp, temp)) + self.assertEqual(getrefcount(temp), temp_rc) + + self._not_tracked(from_pair(1, 2)) + self._not_tracked(from_pair(None, None)) + self._not_tracked(from_pair(True, False)) + self._tracked(from_pair(temp, (1, 2))) + self._tracked(from_pair(temp, 1)) + self._tracked(from_pair([], {})) + + self.assertRaises(TypeError, from_pair, 1, 2, 3) + self.assertRaises(TypeError, from_pair, 1) + self.assertRaises(TypeError, from_pair) + + def test_tuple_from_pair(self): + # Test _PyTuple_FromPair() + from_pair = _testinternalcapi.tuple_from_pair + self.check_tuple_from_pair(from_pair) + + def test_tuple_from_pair_steal(self): + # Test _PyTuple_FromPairSteal() + from_pair = _testinternalcapi.tuple_from_pair_steal + self.check_tuple_from_pair(from_pair) + def test_tuple_size(self): # Test PyTuple_Size() size = _testlimitedcapi.tuple_size diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 39be41d9d2a..0d520684c79 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -174,7 +174,7 @@ @MODULE_XXSUBTYPE_TRUE@xxsubtype xxsubtype.c @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c -@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c +@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c _testinternalcapi/tuple.c @MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/modsupport.c _testcapi/monitoring.c _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c _testcapi/module.c @MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/threadstate.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index b6ed0b89023..aa5911ef2fb 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -2987,6 +2987,9 @@ module_exec(PyObject *module) if (_PyTestInternalCapi_Init_CriticalSection(module) < 0) { return 1; } + if (_PyTestInternalCapi_Init_Tuple(module) < 0) { + return 1; + } Py_ssize_t sizeof_gc_head = 0; #ifndef Py_GIL_DISABLED diff --git a/Modules/_testinternalcapi/parts.h b/Modules/_testinternalcapi/parts.h index 03557d5bf59..81f536c3bab 100644 --- a/Modules/_testinternalcapi/parts.h +++ b/Modules/_testinternalcapi/parts.h @@ -15,5 +15,6 @@ int _PyTestInternalCapi_Init_PyTime(PyObject *module); int _PyTestInternalCapi_Init_Set(PyObject *module); int _PyTestInternalCapi_Init_Complex(PyObject *module); int _PyTestInternalCapi_Init_CriticalSection(PyObject *module); +int _PyTestInternalCapi_Init_Tuple(PyObject *module); #endif // Py_TESTINTERNALCAPI_PARTS_H diff --git a/Modules/_testinternalcapi/tuple.c b/Modules/_testinternalcapi/tuple.c new file mode 100644 index 00000000000..c12ee32deb9 --- /dev/null +++ b/Modules/_testinternalcapi/tuple.c @@ -0,0 +1,39 @@ +#include "parts.h" + +#include "pycore_tuple.h" + + +static PyObject * +tuple_from_pair(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *first, *second; + if (!PyArg_ParseTuple(args, "OO", &first, &second)) { + return NULL; + } + + return _PyTuple_FromPair(first, second); +} + +static PyObject * +tuple_from_pair_steal(PyObject *Py_UNUSED(module), PyObject *args) +{ + PyObject *first, *second; + if (!PyArg_ParseTuple(args, "OO", &first, &second)) { + return NULL; + } + + return _PyTuple_FromPairSteal(Py_NewRef(first), Py_NewRef(second)); +} + + +static PyMethodDef test_methods[] = { + {"tuple_from_pair", tuple_from_pair, METH_VARARGS}, + {"tuple_from_pair_steal", tuple_from_pair_steal, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestInternalCapi_Init_Tuple(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 3c68955495d..01afa53e15c 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -202,6 +202,35 @@ PyTuple_Pack(Py_ssize_t n, ...) return (PyObject *)result; } +PyObject * +_PyTuple_FromPair(PyObject *first, PyObject *second) +{ + assert(first != NULL); + assert(second != NULL); + + return _PyTuple_FromPairSteal(Py_NewRef(first), Py_NewRef(second)); +} + +PyObject * +_PyTuple_FromPairSteal(PyObject *first, PyObject *second) +{ + assert(first != NULL); + assert(second != NULL); + + PyTupleObject *op = tuple_alloc(2); + if (op == NULL) { + Py_DECREF(first); + Py_DECREF(second); + return NULL; + } + PyObject **items = op->ob_item; + items[0] = first; + items[1] = second; + if (maybe_tracked(first) || maybe_tracked(second)) { + _PyObject_GC_TRACK(op); + } + return (PyObject *)op; +} /* Methods */ diff --git a/PCbuild/_testinternalcapi.vcxproj b/PCbuild/_testinternalcapi.vcxproj index 3818e6d3f7b..f3e423fa046 100644 --- a/PCbuild/_testinternalcapi.vcxproj +++ b/PCbuild/_testinternalcapi.vcxproj @@ -100,6 +100,7 @@ + diff --git a/PCbuild/_testinternalcapi.vcxproj.filters b/PCbuild/_testinternalcapi.vcxproj.filters index 012d709bd1c..7ab242c2c23 100644 --- a/PCbuild/_testinternalcapi.vcxproj.filters +++ b/PCbuild/_testinternalcapi.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + From 55b36fdb3deebc5692a6d1379b0d904ced27e663 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 10 Mar 2026 13:11:43 +0200 Subject: [PATCH 060/775] gh-133879: Copyedit "What's new in Python 3.15" (#145737) --- Doc/whatsnew/3.15.rst | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 42b6171c1a8..ead4e7cbf28 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -66,19 +66,22 @@ Summary -- Release highlights .. PEP-sized items next. * :pep:`810`: :ref:`Explicit lazy imports for faster startup times - ` + ` * :pep:`814`: :ref:`Add frozendict built-in type ` * :pep:`799`: :ref:`A dedicated profiling package for organizing Python profiling tools ` * :pep:`799`: :ref:`Tachyon: High frequency statistical sampling profiler ` -* :pep:`798`: :ref:`Unpacking in Comprehensions +* :pep:`798`: :ref:`Unpacking in comprehensions ` * :pep:`686`: :ref:`Python now uses UTF-8 as the default encoding ` +* :pep:`728`: ``TypedDict`` with typed extra items +* :pep:`747`: :ref:`Annotating type forms with TypeForm + ` * :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object - ` + ` * :ref:`The JIT compiler has been significantly upgraded ` * :ref:`Improved error messages ` @@ -86,7 +89,7 @@ Summary -- Release highlights New features ============ -.. _whatsnew315-pep810: +.. _whatsnew315-lazy-imports: :pep:`810`: Explicit lazy imports --------------------------------- @@ -120,12 +123,12 @@ name: .. code-block:: python lazy import json - lazy from datetime import datetime + lazy from pathlib import Path - print("Starting up...") # json and datetime not loaded yet + print("Starting up...") # json and pathlib not loaded yet - data = json.loads('{"key": "value"}') # json gets loads here - now = datetime() # datetime loads here + data = json.loads('{"key": "value"}') # json loads here + p = Path(".") # pathlib loads here This mechanism is particularly useful for applications that import many modules at the top level but may only use a subset of them in any given run. @@ -189,9 +192,9 @@ raise :exc:`SyntaxError`). ---------------------------------------- A new :term:`immutable` type, :class:`frozendict`, is added to the :mod:`builtins` module. -It does not allow modification after creation. A ``frozendict`` is not a subclass of ``dict``; -it inherits directly from ``object``. A ``frozendict`` is :term:`hashable` -as long as all of its keys and values are hashable. A ``frozendict`` preserves +It does not allow modification after creation. A :class:`!frozendict` is not a subclass of ``dict``; +it inherits directly from ``object``. A :class:`!frozendict` is :term:`hashable` +as long as all of its keys and values are hashable. A :class:`!frozendict` preserves insertion order, but comparison does not take order into account. For example:: @@ -1273,7 +1276,7 @@ csv .. _whatsnew315-jit: Upgraded JIT compiler -===================== +--------------------- Results from the `pyperformance `__ benchmark suite report @@ -1438,6 +1441,8 @@ threading typing ------ +.. _whatsnew315-typeform: + * :pep:`747`: Add :data:`~typing.TypeForm`, a new special form for annotating values that are themselves type expressions. ``TypeForm[T]`` means "a type form object describing ``T`` (or a type @@ -1636,7 +1641,7 @@ New features and :c:data:`Py_mod_abi`. (Contributed by Petr Viktorin in :gh:`137210`.) -.. _whatsnew315-pep782: +.. _whatsnew315-pybyteswriter: * Implement :pep:`782`, the :ref:`PyBytesWriter API `. Add functions: From 368a26777a9915326b4857402a8ab595d9837f95 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 10 Mar 2026 13:38:48 +0200 Subject: [PATCH 061/775] gh-142927: Detect system theme in flame graph like in heatmap (#144885) --- .../sampling/_flamegraph_assets/flamegraph.js | 42 +------------- .../flamegraph_template.html | 2 +- .../sampling/_heatmap_assets/heatmap.js | 17 ------ .../_heatmap_assets/heatmap_shared.js | 27 --------- Lib/profiling/sampling/_shared_assets/base.js | 58 +++++++++++++++++++ Lib/profiling/sampling/heatmap_collector.py | 4 +- Lib/profiling/sampling/stack_collector.py | 4 +- 7 files changed, 68 insertions(+), 86 deletions(-) create mode 100644 Lib/profiling/sampling/_shared_assets/base.js diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js index 1a51802ffef..a2b21da2970 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js @@ -83,18 +83,7 @@ function resolveStringIndices(node) { // ============================================================================ function toggleTheme() { - const html = document.documentElement; - const current = html.getAttribute('data-theme') || 'light'; - const next = current === 'light' ? 'dark' : 'light'; - html.setAttribute('data-theme', next); - localStorage.setItem('flamegraph-theme', next); - - // Update theme button icon - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = next === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = next === 'dark' ? '' : 'none'; - } + toggleAndSaveTheme(); // Re-render flamegraph with new theme colors if (window.flamegraphData && normalData) { @@ -154,17 +143,9 @@ function toggleSection(sectionId) { } } +// Restore theme from localStorage, or use browser preference function restoreUIState() { - // Restore theme - const savedTheme = localStorage.getItem('flamegraph-theme'); - if (savedTheme) { - document.documentElement.setAttribute('data-theme', savedTheme); - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = savedTheme === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = savedTheme === 'dark' ? '' : 'none'; - } - } + applyTheme(getPreferredTheme()); // Restore sidebar state const savedSidebar = localStorage.getItem('flamegraph-sidebar'); @@ -1242,23 +1223,6 @@ function generateInvertedFlamegraph(data) { return invertedRoot; } -function updateToggleUI(toggleId, isOn) { - const toggle = document.getElementById(toggleId); - if (toggle) { - const track = toggle.querySelector('.toggle-track'); - const labels = toggle.querySelectorAll('.toggle-label'); - if (isOn) { - track.classList.add('on'); - labels[0].classList.remove('active'); - labels[1].classList.add('active'); - } else { - track.classList.remove('on'); - labels[0].classList.add('active'); - labels[1].classList.remove('active'); - } - } -} - function toggleInvert() { isInverted = !isInverted; updateToggleUI('toggle-invert', isInverted); diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html index 195a555d68e..07b15a5a2b4 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html @@ -1,5 +1,5 @@ - + diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap.js b/Lib/profiling/sampling/_heatmap_assets/heatmap.js index 53928b7b20f..2da1103b82a 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap.js @@ -203,23 +203,6 @@ function applyLineColors() { // Toggle Controls // ============================================================================ -function updateToggleUI(toggleId, isOn) { - const toggle = document.getElementById(toggleId); - if (toggle) { - const track = toggle.querySelector('.toggle-track'); - const labels = toggle.querySelectorAll('.toggle-label'); - if (isOn) { - track.classList.add('on'); - labels[0].classList.remove('active'); - labels[1].classList.add('active'); - } else { - track.classList.remove('on'); - labels[0].classList.add('active'); - labels[1].classList.remove('active'); - } - } -} - function toggleColdCode() { coldCodeHidden = !coldCodeHidden; applyHotFilter(); diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js b/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js index 84b13ca0a96..fb761335876 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap_shared.js @@ -43,33 +43,6 @@ function intensityToColor(intensity) { // Theme Support // ============================================================================ -// Get the preferred theme from localStorage or browser preference -function getPreferredTheme() { - const saved = localStorage.getItem('heatmap-theme'); - if (saved) return saved; - return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; -} - -// Apply theme and update UI. Returns the applied theme. -function applyTheme(theme) { - document.documentElement.setAttribute('data-theme', theme); - const btn = document.getElementById('theme-btn'); - if (btn) { - btn.querySelector('.icon-moon').style.display = theme === 'dark' ? 'none' : ''; - btn.querySelector('.icon-sun').style.display = theme === 'dark' ? '' : 'none'; - } - return theme; -} - -// Toggle theme and save preference. Returns the new theme. -function toggleAndSaveTheme() { - const current = document.documentElement.getAttribute('data-theme') || 'light'; - const next = current === 'light' ? 'dark' : 'light'; - applyTheme(next); - localStorage.setItem('heatmap-theme', next); - return next; -} - // Restore theme from localStorage, or use browser preference function restoreUIState() { applyTheme(getPreferredTheme()); diff --git a/Lib/profiling/sampling/_shared_assets/base.js b/Lib/profiling/sampling/_shared_assets/base.js new file mode 100644 index 00000000000..da8b5851c85 --- /dev/null +++ b/Lib/profiling/sampling/_shared_assets/base.js @@ -0,0 +1,58 @@ +// Tachyon Profiler - Shared JavaScript +// Common utilities shared between flamegraph and heatmap views + +// ============================================================================ +// Theme Support +// ============================================================================ + +// Storage key for theme preference +const THEME_STORAGE_KEY = 'tachyon-theme'; + +// Get the preferred theme from localStorage or system preference +function getPreferredTheme() { + const saved = localStorage.getItem(THEME_STORAGE_KEY); + if (saved) return saved; + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +} + +// Apply theme and update UI +function applyTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + const btn = document.getElementById('theme-btn'); + if (btn) { + const moonIcon = btn.querySelector('.icon-moon'); + const sunIcon = btn.querySelector('.icon-sun'); + if (moonIcon) moonIcon.style.display = theme === 'dark' ? 'none' : ''; + if (sunIcon) sunIcon.style.display = theme === 'dark' ? '' : 'none'; + } +} + +// Toggle theme and save preference. Returns the new theme. +function toggleAndSaveTheme() { + const current = document.documentElement.getAttribute('data-theme') || 'light'; + const next = current === 'light' ? 'dark' : 'light'; + applyTheme(next); + localStorage.setItem(THEME_STORAGE_KEY, next); + return next; +} + +// ============================================================================ +// Toggle Switch UI +// ============================================================================ + +function updateToggleUI(toggleId, isOn) { + const toggle = document.getElementById(toggleId); + if (toggle) { + const track = toggle.querySelector('.toggle-track'); + const labels = toggle.querySelectorAll('.toggle-label'); + if (isOn) { + track.classList.add('on'); + labels[0].classList.remove('active'); + labels[1].classList.add('active'); + } else { + track.classList.remove('on'); + labels[0].classList.add('active'); + labels[1].classList.remove('active'); + } + } +} diff --git a/Lib/profiling/sampling/heatmap_collector.py b/Lib/profiling/sampling/heatmap_collector.py index b6d9ff79e8c..ea1beec70d3 100644 --- a/Lib/profiling/sampling/heatmap_collector.py +++ b/Lib/profiling/sampling/heatmap_collector.py @@ -204,7 +204,9 @@ def _load_templates(self): self.file_css = css_content # Load JS - shared_js = (assets_dir / "heatmap_shared.js").read_text(encoding="utf-8") + base_js = (template_dir / "_shared_assets" / "base.js").read_text(encoding="utf-8") + heatmap_shared_js = (assets_dir / "heatmap_shared.js").read_text(encoding="utf-8") + shared_js = f"{base_js}\n{heatmap_shared_js}" self.index_js = f"{shared_js}\n{(assets_dir / 'heatmap_index.js').read_text(encoding='utf-8')}" self.file_js = f"{shared_js}\n{(assets_dir / 'heatmap.js').read_text(encoding='utf-8')}" diff --git a/Lib/profiling/sampling/stack_collector.py b/Lib/profiling/sampling/stack_collector.py index 5a3497a5408..931bc2c487b 100644 --- a/Lib/profiling/sampling/stack_collector.py +++ b/Lib/profiling/sampling/stack_collector.py @@ -377,7 +377,9 @@ def _create_flamegraph_html(self, data): html_template = (template_dir / "_flamegraph_assets" / "flamegraph_template.html").read_text(encoding="utf-8") css_content = get_combined_css("flamegraph") - js_content = (template_dir / "_flamegraph_assets" / "flamegraph.js").read_text(encoding="utf-8") + base_js = (template_dir / "_shared_assets" / "base.js").read_text(encoding="utf-8") + component_js = (template_dir / "_flamegraph_assets" / "flamegraph.js").read_text(encoding="utf-8") + js_content = f"{base_js}\n{component_js}" # Inline first-party CSS/JS html_template = html_template.replace( From 728e4a075e3dae7e04edf90ad137a35073deb141 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Tue, 10 Mar 2026 17:41:12 +0530 Subject: [PATCH 062/775] gh-142651: use `NonCallableMock._lock` for thread safety of `call_count` (#142922) --- Lib/unittest/mock.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 34fd49bf56f..64a01a0b713 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1184,10 +1184,16 @@ def _increment_mock_call(self, /, *args, **kwargs): # handle call_args # needs to be set here so assertions on call arguments pass before # execution in the case of awaited calls - _call = _Call((args, kwargs), two=True) - self.call_args = _call - self.call_args_list.append(_call) - self.call_count = len(self.call_args_list) + with NonCallableMock._lock: + # Lock is used here so that call_args_list and call_count are + # set atomically otherwise it is possible that by the time call_count + # is set another thread may have appended to call_args_list. + # The rest of this function relies on list.append being atomic and + # skips locking. + _call = _Call((args, kwargs), two=True) + self.call_args = _call + self.call_args_list.append(_call) + self.call_count = len(self.call_args_list) # initial stuff for method_calls: do_method_calls = self._mock_parent is not None From 6024d3c6dadf73bcd0b234d2d97365486253f0ee Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:30:46 +0200 Subject: [PATCH 063/775] Python 3.15.0a7 --- Doc/c-api/arg.rst | 4 +- Doc/c-api/dict.rst | 2 +- Doc/c-api/exceptions.rst | 2 +- Doc/c-api/import.rst | 10 +- Doc/c-api/object.rst | 2 +- Doc/library/dataclasses.rst | 2 +- Doc/library/email.headerregistry.rst | 2 +- Doc/library/exceptions.rst | 2 +- Doc/library/functions.rst | 6 +- Doc/library/importlib.rst | 4 +- Doc/library/mailbox.rst | 2 +- Doc/library/marshal.rst | 2 +- Doc/library/os.rst | 6 +- Doc/library/re.rst | 6 +- Doc/library/shutil.rst | 2 +- Doc/library/stdtypes.rst | 4 +- Doc/library/sys.rst | 8 +- Doc/library/types.rst | 2 +- Doc/library/unicodedata.rst | 2 +- Doc/library/xml.etree.elementtree.rst | 4 +- Doc/reference/lexical_analysis.rst | 2 +- Doc/reference/simple_stmts.rst | 2 +- Doc/using/cmdline.rst | 8 +- Include/patchlevel.h | 4 +- Lib/pydoc_data/module_docs.py | 2 +- Lib/pydoc_data/topics.py | 408 +++--- Misc/NEWS.d/3.15.0a7.rst | 1212 +++++++++++++++++ ...-07-21-00-33-38.gh-issue-136677.Y1_3ec.rst | 1 - ...-02-10-16-59-56.gh-issue-144675.Wrf3Es.rst | 1 - ...-02-10-18-26-04.gh-issue-144679.FIH73W.rst | 2 - ...-02-22-13-35-20.gh-issue-145110.KgWofW.rst | 2 - ...-02-27-18-10-02.gh-issue-144533.21fk9L.rst | 1 - ...-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst | 3 - ...-02-10-14-49-49.gh-issue-121617.57vMqa.rst | 3 - ...-02-12-19-03-31.gh-issue-141510.U_1tjz.rst | 9 - ...-02-18-15-12-34.gh-issue-144981.4ZdM63.rst | 3 - ...-02-24-14-46-05.gh-issue-144748.uhnFtE.rst | 2 - ...-03-03-14-59-57.gh-issue-142417.HiNP5j.rst | 2 - ...3-07-26-00-03-00.gh-issue-80667.N7Dh8B.rst | 2 - ...-02-19-21-06-30.gh-issue-130327.z3TaR8.rst | 2 - ...-09-15-13-28-48.gh-issue-138912.61EYbn.rst | 1 - ...-11-09-15-44-58.gh-issue-141226.KTb_3F.rst | 3 - ...-12-06-15-46-32.gh-issue-142349.IdTuYL.rst | 1 - ...2-06-21-45-52.gh-issue-144438.GI_uB1LR.rst | 2 - ...-02-08-13-14-00.gh-issue-144569.pjlJVe.rst | 1 - ...-02-11-11-28-25.gh-issue-144702.XjFumv.rst | 2 - ...-02-11-13-30-11.gh-issue-143300.yjB63-.rst | 1 - ...-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst | 1 - ...-02-12-19-01-13.gh-issue-141510.KlKjZg.rst | 1 - ...-02-13-12-00-00.gh-issue-144759.d3qYpe.rst | 4 - ...-02-13-18-30-59.gh-issue-144766.JGu3x3.rst | 1 - ...-02-16-12-28-43.gh-issue-144872.k9_Q30.rst | 1 - ...-02-17-18-27-28.gh-issue-144914.DcXO4m.rst | 1 - ...-02-17-21-04-03.gh-issue-100239.LyVabQ.rst | 2 - ...-02-17-22-27-11.gh-issue-141510.-4yYsf.rst | 2 - ...-02-18-21-44-39.gh-issue-141510.7LST2O.rst | 1 - ...-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst | 2 - ...-02-21-09-47-45.gh-issue-145058.e-RBw-.rst | 2 - ...-02-21-12-16-46.gh-issue-145055.VyT-zI.rst | 2 - ...-02-22-07-51-10.gh-issue-145064.iIMGKA.rst | 1 - ...-02-22-19-05-03.gh-issue-145118.bU6Sic.rst | 1 - ...20-15-00.gh-issue-144015.pystrhex_simd.rst | 5 - ...-02-22-22-05-09.gh-issue-145118.TaKMJE.rst | 1 - ...-02-23-23-18-28.gh-issue-145142.T-XbVe.rst | 2 - ...-02-24-18-30-56.gh-issue-145187.YjPu1Z.rst | 2 - ...-02-25-15-02-08.gh-issue-145197.G6hAUk.rst | 1 - ...-02-26-12-00-00.gh-issue-130555.TMSOIu.rst | 3 - ...-02-26-18-00-00.gh-issue-145241.hL2k9Q.rst | 3 - ...-02-26-20-51-54.gh-issue-145273.B5QcUp.rst | 2 - ...-02-26-21-07-38.gh-issue-145275.qE-3O1.rst | 3 - ...-02-26-21-36-00.gh-issue-145234.w0mQ9n.rst | 5 - ...-02-28-16-46-17.gh-issue-145376.lG5u1a.rst | 1 - ...-03-01-13-37-31.gh-issue-145335.e36kPJ.rst | 2 - ...-03-05-16-16-17.gh-issue-143055.qDUFlY.rst | 2 - ...3-05-19-10-56.gh-issue-145566.H4RupyYN.rst | 2 - ...-03-06-01-36-20.gh-issue-116738.OWVWRx.rst | 2 - ...3-06-21-05-05.gh-issue-145615.NKXXZgDW.rst | 2 - ...-03-09-18-52-03.gh-issue-145701.79KQyO.rst | 3 - ...-08-02-18-59-01.gh-issue-136246.RIK7nE.rst | 3 - ...-01-06-16-04-08.gh-issue-110937.SyO5lk.rst | 1 - ...-03-03-08-18-00.gh-issue-145450.VI7GXj.rst | 1 - .../2017-12-15-09-32-57.bpo-32234.XaOkhR.rst | 2 - .../2018-05-11-12-26-16.bpo-3405.CacMw9.rst | 3 - .../2020-04-07-05-09-34.bpo-40212.oPYeBs.rst | 1 - .../2020-04-10-14-29-53.bpo-40243.85HRib.rst | 1 - .../2022-02-05-00-15-03.bpo-42353.0ebVGG.rst | 10 - ...3-02-05-20-02-30.gh-issue-80667.7LmzeA.rst | 1 - ...-09-30-15-31-59.gh-issue-124748.KYzYFp.rst | 2 - ...-06-24-19-07-18.gh-issue-135883.38cePA.rst | 2 - ...-08-04-23-20-43.gh-issue-137335.IIjDJN.rst | 2 - ...-10-10-14-08-58.gh-issue-139899.09leRY.rst | 3 - ...2-06-16-14-18.gh-issue-142352.pW5HLX88.rst | 4 - ...-12-16-13-34-48.gh-issue-142787.wNitJX.rst | 2 - ...-12-18-00-14-16.gh-issue-142781.gcOeYF.rst | 2 - ...-01-01-05-26-00.gh-issue-143304.Kv7x9Q.rst | 1 - ...6-01-10-22-58-30.gh-issue-85809.0eW4wt.rst | 1 - ...-01-11-13-03-32.gh-issue-142516.u7An-s.rst | 2 - ...-01-11-16-59-22.gh-issue-143698.b-Cpeb.rst | 3 - ...-01-11-18-35-52.gh-issue-143698.gXDzsJ.rst | 3 - ...-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst | 1 - ...-01-17-08-44-25.gh-issue-143637.qyPqDo.rst | 1 - ...-02-03-19-57-41.gh-issue-144316.wop870.rst | 1 - ...-02-07-16-31-42.gh-issue-144285.iyH9iL.rst | 3 - ...-02-07-16-37-42.gh-issue-144475.8tFEXw.rst | 3 - ...-02-08-17-09-10.gh-issue-144321.w58PhQ.rst | 3 - ...-02-09-02-16-36.gh-issue-144615.s04x4n.rst | 3 - ...6-02-10-16-56-05.gh-issue-66305.PZ6GN8.rst | 3 - ...-02-10-22-05-51.gh-issue-144156.UbrC7F.rst | 1 - ...-02-12-17-56-17.gh-issue-117865.jE1ema.rst | 1 - ...3-00-00-00.gh-issue-142224.BidiMissing.rst | 2 - ...-02-13-11-14-18.gh-issue-144763.cDwnEE.rst | 2 - ...-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst | 1 - ...-02-14-14-56-44.gh-issue-140715.AbSheM.rst | 1 - ...-02-15-00-00-00.gh-issue-144833.TUelo1.rst | 3 - ...-02-15-12-02-20.gh-issue-144835.w_oS_J.rst | 2 - ...-02-17-11-15-17.gh-issue-141510.ZmqEUb.rst | 2 - ...-02-17-11-28-37.gh-issue-141510.OpAz0M.rst | 2 - ...-02-18-00-00-00.gh-issue-144809.nYpEUx.rst | 1 - ...-02-18-13-45-00.gh-issue-144777.R97q0a.rst | 1 - ...9-00-00-00.gh-issue-144986.atexit-leak.rst | 2 - ...6-02-19-10-57-40.gh-issue-88091.N7qGV-.rst | 1 - ...-02-19-15-42-06.gh-issue-134872.sjYX1-.rst | 1 - ...-02-19-16-26-08.gh-issue-141510.4Qxy8_.rst | 3 - ...-02-19-17-50-47.gh-issue-145006.9gqA0Q.rst | 2 - ...-02-19-18-02-54.gh-issue-141510.qzvYsO.rst | 3 - ...-02-19-20-54-25.gh-issue-145033.X9EBPQ.rst | 2 - ...6-02-20-13-03-10.gh-issue-66802.OYcAi_.rst | 3 - ...-02-21-17-34-53.gh-issue-123853.6RUwWh.rst | 1 - ...-02-23-20-52-55.gh-issue-145158.vWJtxI.rst | 2 - ...6-02-27-18-04-51.gh-issue-76007.17idfK.rst | 2 - ...-02-27-19-00-26.gh-issue-145301.2Wih4b.rst | 2 - ...-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst | 2 - ...-03-02-19-41-39.gh-issue-145376.OOzSOh.rst | 2 - ...-03-02-20-08-09.gh-issue-145335.lVTBvd.rst | 5 - ...-03-03-11-49-44.gh-issue-145417.m_HxIL.rst | 4 - ...-03-05-16-06-09.gh-issue-141510.dFPAQS.rst | 2 - ...-03-05-19-01-28.gh-issue-145551.gItPRl.rst | 1 - ...-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst | 3 - ...-01-31-21-56-54.gh-issue-144370.fp9m8t.rst | 2 - ...-03-04-18-59-17.gh-issue-145506.6hwvEh.rst | 2 - ...-02-12-12-12-00.gh-issue-144739.-fx1tN.rst | 3 - ...-03-04-17-39-15.gh-issue-144741.0RHhBF.rst | 3 - ...-02-13-11-07-51.gh-issue-144551.ENtMYD.rst | 1 - ...-02-27-10-57-20.gh-issue-145307.ueoT7j.rst | 2 - ...-03-10-09-46-44.gh-issue-145731.5uEGgb.rst | 1 - README.rst | 2 +- 146 files changed, 1512 insertions(+), 453 deletions(-) create mode 100644 Misc/NEWS.d/3.15.0a7.rst delete mode 100644 Misc/NEWS.d/next/Build/2025-07-21-00-33-38.gh-issue-136677.Y1_3ec.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-02-10-16-59-56.gh-issue-144675.Wrf3Es.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-02-10-18-26-04.gh-issue-144679.FIH73W.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-02-22-13-35-20.gh-issue-145110.KgWofW.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-02-27-18-10-02.gh-issue-144533.21fk9L.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-02-10-14-49-49.gh-issue-121617.57vMqa.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-02-12-19-03-31.gh-issue-141510.U_1tjz.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-02-18-15-12-34.gh-issue-144981.4ZdM63.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-02-24-14-46-05.gh-issue-144748.uhnFtE.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-03-03-14-59-57.gh-issue-142417.HiNP5j.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2023-07-26-00-03-00.gh-issue-80667.N7Dh8B.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-02-19-21-06-30.gh-issue-130327.z3TaR8.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-09-15-13-28-48.gh-issue-138912.61EYbn.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-11-09-15-44-58.gh-issue-141226.KTb_3F.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-12-06-15-46-32.gh-issue-142349.IdTuYL.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-06-21-45-52.gh-issue-144438.GI_uB1LR.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-13-14-00.gh-issue-144569.pjlJVe.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-11-28-25.gh-issue-144702.XjFumv.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-13-30-11.gh-issue-143300.yjB63-.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-19-01-13.gh-issue-141510.KlKjZg.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-12-00-00.gh-issue-144759.d3qYpe.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-18-30-59.gh-issue-144766.JGu3x3.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-16-12-28-43.gh-issue-144872.k9_Q30.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-18-27-28.gh-issue-144914.DcXO4m.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-21-04-03.gh-issue-100239.LyVabQ.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-22-27-11.gh-issue-141510.-4yYsf.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-18-21-44-39.gh-issue-141510.7LST2O.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-09-47-45.gh-issue-145058.e-RBw-.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-07-51-10.gh-issue-145064.iIMGKA.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-20-15-00.gh-issue-144015.pystrhex_simd.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-22-05-09.gh-issue-145118.TaKMJE.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-23-23-18-28.gh-issue-145142.T-XbVe.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-24-18-30-56.gh-issue-145187.YjPu1Z.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-12-00-00.gh-issue-130555.TMSOIu.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-18-00-00.gh-issue-145241.hL2k9Q.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-20-51-54.gh-issue-145273.B5QcUp.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-07-38.gh-issue-145275.qE-3O1.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-36-00.gh-issue-145234.w0mQ9n.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-16-46-17.gh-issue-145376.lG5u1a.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2025-08-02-18-59-01.gh-issue-136246.RIK7nE.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2026-03-03-08-18-00.gh-issue-145450.VI7GXj.rst delete mode 100644 Misc/NEWS.d/next/Library/2017-12-15-09-32-57.bpo-32234.XaOkhR.rst delete mode 100644 Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst delete mode 100644 Misc/NEWS.d/next/Library/2020-04-07-05-09-34.bpo-40212.oPYeBs.rst delete mode 100644 Misc/NEWS.d/next/Library/2020-04-10-14-29-53.bpo-40243.85HRib.rst delete mode 100644 Misc/NEWS.d/next/Library/2022-02-05-00-15-03.bpo-42353.0ebVGG.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-02-05-20-02-30.gh-issue-80667.7LmzeA.rst delete mode 100644 Misc/NEWS.d/next/Library/2024-09-30-15-31-59.gh-issue-124748.KYzYFp.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-06-24-19-07-18.gh-issue-135883.38cePA.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-08-04-23-20-43.gh-issue-137335.IIjDJN.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-10-10-14-08-58.gh-issue-139899.09leRY.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-12-06-16-14-18.gh-issue-142352.pW5HLX88.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-12-16-13-34-48.gh-issue-142787.wNitJX.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-12-18-00-14-16.gh-issue-142781.gcOeYF.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-01-05-26-00.gh-issue-143304.Kv7x9Q.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-10-22-58-30.gh-issue-85809.0eW4wt.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-11-13-03-32.gh-issue-142516.u7An-s.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-11-16-59-22.gh-issue-143698.b-Cpeb.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-11-18-35-52.gh-issue-143698.gXDzsJ.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-03-19-57-41.gh-issue-144316.wop870.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-07-16-31-42.gh-issue-144285.iyH9iL.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-07-16-37-42.gh-issue-144475.8tFEXw.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-08-17-09-10.gh-issue-144321.w58PhQ.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-09-02-16-36.gh-issue-144615.s04x4n.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-10-16-56-05.gh-issue-66305.PZ6GN8.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-10-22-05-51.gh-issue-144156.UbrC7F.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-12-17-56-17.gh-issue-117865.jE1ema.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-13-00-00-00.gh-issue-142224.BidiMissing.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-13-11-14-18.gh-issue-144763.cDwnEE.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-14-14-56-44.gh-issue-140715.AbSheM.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-15-00-00-00.gh-issue-144833.TUelo1.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-15-12-02-20.gh-issue-144835.w_oS_J.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-17-11-15-17.gh-issue-141510.ZmqEUb.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-18-00-00-00.gh-issue-144809.nYpEUx.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-18-13-45-00.gh-issue-144777.R97q0a.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-00-00-00.gh-issue-144986.atexit-leak.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-10-57-40.gh-issue-88091.N7qGV-.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-16-26-08.gh-issue-141510.4Qxy8_.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-17-50-47.gh-issue-145006.9gqA0Q.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-18-02-54.gh-issue-141510.qzvYsO.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-20-54-25.gh-issue-145033.X9EBPQ.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-20-13-03-10.gh-issue-66802.OYcAi_.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-23-20-52-55.gh-issue-145158.vWJtxI.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-27-18-04-51.gh-issue-76007.17idfK.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-02-20-08-09.gh-issue-145335.lVTBvd.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst delete mode 100644 Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst delete mode 100644 Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst delete mode 100644 Misc/NEWS.d/next/Tests/2026-02-12-12-12-00.gh-issue-144739.-fx1tN.rst delete mode 100644 Misc/NEWS.d/next/Tests/2026-03-04-17-39-15.gh-issue-144741.0RHhBF.rst delete mode 100644 Misc/NEWS.d/next/Windows/2026-02-13-11-07-51.gh-issue-144551.ENtMYD.rst delete mode 100644 Misc/NEWS.d/next/Windows/2026-02-27-10-57-20.gh-issue-145307.ueoT7j.rst delete mode 100644 Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index 4a3a6347239..58456a36b96 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -524,7 +524,7 @@ API Functions Returns true on success; on failure, it returns false and raises the appropriate exception. - .. versionadded:: next + .. versionadded:: 3.15 .. c:function:: int PyArg_ParseArrayAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, const char *format, const char * const *kwlist, ...) @@ -535,7 +535,7 @@ API Functions Returns true on success; on failure, it returns false and raises the appropriate exception. - .. versionadded:: next + .. versionadded:: 3.15 .. c:function:: int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 371761573e9..d63c2686589 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -495,7 +495,7 @@ Dictionary view objects Frozen dictionary objects ^^^^^^^^^^^^^^^^^^^^^^^^^ -.. versionadded:: next +.. versionadded:: 3.15 .. c:var:: PyTypeObject PyFrozenDict_Type diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index aef191d3a29..8ecd7c62517 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -716,7 +716,7 @@ Signal Handling This function may now execute a remote debugger script, if remote debugging is enabled. - .. versionchanged:: next + .. versionchanged:: 3.15 The exception set by :c:func:`PyThreadState_SetAsyncExc` is now raised. diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index 04b5adb9a8f..367490732b9 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -350,14 +350,14 @@ Importing Modules Gets the current lazy imports mode. - .. versionadded:: next + .. versionadded:: 3.15 .. c:function:: PyObject* PyImport_GetLazyImportsFilter() Return a :term:`strong reference` to the current lazy imports filter, or ``NULL`` if none exists. This function always succeeds. - .. versionadded:: next + .. versionadded:: 3.15 .. c:function:: int PyImport_SetLazyImportsMode(PyImport_LazyImportsMode mode) @@ -366,7 +366,7 @@ Importing Modules This function always returns ``0``. - .. versionadded:: next + .. versionadded:: 3.15 .. c:function:: int PyImport_SetLazyImportsFilter(PyObject *filter) @@ -377,7 +377,7 @@ Importing Modules Return ``0`` on success and ``-1`` with an exception set otherwise. - .. versionadded:: next + .. versionadded:: 3.15 .. c:type:: PyImport_LazyImportsMode @@ -396,7 +396,7 @@ Importing Modules Disable lazy imports entirely. Even explicit ``lazy`` statements become eager imports. - .. versionadded:: next + .. versionadded:: 3.15 .. c:function:: PyObject* PyImport_CreateModuleFromInitfunc(PyObject *spec, PyObject* (*initfunc)(void)) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index f71bfebdb2a..15a4b55eab8 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -817,4 +817,4 @@ Object Protocol Returns 1 if the object was made immortal and returns 0 if it was not. This function cannot fail. - .. versionadded:: next + .. versionadded:: 3.15 diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 447f05e67d8..fd8e0c0bea1 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -330,7 +330,7 @@ Module contents :attr:`!C.t` will be ``20``, and the class attributes :attr:`!C.x` and :attr:`!C.y` will not be set. - .. versionchanged:: next + .. versionchanged:: 3.15 If *metadata* is ``None``, use an empty :class:`frozendict`, instead of a :func:`~types.MappingProxyType` of an empty :class:`dict`. diff --git a/Doc/library/email.headerregistry.rst b/Doc/library/email.headerregistry.rst index 8dfcd492f0a..c6924a0ac29 100644 --- a/Doc/library/email.headerregistry.rst +++ b/Doc/library/email.headerregistry.rst @@ -266,7 +266,7 @@ variant, :attr:`~.BaseHeader.max_count` is set to 1. A dictionary mapping parameter names to parameter values. - .. versionchanged:: next + .. versionchanged:: 3.15 It is now a :class:`frozendict` instead of a :class:`types.MappingProxyType`. diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index 33f37bdf1fc..3db3c7a1350 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -271,7 +271,7 @@ The following exceptions are the exceptions that are usually raised. A subclass of :exc:`ImportError` which is raised when a lazy import fails because it (directly or indirectly) tries to import itself. - .. versionadded:: next + .. versionadded:: 3.15 .. exception:: IndexError diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index af53b57dc9d..1d83cb6f2bb 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -660,7 +660,7 @@ are always available. They are listed here in alphabetical order. The semantics of the default *locals* namespace have been adjusted as described for the :func:`locals` builtin. - .. versionchanged:: next + .. versionchanged:: 3.15 *globals* can now be a :class:`frozendict`. @@ -741,7 +741,7 @@ are always available. They are listed here in alphabetical order. The semantics of the default *locals* namespace have been adjusted as described for the :func:`locals` builtin. - .. versionchanged:: next + .. versionchanged:: 3.15 *globals* can now be a :class:`frozendict`. @@ -2099,7 +2099,7 @@ are always available. They are listed here in alphabetical order. Subclasses of :class:`!type` which don't override ``type.__new__`` may no longer use the one-argument form to get the type of an object. - .. versionchanged:: next + .. versionchanged:: 3.15 *dict* can now be a :class:`frozendict`. diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index d5036a0fe75..785f6c614b4 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -292,7 +292,7 @@ ABC hierarchy:: instead of a :class:`list` or other :class:`collection ` type. - .. versionadded:: next + .. versionadded:: 3.15 .. class:: PathEntryFinder @@ -346,7 +346,7 @@ ABC hierarchy:: instead of a :class:`list` or other :class:`collection ` type. - .. versionadded:: next + .. versionadded:: 3.15 .. class:: Loader diff --git a/Doc/library/mailbox.rst b/Doc/library/mailbox.rst index b9a55a03dc8..5b9741bdbca 100644 --- a/Doc/library/mailbox.rst +++ b/Doc/library/mailbox.rst @@ -80,7 +80,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF. returns the mailbox object as the context object, and at context end calls :meth:`close`, thereby releasing the lock. - .. versionchanged:: next + .. versionchanged:: 3.15 Support for the :keyword:`with` statement was added. :class:`!Mailbox` instances have the following methods: diff --git a/Doc/library/marshal.rst b/Doc/library/marshal.rst index 25902622b87..4fe34f0a3a3 100644 --- a/Doc/library/marshal.rst +++ b/Doc/library/marshal.rst @@ -72,7 +72,7 @@ this module. The following types are supported: Added format version 5, which allows marshalling slices. -.. versionchanged:: next +.. versionchanged:: 3.15 Added format version 6, which allows marshalling :class:`frozendict`. diff --git a/Doc/library/os.rst b/Doc/library/os.rst index a22afdec516..940d04ccc92 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2409,7 +2409,7 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. - .. versionchanged:: next + .. versionchanged:: 3.15 ``os.listdir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than listing the current directory. @@ -2943,7 +2943,7 @@ features: .. versionchanged:: 3.7 Added support for :ref:`file descriptors ` on Unix. - .. versionchanged:: next + .. versionchanged:: 3.15 ``os.scandir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than listing the current directory. @@ -4582,7 +4582,7 @@ These functions are all available on Linux only. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. - .. versionchanged:: next + .. versionchanged:: 3.15 ``os.listxattr(-1)`` now fails with ``OSError(errno.EBADF)`` rather than listing extended attributes of the current directory. diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 7edb85ca507..43fb7295876 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -954,7 +954,7 @@ Functions :func:`~re.match`. Use that name when you need to retain compatibility with older Python versions. - .. versionchanged:: next + .. versionchanged:: 3.15 The alternate :func:`~re.prefixmatch` name of this API was added as a more explicitly descriptive name than :func:`~re.match`. Use it to better express intent. The norm in other languages and regular expression @@ -1309,7 +1309,7 @@ Regular Expression Objects :meth:`~Pattern.match`. Use that name when you need to retain compatibility with older Python versions. - .. versionchanged:: next + .. versionchanged:: 3.15 The alternate :meth:`~Pattern.prefixmatch` name of this API was added as a more explicitly descriptive name than :meth:`~Pattern.match`. Use it to better express intent. The norm in other languages and regular expression @@ -1781,7 +1781,7 @@ We **do not** plan to deprecate and remove the older *match* name, as it has been used in code for over 30 years. Code supporting older versions of Python should continue to use *match*. -.. versionadded:: next +.. versionadded:: 3.15 Making a Phonebook ^^^^^^^^^^^^^^^^^^ diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 0666fcfde61..d289ba58c24 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -669,7 +669,7 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. This function is now made thread-safe during creation of standard ``.zip`` and tar archives. - .. versionchanged:: next + .. versionchanged:: 3.15 Accepts a :term:`path-like object` for *base_name*, *root_dir* and *base_dir*. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index c930b876b3c..e16954b12a6 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2385,7 +2385,7 @@ expression support in the :mod:`re` module). the same position in *to*. If there is a third argument, it must be a string, whose characters will be mapped to ``None`` in the result. - .. versionchanged:: next + .. versionchanged:: 3.15 *dict* can now be a :class:`frozendict`. @@ -5665,7 +5665,7 @@ Frozen dictionaries :class:`!frozendict` is not a :class:`!dict` subclass but inherits directly from ``object``. - .. versionadded:: next + .. versionadded:: 3.15 .. _typecontextmanager: diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 4c76feafc9b..b1461b0cbaf 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -924,7 +924,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only See also :func:`set_lazy_imports` and :pep:`810`. - .. versionadded:: next + .. versionadded:: 3.15 .. function:: get_lazy_imports_filter() @@ -937,7 +937,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only :func:`set_lazy_imports_filter` for details on the filter function signature. - .. versionadded:: next + .. versionadded:: 3.15 .. function:: getrefcount(object) @@ -1770,7 +1770,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only See also :func:`get_lazy_imports` and :pep:`810`. - .. versionadded:: next + .. versionadded:: 3.15 .. function:: set_lazy_imports_filter(filter) @@ -1800,7 +1800,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only See also :func:`get_lazy_imports_filter` and :pep:`810`. - .. versionadded:: next + .. versionadded:: 3.15 .. function:: setprofile(profilefunc) diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 01f4df3c890..74898baa521 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -350,7 +350,7 @@ Standard names are defined for the following types: actually accessed. This type can be used to detect lazy imports programmatically. - .. versionadded:: next + .. versionadded:: 3.15 .. seealso:: :pep:`810` diff --git a/Doc/library/unicodedata.rst b/Doc/library/unicodedata.rst index d5f0405efbe..f5c11fd849f 100644 --- a/Doc/library/unicodedata.rst +++ b/Doc/library/unicodedata.rst @@ -139,7 +139,7 @@ following functions: >>> unicodedata.block('S') 'Basic Latin' - .. versionadded:: next + .. versionadded:: 3.15 .. function:: mirrored(chr, /) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 45abf5b1e73..919d4c595bf 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -702,7 +702,7 @@ Functions attributes. *extra* contains additional attributes, given as keyword arguments. Returns an element instance. - .. versionchanged:: next + .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. @@ -890,7 +890,7 @@ Element Objects an optional dictionary, containing element attributes. *extra* contains additional attributes, given as keyword arguments. - .. versionchanged:: next + .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 5c931683db1..ae541680c53 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -469,7 +469,7 @@ identifier names. .. versionchanged:: 3.12 ``type`` is now a soft keyword. -.. versionchanged:: next +.. versionchanged:: 3.15 ``lazy`` is now a soft keyword. .. index:: diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 9ada6f04784..9b84c2e9ac7 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -918,7 +918,7 @@ used, not at the import statement itself. See :pep:`810` for the full specification of lazy imports. -.. versionadded:: next +.. versionadded:: 3.15 .. _future: diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index cc3d2f154ed..5c3d44395c0 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -692,7 +692,7 @@ Miscellaneous options If false (``0``) suppress these warnings. Set to true by default. See also :envvar:`PYTHON_PATHCONFIG_WARNINGS`. - .. versionadded:: next + .. versionadded:: 3.15 * :samp:`-X tlbc={0,1}` enables (1, the default) or disables (0) thread-local bytecode in builds configured with :option:`--disable-gil`. When disabled, @@ -707,7 +707,7 @@ Miscellaneous options (the default) respects the ``lazy`` keyword in source code. See also :envvar:`PYTHON_LAZY_IMPORTS`. - .. versionadded:: next + .. versionadded:: 3.15 It also allows passing arbitrary values and retrieving them through the :data:`sys._xoptions` dictionary. @@ -1367,7 +1367,7 @@ conflict. stderr. If false (``0``) suppress these warnings. Set to true by default. See also :option:`-X pathconfig_warnings<-X>`. - .. versionadded:: next + .. versionadded:: 3.15 .. envvar:: PYTHON_JIT @@ -1396,7 +1396,7 @@ conflict. See also the :option:`-X lazy_imports <-X>` command-line option. - .. versionadded:: next + .. versionadded:: 3.15 Debug-mode variables ~~~~~~~~~~~~~~~~~~~~ diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 50d5ac4a73c..3cc12a2b2d3 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -24,10 +24,10 @@ #define PY_MINOR_VERSION 15 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 6 +#define PY_RELEASE_SERIAL 7 /* Version as a string */ -#define PY_VERSION "3.15.0a6+" +#define PY_VERSION "3.15.0a7" /*--end constants--*/ diff --git a/Lib/pydoc_data/module_docs.py b/Lib/pydoc_data/module_docs.py index 76a2c18bdb2..314bef547f3 100644 --- a/Lib/pydoc_data/module_docs.py +++ b/Lib/pydoc_data/module_docs.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Wed Feb 11 14:22:57 2026 +# Autogenerated by Sphinx on Tue Mar 10 14:31:07 2026 # as part of the release process. module_docs = { diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index dc09c5fd47a..7dd9cfe2ff5 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Wed Feb 11 14:22:57 2026 +# Autogenerated by Sphinx on Tue Mar 10 14:31:07 2026 # as part of the release process. topics = { @@ -361,13 +361,12 @@ The following code: Is semantically equivalent to: - iter = (ITER) - iter = type(iter).__aiter__(iter) + iter = (ITER).__aiter__() running = True while running: try: - TARGET = await type(iter).__anext__(iter) + TARGET = await iter.__anext__() except StopAsyncIteration: running = False else: @@ -375,7 +374,8 @@ Is semantically equivalent to: else: SUITE2 -See also "__aiter__()" and "__anext__()" for details. +except that implicit special method lookup is used for "__aiter__()" +and "__anext__()". It is a "SyntaxError" to use an "async for" statement outside the body of a coroutine function. @@ -397,9 +397,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - aenter = type(manager).__aenter__ - aexit = type(manager).__aexit__ - value = await aenter(manager) + aenter = manager.__aenter__ + aexit = manager.__aexit__ + value = await aenter() hit_except = False try: @@ -407,13 +407,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not await aexit(manager, *sys.exc_info()): + if not await aexit(*sys.exc_info()): raise finally: if not hit_except: - await aexit(manager, None, None, None) + await aexit(None, None, None) -See also "__aenter__()" and "__aexit__()" for details. +except that implicit special method lookup is used for "__aenter__()" +and "__aexit__()". It is a "SyntaxError" to use an "async with" statement outside the body of a coroutine function. @@ -481,16 +482,34 @@ The transformation rule is defined as follows: 'atom-literals': r'''Literals ******** -Python supports string and bytes literals and various numeric -literals: +A *literal* is a textual representation of a value. Python supports +numeric, string and bytes literals. Format strings and template +strings are treated as string literals. + +Numeric literals consist of a single "NUMBER" token, which names an +integer, floating-point number, or an imaginary number. See the +Numeric literals section in Lexical analysis documentation for +details. + +String and bytes literals may consist of several tokens. See section +String literal concatenation for details. + +Note that negative and complex numbers, like "-3" or "3+4.2j", are +syntactically not literals, but unary or binary arithmetic operations +involving the "-" or "+" operator. + +Evaluation of a literal yields an object of the given type ("int", +"float", "complex", "str", "bytes", or "Template") with the given +value. The value may be approximated in the case of floating-point and +imaginary literals. + +The formal grammar for literals is: literal: strings | NUMBER -Evaluation of a literal yields an object of the given type (string, -bytes, integer, floating-point number, complex number) with the given -value. The value may be approximated in the case of floating-point -and imaginary (complex) literals. See section Literals for details. -See section String literal concatenation for details on "strings". + +Literals and object identity +============================ All literals correspond to immutable data types, and hence the object’s identity is less important than its value. Multiple @@ -498,21 +517,53 @@ evaluations of literals with the same value (either the same occurrence in the program text or a different occurrence) may obtain the same object or a different object with the same value. +CPython implementation detail: For example, in CPython, *small* +integers with the same value evaluate to the same object: + + >>> x = 7 + >>> y = 7 + >>> x is y + True + +However, large integers evaluate to different objects: + + >>> x = 123456789 + >>> y = 123456789 + >>> x is y + False + +This behavior may change in future versions of CPython. In particular, +the boundary between “small” and “large” integers has already changed +in the past.CPython will emit a "SyntaxWarning" when you compare +literals using "is": + + >>> x = 7 + >>> x is 7 + :1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? + True + +See When can I rely on identity tests with the is operator? for more +information. + +Template strings are immutable but may reference mutable objects as +"Interpolation" values. For the purposes of this section, two +t-strings have the “same value” if both their structure and the +*identity* of the values match. + +**CPython implementation detail:** Currently, each evaluation of a +template string results in a different object. + String literal concatenation ============================ -Multiple adjacent string or bytes literals (delimited by whitespace), -possibly using different quoting conventions, are allowed, and their -meaning is the same as their concatenation: +Multiple adjacent string or bytes literals, possibly using different +quoting conventions, are allowed, and their meaning is the same as +their concatenation: >>> "hello" 'world' "helloworld" -Formally: - - strings: ( STRING | fstring)+ | tstring+ - This feature is defined at the syntactical level, so it only works with literals. To concatenate string expressions at run time, the ‘+’ operator may be used: @@ -543,6 +594,10 @@ may only be combined with other template string literals: >>> t"Hello" t"{name}!" Template(strings=('Hello', '!'), interpolations=(...)) + +Formally: + + strings: (STRING | fstring)+ | tstring+ ''', 'attribute-access': r'''Customizing attribute access **************************** @@ -1007,7 +1062,7 @@ operation can be customized using the special "__floordiv__()" and The "%" (modulo) operator yields the remainder from the division of the first argument by the second. The numeric arguments are first -converted to a common type. A zero right argument raises the +converted to a common type. A zero right argument raises the "ZeroDivisionError" exception. The arguments may be floating-point numbers, e.g., "3.14%0.7" equals "0.34" (since "3.14" equals "4*0.7 + 0.34".) The modulo operator always yields a result with the same sign @@ -2229,9 +2284,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - enter = type(manager).__enter__ - exit = type(manager).__exit__ - value = enter(manager) + enter = manager.__enter__ + exit = manager.__exit__ + value = enter() hit_except = False try: @@ -2239,11 +2294,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not exit(manager, *sys.exc_info()): + if not exit(*sys.exc_info()): raise finally: if not hit_except: - exit(manager, None, None, None) + exit(None, None, None) + +except that implicit special method lookup is used for "__enter__()" +and "__exit__()". With more than one item, the context managers are processed as if multiple "with" statements were nested: @@ -3287,13 +3345,12 @@ The following code: Is semantically equivalent to: - iter = (ITER) - iter = type(iter).__aiter__(iter) + iter = (ITER).__aiter__() running = True while running: try: - TARGET = await type(iter).__anext__(iter) + TARGET = await iter.__anext__() except StopAsyncIteration: running = False else: @@ -3301,7 +3358,8 @@ Is semantically equivalent to: else: SUITE2 -See also "__aiter__()" and "__anext__()" for details. +except that implicit special method lookup is used for "__aiter__()" +and "__anext__()". It is a "SyntaxError" to use an "async for" statement outside the body of a coroutine function. @@ -3323,9 +3381,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - aenter = type(manager).__aenter__ - aexit = type(manager).__aexit__ - value = await aenter(manager) + aenter = manager.__aenter__ + aexit = manager.__aexit__ + value = await aenter() hit_except = False try: @@ -3333,13 +3391,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not await aexit(manager, *sys.exc_info()): + if not await aexit(*sys.exc_info()): raise finally: if not hit_except: - await aexit(manager, None, None, None) + await aexit(None, None, None) -See also "__aenter__()" and "__aexit__()" for details. +except that implicit special method lookup is used for "__aenter__()" +and "__aexit__()". It is a "SyntaxError" to use an "async with" statement outside the body of a coroutine function. @@ -3676,8 +3735,8 @@ less likely to be able to resolve annotations at runtime. * a class that inherits from any of the above - The standard library classes "dict", "frozendict" - and "types.MappingProxyType" are mappings. + The standard library classes "dict" and "types.MappingProxyType" + are mappings. [4] A string literal appearing as the first statement in the function body is transformed into the function’s "__doc__" attribute and @@ -3750,19 +3809,13 @@ starting the next loop cycle. When a description of an arithmetic operator below uses the phrase “the numeric arguments are converted to a common real type”, this -means that the operator implementation for built-in types works as -follows: +means that the operator implementation for built-in numeric types +works as described in the Numeric Types section of the standard +library documentation. -* If both arguments are complex numbers, no conversion is performed; - -* if either argument is a complex or a floating-point number, the - other is converted to a floating-point number; - -* otherwise, both must be integers and no conversion is necessary. - -Some additional rules apply for certain operators (e.g., a string as a -left argument to the ‘%’ operator). Extensions must define their own -conversion behavior. +Some additional rules apply for certain operators and non-numeric +operands (for example, a string as a left argument to the "%" +operator). Extensions must define their own conversion behavior. ''', 'customization': r'''Basic customization ******************* @@ -4056,7 +4109,7 @@ object.__hash__(self) intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst case performance of a dict insertion, *O*(*n*^2) complexity. See - http://ocert.org/advisories/ocert-2011-003.html for + https://ocert.org/advisories/ocert-2011-003.html for details.Changing hash values affects the iteration order of sets. Python has never made guarantees about this ordering (and it typically varies between 32-bit and 64-bit builds).See also @@ -4971,8 +5024,8 @@ the evaluation order of key and value was not well-defined. In CPython, the value was evaluated before the key. Starting with 3.8, the key is evaluated before the value, as proposed by **PEP 572**. -Changed in version 3.15.0a5 (unreleased): Unpacking with the "**" -operator is now allowed in dictionary comprehensions. +Changed in version 3.15: Unpacking with the "**" operator is now +allowed in dictionary comprehensions. ''', 'dynamic-features': r'''Interaction with dynamic features ********************************* @@ -6552,6 +6605,8 @@ as *soft keywords*: * "type", when used in the "type" statement. +* "lazy", when used before an "import" statement. + These syntactically act as keywords in their specific contexts, but this distinction is done at the parser level, not when tokenizing. @@ -6561,6 +6616,9 @@ identifier names. Changed in version 3.12: "type" is now a soft keyword. +Changed in version 3.15.0a6 (unreleased): "lazy" is now a soft +keyword. + Reserved classes of identifiers =============================== @@ -6770,10 +6828,10 @@ definition: 'import': r'''The "import" statement ********************** - import_stmt: "import" module ["as" identifier] ("," module ["as" identifier])* - | "from" relative_module "import" identifier ["as" identifier] + import_stmt: ["lazy"] "import" module ["as" identifier] ("," module ["as" identifier])* + | ["lazy"] "from" relative_module "import" identifier ["as" identifier] ("," identifier ["as" identifier])* - | "from" relative_module "import" "(" identifier ["as" identifier] + | ["lazy"] "from" relative_module "import" "(" identifier ["as" identifier] ("," identifier ["as" identifier])* [","] ")" | "from" relative_module "import" "*" module: (identifier ".")* identifier @@ -6885,6 +6943,48 @@ Raises an auditing event "import" with arguments "module", "filename", "sys.path", "sys.meta_path", "sys.path_hooks". +Lazy imports +============ + +The "lazy" keyword is a soft keyword that only has special meaning +when it appears immediately before an "import" or "from" statement. +When an import statement is preceded by the "lazy" keyword, the import +becomes *lazy*: the module is not loaded immediately at the import +statement. Instead, a lazy proxy object is created and bound to the +name. The actual module is loaded on first use of that name. + +Lazy imports are only permitted at module scope. Using "lazy" inside a +function, class body, or "try"/"except"/"finally" block raises a +"SyntaxError". Star imports cannot be lazy ("lazy from module import +*" is a syntax error), and future statements cannot be lazy. + +When using "lazy from ... import", each imported name is bound to a +lazy proxy object. The first access to any of these names triggers +loading of the entire module and resolves only that specific name to +its actual value. Other names remain as lazy proxies until they are +accessed. + +Example: + + lazy import json + import sys + + print('json' in sys.modules) # False - json module not yet loaded + + # First use triggers loading + result = json.dumps({"hello": "world"}) + + print('json' in sys.modules) # True - now loaded + +If an error occurs during module loading (such as "ImportError" or +"SyntaxError"), it is raised at the point where the lazy import is +first used, not at the import statement itself. + +See **PEP 810** for the full specification of lazy imports. + +Added in version 3.15.0a6 (unreleased). + + Future statements ================= @@ -7975,8 +8075,8 @@ the evaluation order for the operands): "-1**2" results in "-1". The power operator has the same semantics as the built-in "pow()" function, when called with two arguments: it yields its left argument -raised to the power of its right argument. The numeric arguments are -first converted to a common type, and the result is of that type. +raised to the power of its right argument. Numeric arguments are first +converted to a common type, and the result is of that type. For int operands, the result has the same type as the operands unless the second argument is negative; in that case, all arguments are @@ -8701,7 +8801,7 @@ object.__hash__(self) intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst case performance of a dict insertion, *O*(*n*^2) complexity. See - http://ocert.org/advisories/ocert-2011-003.html for + https://ocert.org/advisories/ocert-2011-003.html for details.Changing hash values affects the iteration order of sets. Python has never made guarantees about this ordering (and it typically varies between 32-bit and 64-bit builds).See also @@ -10312,16 +10412,14 @@ str.isalnum() "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()". For example: - .. doctest:: - - >>> 'abc123'.isalnum() - True - >>> 'abc123!@#'.isalnum() - False - >>> ''.isalnum() - False - >>> ' '.isalnum() - False + >>> 'abc123'.isalnum() + True + >>> 'abc123!@#'.isalnum() + False + >>> ''.isalnum() + False + >>> ' '.isalnum() + False str.isalpha() @@ -10575,6 +10673,9 @@ static str.maketrans(from, to, remove='', /) a third argument, it must be a string, whose characters will be mapped to "None" in the result. + Changed in version 3.15.0a6 (unreleased): *dict* can now be a + "frozendict". + str.partition(sep, /) Split the string at the first occurrence of *sep*, and return a @@ -10676,6 +10777,17 @@ str.rjust(width, fillchar=' ', /) space). The original string is returned if *width* is less than or equal to "len(s)". + For example: + + >>> 'Python'.rjust(10) + ' Python' + >>> 'Python'.rjust(10, '.') + '....Python' + >>> 'Monty Python'.rjust(10, '.') + 'Monty Python' + + See also "ljust()" and "zfill()". + str.rpartition(sep, /) Split the string at the last occurrence of *sep*, and return a @@ -10982,6 +11094,8 @@ str.zfill(width, /) '00042' >>> "-42".zfill(5) '-0042' + + See also "rjust()". ''', 'strings': '''String and Bytes literals ************************* @@ -13338,13 +13452,13 @@ different object types. See Function definitions for more information. ''', - 'typesmapping': r'''Mapping Types — "dict" -********************** + 'typesmapping': r'''Mapping types — "dict", "frozendict" +************************************ -A *mapping* object maps *hashable* values to arbitrary objects. -Mappings are mutable objects. There is currently only one standard -mapping type, the *dictionary*. (For other containers see the built- -in "list", "set", and "tuple" classes, and the "collections" module.) +A *mapping* object maps *hashable* values to arbitrary objects. There +are currently two standard mapping types, the *dictionary* and +"frozendict". (For other containers see the built-in "list", "set", +and "tuple" classes, and the "collections" module.) A dictionary’s keys are *almost* arbitrary values. Values that are not *hashable*, that is, values containing lists, dictionaries or @@ -13618,10 +13732,15 @@ class dict(iterable, /, **kwargs) Changed in version 3.8: Dictionaries are now reversible. + See also: + + "frozendict" and "types.MappingProxyType" can be used to create a + read-only view of a "dict". + See also: - "frozendict" and "types.MappingProxyType" can be used to create a read-only - view of a "dict". + For detailed information on thread-safety guarantees for "dict" + objects, see Thread safety for dict objects. Dictionary view objects @@ -13726,6 +13845,47 @@ An example of dictionary view usage: mappingproxy({'bacon': 1, 'spam': 500}) >>> values.mapping['spam'] 500 + + +Frozen dictionaries +=================== + +class frozendict(**kwargs) +class frozendict(mapping, /, **kwargs) +class frozendict(iterable, /, **kwargs) + + Return a new frozen dictionary initialized from an optional + positional argument and a possibly empty set of keyword arguments. + + A "frozendict" has a similar API to the "dict" API, with the + following differences: + + * "dict" has more methods than "frozendict": + + * "__delitem__()" + + * "__setitem__()" + + * "clear()" + + * "pop()" + + * "popitem()" + + * "setdefault()" + + * "update()" + + * A "frozendict" can be hashed with "hash(frozendict)" if all keys + and values can be hashed. + + * "frozendict |= other" does not modify the "frozendict" in-place + but creates a new frozen dictionary. + + "frozendict" is not a "dict" subclass but inherits directly from + "object". + + Added in version 3.15.0a6 (unreleased). ''', 'typesmethods': r'''Methods ******* @@ -14175,75 +14335,10 @@ class list(iterable=(), /) empty for the duration, and raises "ValueError" if it can detect that the list has been mutated during a sort. -Thread safety: Reading a single element from a "list" is *atomic*: +See also: - lst[i] # list.__getitem__ - -The following methods traverse the list and use *atomic* reads of each -item to perform their function. That means that they may return -results affected by concurrent modifications: - - item in lst - lst.index(item) - lst.count(item) - -All of the above methods/operations are also lock-free. They do not -block concurrent modifications. Other operations that hold a lock will -not block these from observing intermediate states.All other -operations from here on block using the per-object lock.Writing a -single item via "lst[i] = x" is safe to call from multiple threads and -will not corrupt the list.The following operations return new objects -and appear *atomic* to other threads: - - lst1 + lst2 # concatenates two lists into a new list - x * lst # repeats lst x times into a new list - lst.copy() # returns a shallow copy of the list - -Methods that only operate on a single elements with no shifting -required are *atomic*: - - lst.append(x) # append to the end of the list, no shifting required - lst.pop() # pop element from the end of the list, no shifting required - -The "clear()" method is also *atomic*. Other threads cannot observe -elements being removed.The "sort()" method is not *atomic*. Other -threads cannot observe intermediate states during sorting, but the -list appears empty for the duration of the sort.The following -operations may allow lock-free operations to observe intermediate -states since they modify multiple elements in place: - - lst.insert(idx, item) # shifts elements - lst.pop(idx) # idx not at the end of the list, shifts elements - lst *= x # copies elements in place - -The "remove()" method may allow concurrent modifications since element -comparison may execute arbitrary Python code (via -"__eq__()")."extend()" is safe to call from multiple threads. -However, its guarantees depend on the iterable passed to it. If it is -a "list", a "tuple", a "set", a "frozenset", a "dict" or a dictionary -view object (but not their subclasses), the "extend" operation is safe -from concurrent modifications to the iterable. Otherwise, an iterator -is created which can be concurrently modified by another thread. The -same applies to inplace concatenation of a list with other iterables -when using "lst += iterable".Similarly, assigning to a list slice with -"lst[i:j] = iterable" is safe to call from multiple threads, but -"iterable" is only locked when it is also a "list" (but not its -subclasses).Operations that involve multiple accesses, as well as -iteration, are never atomic. For example: - - # NOT atomic: read-modify-write - lst[i] = lst[i] + 1 - - # NOT atomic: check-then-act - if lst: - item = lst.pop() - - # NOT thread-safe: iteration while modifying - for item in lst: - process(item) # another thread may modify lst - -Consider external synchronization when sharing "list" instances across -threads. See Python support for free threading for more information. + For detailed information on thread-safety guarantees for "list" + objects, see Thread safety for list objects. Tuples @@ -14615,9 +14710,9 @@ The following code: is semantically equivalent to: manager = (EXPRESSION) - enter = type(manager).__enter__ - exit = type(manager).__exit__ - value = enter(manager) + enter = manager.__enter__ + exit = manager.__exit__ + value = enter() hit_except = False try: @@ -14625,11 +14720,14 @@ is semantically equivalent to: SUITE except: hit_except = True - if not exit(manager, *sys.exc_info()): + if not exit(*sys.exc_info()): raise finally: if not hit_except: - exit(manager, None, None, None) + exit(None, None, None) + +except that implicit special method lookup is used for "__enter__()" +and "__exit__()". With more than one item, the context managers are processed as if multiple "with" statements were nested: diff --git a/Misc/NEWS.d/3.15.0a7.rst b/Misc/NEWS.d/3.15.0a7.rst new file mode 100644 index 00000000000..7d9681cbcbe --- /dev/null +++ b/Misc/NEWS.d/3.15.0a7.rst @@ -0,0 +1,1212 @@ +.. date: 2026-03-10-09-46-44 +.. gh-issue: 145731 +.. nonce: 5uEGgb +.. release date: 2026-03-10 +.. section: Windows + +Fix negative timestamp during DST on Windows. Patch by Hugo van Kemenade. + +.. + +.. date: 2026-02-27-10-57-20 +.. gh-issue: 145307 +.. nonce: ueoT7j +.. section: Windows + +Defers loading of the ``psapi.dll`` module until it is used by +:func:`ctypes.util.dllist`. + +.. + +.. date: 2026-02-13-11-07-51 +.. gh-issue: 144551 +.. nonce: ENtMYD +.. section: Windows + +Updated bundled version of OpenSSL to 3.5.5. + +.. + +.. date: 2026-03-04-17-39-15 +.. gh-issue: 144741 +.. nonce: 0RHhBF +.. section: Tests + +Fix ``test_frame_pointer_unwind`` when Python is built with +:option:`--enable-shared`. Classify also libpython frames as ``"python"``. +Patch by Victor Stinner. + +.. + +.. date: 2026-02-12-12-12-00 +.. gh-issue: 144739 +.. nonce: -fx1tN +.. section: Tests + +When Python was compiled with system expat older then 2.7.2 but tests run +with newer expat, still skip +:class:`!test.test_pyexpat.MemoryProtectionTest`. + +.. + +.. date: 2026-03-04-18-59-17 +.. gh-issue: 145506 +.. nonce: 6hwvEh +.. section: Security + +Fixes :cve:`2026-2297` by ensuring that ``SourcelessFileLoader`` uses +:func:`io.open_code` when opening ``.pyc`` files. + +.. + +.. date: 2026-01-31-21-56-54 +.. gh-issue: 144370 +.. nonce: fp9m8t +.. section: Security + +Disallow usage of control characters in status in :mod:`wsgiref.handlers` to +prevent HTTP header injections. Patch by Benedikt Johannes. + +.. + +.. date: 2026-03-07-15-00-00 +.. gh-issue: 145623 +.. nonce: 2Y7LzT +.. section: Library + +Fix crash in :mod:`struct` when calling :func:`repr` or ``__sizeof__()`` on +an uninitialized :class:`struct.Struct` object created via +``Struct.__new__()`` without calling ``__init__()``. + +.. + +.. date: 2026-03-05-19-01-28 +.. gh-issue: 145551 +.. nonce: gItPRl +.. section: Library + +Fix InvalidStateError when cancelling process created by +:func:`asyncio.create_subprocess_exec` or +:func:`asyncio.create_subprocess_shell`. Patch by Daan De Meyer. + +.. + +.. date: 2026-03-05-16-06-09 +.. gh-issue: 141510 +.. nonce: dFPAQS +.. section: Library + +:mod:`marshal` now supports :class:`frozendict` objects. The marshal format +version was increased to 6. Patch by Victor Stinner. + +.. + +.. date: 2026-03-03-11-49-44 +.. gh-issue: 145417 +.. nonce: m_HxIL +.. section: Library + +:mod:`venv`: Prevent incorrect preservation of SELinux context when copying +the ``Activate.ps1`` script. The script inherited the SELinux security +context of the system template directory, rather than the destination +project directory. + +.. + +.. date: 2026-03-02-20-08-09 +.. gh-issue: 145335 +.. nonce: lVTBvd +.. section: Library + +``os.listdir(-1)`` and ``os.scandir(-1)`` now fail with +``OSError(errno.EBADF)`` rather than listing the current directory. +``os.listxattr(-1)`` now fails with ``OSError(errno.EBADF)`` rather than +listing extended attributes of the current directory. Patch by Victor +Stinner. + +.. + +.. date: 2026-03-02-19-41-39 +.. gh-issue: 145376 +.. nonce: OOzSOh +.. section: Library + +Fix double free and null pointer dereference in unusual error scenarios in +:mod:`hashlib` and :mod:`hmac` modules. + +.. + +.. date: 2026-02-28-00-55-00 +.. gh-issue: 145301 +.. nonce: Lk2bRl +.. section: Library + +:mod:`hmac`: fix a crash when the initialization of the underlying C +extension module fails. + +.. + +.. date: 2026-02-27-19-00-26 +.. gh-issue: 145301 +.. nonce: 2Wih4b +.. section: Library + +:mod:`hashlib`: fix a crash when the initialization of the underlying C +extension module fails. + +.. + +.. date: 2026-02-27-18-04-51 +.. gh-issue: 76007 +.. nonce: 17idfK +.. section: Library + +The ``version`` attribute of the :mod:`tarfile` module is deprecated and +slated for removal in Python 3.20. + +.. + +.. date: 2026-02-23-20-52-55 +.. gh-issue: 145158 +.. nonce: vWJtxI +.. section: Library + +Avoid undefined behaviour from signed integer overflow when parsing format +strings in the :mod:`struct` module. + +.. + +.. date: 2026-02-21-17-34-53 +.. gh-issue: 123853 +.. nonce: 6RUwWh +.. section: Library + +Removed Windows 95 compatibility for :func:`locale.getdefaultlocale`. + +.. + +.. date: 2026-02-20-13-03-10 +.. gh-issue: 66802 +.. nonce: OYcAi_ +.. section: Library + +Add :func:`unicodedata.block` function to return the `Unicode block +`_ +of a character. + +.. + +.. date: 2026-02-19-20-54-25 +.. gh-issue: 145033 +.. nonce: X9EBPQ +.. section: Library + +Add :data:`typing.TypeForm`, implementing :pep:`747`. Patch by Jelle +Zijlstra. + +.. + +.. date: 2026-02-19-18-02-54 +.. gh-issue: 141510 +.. nonce: qzvYsO +.. section: Library + +:func:`dataclasses.field`: if *metadata* is ``None``, use an empty +:class:`frozendict`, instead of a :func:`~types.MappingProxyType` of an +empty :class:`dict`. Patch by Victor Stinner. + +.. + +.. date: 2026-02-19-17-50-47 +.. gh-issue: 145006 +.. nonce: 9gqA0Q +.. section: Library + +Add :exc:`ModuleNotFoundError` hints when a module for a different ABI +exists. + +.. + +.. date: 2026-02-19-16-26-08 +.. gh-issue: 141510 +.. nonce: 4Qxy8_ +.. section: Library + +``ParameterizedMIMEHeader.params`` of :mod:`email.headerregistry` is now a +:class:`frozendict` instead of a :class:`types.MappingProxyType`. Patch by +Victor Stinner. + +.. + +.. date: 2026-02-19-15-42-06 +.. gh-issue: 134872 +.. nonce: sjYX1- +.. section: Library + +Add valid import name suggestions on :exc:`ModuleNotFoundError`. + +.. + +.. date: 2026-02-19-10-57-40 +.. gh-issue: 88091 +.. nonce: N7qGV- +.. section: Library + +Fix :func:`unicodedata.decomposition` for Hangul characters. + +.. + +.. date: 2026-02-19-00-00-00 +.. gh-issue: 144986 +.. nonce: atexit-leak +.. section: Library + +Fix a memory leak in :func:`atexit.register`. Patch by Shamil Abdulaev. + +.. + +.. date: 2026-02-18-13-45-00 +.. gh-issue: 144777 +.. nonce: R97q0a +.. section: Library + +Fix data races in :class:`io.IncrementalNewlineDecoder` in the +:term:`free-threaded build`. + +.. + +.. date: 2026-02-18-00-00-00 +.. gh-issue: 144809 +.. nonce: nYpEUx +.. section: Library + +Make :class:`collections.deque` copy atomic in the :term:`free-threaded +build`. + +.. + +.. date: 2026-02-17-11-28-37 +.. gh-issue: 141510 +.. nonce: OpAz0M +.. section: Library + +The :mod:`copy` module now supports the :class:`frozendict` type. Patch by +Pieter Eendebak based on work by Victor Stinner. + +.. + +.. date: 2026-02-17-11-15-17 +.. gh-issue: 141510 +.. nonce: ZmqEUb +.. section: Library + +The :mod:`json` module now supports the :class:`frozendict` type. Patch by +Victor Stinner. + +.. + +.. date: 2026-02-15-12-02-20 +.. gh-issue: 144835 +.. nonce: w_oS_J +.. section: Library + +Added missing explanations for some parameters in :func:`glob.glob` and +:func:`glob.iglob`. + +.. + +.. date: 2026-02-15-00-00-00 +.. gh-issue: 144833 +.. nonce: TUelo1 +.. section: Library + +Fixed a use-after-free in :mod:`ssl` when ``SSL_new()`` returns NULL in +``newPySSLSocket()``. The error was reported via a dangling pointer after +the object had already been freed. + +.. + +.. date: 2026-02-14-14-56-44 +.. gh-issue: 140715 +.. nonce: AbSheM +.. section: Library + +Add ``'%D'`` support to :meth:`~datetime.datetime.strptime`. + +.. + +.. date: 2026-02-13-14-20-10 +.. gh-issue: 144782 +.. nonce: 0Y8TKj +.. section: Library + +Fix :class:`argparse.ArgumentParser` to be :mod:`pickleable `. + +.. + +.. date: 2026-02-13-11-14-18 +.. gh-issue: 144763 +.. nonce: cDwnEE +.. section: Library + +Fix a race condition in :mod:`tracemalloc`: it no longer detaches the +attached thread state to acquire its internal lock. Patch by Victor Stinner. + +.. + +.. date: 2026-02-13-00-00-00 +.. gh-issue: 142224 +.. nonce: BidiMissing +.. section: Library + +:func:`unicodedata.bidirectional` now return the correct default bidi class +for unassigned code points. + +.. + +.. date: 2026-02-12-17-56-17 +.. gh-issue: 117865 +.. nonce: jE1ema +.. section: Library + +Reduce the import time of :mod:`inspect` module by ~20%. + +.. + +.. date: 2026-02-10-22-05-51 +.. gh-issue: 144156 +.. nonce: UbrC7F +.. section: Library + +Fix the folding of headers by the :mod:`email` library when :rfc:`2047` +encoded words are used. Now whitespace is correctly preserved and also +correctly added between adjacent encoded words. The latter property was +broken by the fix for gh-92081, which mostly fixed previous failures to +preserve whitespace. + +.. + +.. date: 2026-02-10-16-56-05 +.. gh-issue: 66305 +.. nonce: PZ6GN8 +.. section: Library + +Fixed a hang on Windows in the :mod:`tempfile` module when trying to create +a temporary file or subdirectory in a non-writable directory. + +.. + +.. date: 2026-02-09-02-16-36 +.. gh-issue: 144615 +.. nonce: s04x4n +.. section: Library + +Methods directly decorated with :deco:`functools.singledispatchmethod` now +dispatch on the second argument when called after being accessed as class +attributes. Patch by Bartosz Sławecki. + +.. + +.. date: 2026-02-08-17-09-10 +.. gh-issue: 144321 +.. nonce: w58PhQ +.. section: Library + +The functional syntax for creating :class:`typing.NamedTuple` classes now +supports passing any :term:`iterable` of fields and types. Previously, only +sequences were supported. + +.. + +.. date: 2026-02-07-16-37-42 +.. gh-issue: 144475 +.. nonce: 8tFEXw +.. section: Library + +Calling :func:`repr` on :func:`functools.partial` is now safer when the +partial object's internal attributes are replaced while the string +representation is being generated. + +.. + +.. date: 2026-02-07-16-31-42 +.. gh-issue: 144285 +.. nonce: iyH9iL +.. section: Library + +Attribute suggestions in :exc:`AttributeError` tracebacks are now formatted +differently to make them easier to understand, for example: ``Did you mean +'.datetime.now' instead of '.now'``. Contributed by Bartosz Sławecki. + +.. + +.. date: 2026-02-03-19-57-41 +.. gh-issue: 144316 +.. nonce: wop870 +.. section: Library + +Fix crash in ``_remote_debugging`` that caused ``test_external_inspection`` +to intermittently fail. Patch by Taegyun Kim. + +.. + +.. date: 2026-01-17-08-44-25 +.. gh-issue: 143637 +.. nonce: qyPqDo +.. section: Library + +Fixed a crash in socket.sendmsg() that could occur if ancillary data is +mutated re-entrantly during argument parsing. + +.. + +.. date: 2026-01-12-19-39-57 +.. gh-issue: 140652 +.. nonce: HvM9Bl +.. section: Library + +Fix a crash in :func:`!_interpchannels.list_all` after closing a channel. + +.. + +.. date: 2026-01-11-18-35-52 +.. gh-issue: 143698 +.. nonce: gXDzsJ +.. section: Library + +Allow *scheduler* and *setpgroup* arguments to be explicitly :const:`None` +when calling :func:`os.posix_spawn` or :func:`os.posix_spawnp`. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-01-11-16-59-22 +.. gh-issue: 143698 +.. nonce: b-Cpeb +.. section: Library + +Raise :exc:`TypeError` instead of :exc:`SystemError` when the *scheduler* in +:func:`os.posix_spawn` or :func:`os.posix_spawnp` is not a tuple. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-01-11-13-03-32 +.. gh-issue: 142516 +.. nonce: u7An-s +.. section: Library + +:mod:`ssl`: fix reference leaks in :class:`ssl.SSLContext` objects. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-01-10-22-58-30 +.. gh-issue: 85809 +.. nonce: 0eW4wt +.. section: Library + +Added :term:`path-like object` support for :func:`shutil.make_archive`. + +.. + +.. date: 2026-01-01-05-26-00 +.. gh-issue: 143304 +.. nonce: Kv7x9Q +.. section: Library + +Fix :class:`ctypes.CDLL` to honor the ``handle`` parameter on POSIX systems. + +.. + +.. date: 2025-12-18-00-14-16 +.. gh-issue: 142781 +.. nonce: gcOeYF +.. section: Library + +:mod:`zoneinfo`: fix a crash when instantiating :class:`~zoneinfo.ZoneInfo` +objects for which the internal class-level cache is inconsistent. + +.. + +.. date: 2025-12-16-13-34-48 +.. gh-issue: 142787 +.. nonce: wNitJX +.. section: Library + +Fix assertion failure in :mod:`sqlite3` blob subscript when slicing with +indices that result in an empty slice. + +.. + +.. date: 2025-12-06-16-14-18 +.. gh-issue: 142352 +.. nonce: pW5HLX88 +.. section: Library + +Fix :meth:`asyncio.StreamWriter.start_tls` to transfer buffered data from +:class:`~asyncio.StreamReader` to the SSL layer, preventing data loss when +upgrading a connection to TLS mid-stream (e.g., when implementing PROXY +protocol support). + +.. + +.. date: 2025-10-10-14-08-58 +.. gh-issue: 139899 +.. nonce: 09leRY +.. section: Library + +Introduced :meth:`importlib.abc.MetaPathFinder.discover` and +:meth:`importlib.abc.PathEntryFinder.discover` to allow module and submodule +name discovery without assuming the use of traditional filesystem based +imports. + +.. + +.. date: 2025-08-04-23-20-43 +.. gh-issue: 137335 +.. nonce: IIjDJN +.. section: Library + +Get rid of any possibility of a name conflict for named pipes in +:mod:`multiprocessing` and :mod:`asyncio` on Windows, no matter how small. + +.. + +.. date: 2025-06-24-19-07-18 +.. gh-issue: 135883 +.. nonce: 38cePA +.. section: Library + +Fix :mod:`sqlite3`'s :ref:`interactive shell ` keeping part of +previous commands when scrolling history. + +.. + +.. date: 2024-09-30-15-31-59 +.. gh-issue: 124748 +.. nonce: KYzYFp +.. section: Library + +Improve :exc:`TypeError` error message when +:meth:`!weakref.WeakKeyDictionary.update` is used with keyword-only +parameters. + +.. + +.. date: 2023-02-05-20-02-30 +.. gh-issue: 80667 +.. nonce: 7LmzeA +.. section: Library + +Add support for Tangut Ideographs names in :mod:`unicodedata`. + +.. + +.. bpo: 42353 +.. date: 2022-02-05-00-15-03 +.. nonce: 0ebVGG +.. section: Library + +The :mod:`re` module gains a new :func:`re.prefixmatch` function as an +explicit spelling of what has to date always been known as :func:`re.match`. +:class:`re.Pattern` similary gains a :meth:`re.Pattern.prefixmatch` method. + +Why? Explicit is better than implicit. Other widely used languages all use +the term "match" to mean what Python uses the term "search" for. The +unadorened "match" name in Python has been a frequent case of confusion and +coding bugs due to the inconsistency with the rest if the software industry. + +We do not plan to deprecate and remove the older ``match`` name. + +.. + +.. bpo: 40243 +.. date: 2020-04-10-14-29-53 +.. nonce: 85HRib +.. section: Library + +Fix :meth:`!unicodedata.ucd_3_2_0.numeric` for non-decimal values. + +.. + +.. bpo: 40212 +.. date: 2020-04-07-05-09-34 +.. nonce: oPYeBs +.. section: Library + +Re-enable :func:`os.posix_fallocate` and :func:`os.posix_fadvise` on AIX. + +.. + +.. bpo: 3405 +.. date: 2018-05-11-12-26-16 +.. nonce: CacMw9 +.. section: Library + +Add support for user data of Tk virtual events and detail for ``Enter``, +``Leave``, ``FocusIn``, ``FocusOut``, and ``ConfigureRequest`` events to +:mod:`tkinter`. + +.. + +.. bpo: 32234 +.. date: 2017-12-15-09-32-57 +.. nonce: XaOkhR +.. section: Library + +:class:`mailbox.Mailbox` instances can now be used as a context manager. The +Mailbox is locked on context entry and unlocked and closed at context exit. + +.. + +.. date: 2026-03-03-08-18-00 +.. gh-issue: 145450 +.. nonce: VI7GXj +.. section: Documentation + +Document missing public :class:`wave.Wave_write` getter methods. + +.. + +.. date: 2026-01-06-16-04-08 +.. gh-issue: 110937 +.. nonce: SyO5lk +.. section: Documentation + +Document rest of full public :class:`importlib.metadata.Distribution` API. +Also add the (already documented) :class:`~importlib.metadata.PackagePath` +to ``__all__``. + +.. + +.. date: 2025-08-02-18-59-01 +.. gh-issue: 136246 +.. nonce: RIK7nE +.. section: Documentation + +A new "Improve this page" link is available in the left-hand sidebar of the +docs, offering links to create GitHub issues, discussion forum posts, or +pull requests. + +.. + +.. date: 2026-03-09-18-52-03 +.. gh-issue: 145701 +.. nonce: 79KQyO +.. section: Core and Builtins + +Fix :exc:`SystemError` when ``__classdict__`` or +``__conditional_annotations__`` is in a class-scope inlined comprehension. +Found by OSS Fuzz in :oss-fuzz:`491105000`. + +.. + +.. date: 2026-03-06-21-05-05 +.. gh-issue: 145615 +.. nonce: NKXXZgDW +.. section: Core and Builtins + +Fixed a memory leak in the :term:`free-threaded build` where mimalloc pages +could become permanently unreclaimable until the owning thread exited. + +.. + +.. date: 2026-03-06-01-36-20 +.. gh-issue: 116738 +.. nonce: OWVWRx +.. section: Core and Builtins + +Make :meth:`!mmap.mmap.set_name` thread-safe on the :term:`free threaded +` build. + +.. + +.. date: 2026-03-05-19-10-56 +.. gh-issue: 145566 +.. nonce: H4RupyYN +.. section: Core and Builtins + +In the free threading build, skip the stop-the-world pause when reassigning +``__class__`` on a newly created object. + +.. + +.. date: 2026-03-05-16-16-17 +.. gh-issue: 143055 +.. nonce: qDUFlY +.. section: Core and Builtins + +Fix crash in AST unparser when unparsing dict comprehension unpacking. Found +by OSS Fuzz in :oss-fuzz:`489790200`. + +.. + +.. date: 2026-03-01-13-37-31 +.. gh-issue: 145335 +.. nonce: e36kPJ +.. section: Core and Builtins + +Fix a crash in :func:`os.pathconf` when called with ``-1`` as the path +argument. + +.. + +.. date: 2026-02-28-16-46-17 +.. gh-issue: 145376 +.. nonce: lG5u1a +.. section: Core and Builtins + +Fix reference leaks in various unusual error scenarios. + +.. + +.. date: 2026-02-26-21-36-00 +.. gh-issue: 145234 +.. nonce: w0mQ9n +.. section: Core and Builtins + +Fixed a ``SystemError`` in the parser when an encoding cookie (for example, +UTF-7) decodes to carriage returns (``\r``). Newlines are now normalized +after decoding in the string tokenizer. + +Patch by Pablo Galindo. + +.. + +.. date: 2026-02-26-21-07-38 +.. gh-issue: 145275 +.. nonce: qE-3O1 +.. section: Core and Builtins + +Added the :option:`-X pathconfig_warnings<-X>` and +:envvar:`PYTHON_PATHCONFIG_WARNINGS` options, allowing to disable warnings +from :ref:`sys-path-init`. + +.. + +.. date: 2026-02-26-20-51-54 +.. gh-issue: 145273 +.. nonce: B5QcUp +.. section: Core and Builtins + +A warning is now shown during :ref:`sys-path-init` if it can't find a valid +standard library. + +.. + +.. date: 2026-02-26-18-00-00 +.. gh-issue: 145241 +.. nonce: hL2k9Q +.. section: Core and Builtins + +Specialized the parser error for when ``with`` items are followed by a +trailing comma (for example, ``with item,:``), raising a clearer +:exc:`SyntaxError` message. Patch by Pablo Galindo and Bartosz Sławecki. + +.. + +.. date: 2026-02-26-12-00-00 +.. gh-issue: 130555 +.. nonce: TMSOIu +.. section: Core and Builtins + +Fix use-after-free in :meth:`dict.clear` when the dictionary values are +embedded in an object and a destructor causes re-entrant mutation of the +dictionary. + +.. + +.. date: 2026-02-25-15-02-08 +.. gh-issue: 145197 +.. nonce: G6hAUk +.. section: Core and Builtins + +Fix JIT trace crash when recording function from cleared generator frame. + +.. + +.. date: 2026-02-24-18-30-56 +.. gh-issue: 145187 +.. nonce: YjPu1Z +.. section: Core and Builtins + +Fix compiler assertion fail when a type parameter bound contains an invalid +expression in a conditional block. + +.. + +.. date: 2026-02-23-23-18-28 +.. gh-issue: 145142 +.. nonce: T-XbVe +.. section: Core and Builtins + +Fix a crash in the free-threaded build when the dictionary argument to +:meth:`str.maketrans` is concurrently modified. + +.. + +.. date: 2026-02-22-22-05-09 +.. gh-issue: 145118 +.. nonce: TaKMJE +.. section: Core and Builtins + +:meth:`str.maketrans` now accepts :class:`frozendict`. + +.. + +.. date: 2026-02-22-20-15-00 +.. gh-issue: 144015 +.. nonce: pystrhex_simd +.. section: Core and Builtins + +Speed up :meth:`bytes.hex`, :meth:`bytearray.hex`, :func:`binascii.hexlify`, +and :mod:`hashlib` ``.hexdigest()`` operations with SIMD on x86-64, ARM64, +and ARM32 with NEON when built with gcc (version 12 or higher) or clang +(version 3 or higher) compilers. Around 1.1-3x faster for common 16-64 byte +inputs such as hashlib hex digests, and up to 8x faster for larger data. + +.. + +.. date: 2026-02-22-19-05-03 +.. gh-issue: 145118 +.. nonce: bU6Sic +.. section: Core and Builtins + +:func:`type` now accepts :class:`frozendict` as an argument. + +.. + +.. date: 2026-02-22-07-51-10 +.. gh-issue: 145064 +.. nonce: iIMGKA +.. section: Core and Builtins + +Fix JIT optimizer assertion failure during ``CALL_ALLOC_AND_ENTER_INIT`` +side exit. + +.. + +.. date: 2026-02-21-12-16-46 +.. gh-issue: 145055 +.. nonce: VyT-zI +.. section: Core and Builtins + +:func:`exec` and :func:`eval` now accept :class:`frozendict` for *globals*. +Patch by Victor Stinner. + +.. + +.. date: 2026-02-21-09-47-45 +.. gh-issue: 145058 +.. nonce: e-RBw- +.. section: Core and Builtins + +Fix a crash when :func:`!__lazy_import__` is passed a non-string argument, +by raising an :exc:`TypeError` instead. + +.. + +.. date: 2026-02-19-12-49-15 +.. gh-issue: 144995 +.. nonce: Ob2oYJ +.. section: Core and Builtins + +Optimize :class:`memoryview` comparison: a :class:`memoryview` is equal to +itself, there is no need to compare values. Patch by Victor Stinner. + +.. + +.. date: 2026-02-18-21-44-39 +.. gh-issue: 141510 +.. nonce: 7LST2O +.. section: Core and Builtins + +Update specializer to support frozendict. Patch by Donghee Na. + +.. + +.. date: 2026-02-17-22-27-11 +.. gh-issue: 141510 +.. nonce: -4yYsf +.. section: Core and Builtins + +Optimize :meth:`!frozendict.fromkeys` to avoid unnecessary thread-safety +operations in frozendict cases. Patch by Donghee Na. + +.. + +.. date: 2026-02-17-21-04-03 +.. gh-issue: 100239 +.. nonce: LyVabQ +.. section: Core and Builtins + +Speedup ``BINARY_OP_EXTEND`` for exact floats and medium-size integers by up +to 15%. Patch by Chris Eibl. + +.. + +.. date: 2026-02-17-18-27-28 +.. gh-issue: 144914 +.. nonce: DcXO4m +.. section: Core and Builtins + +Use ``mimalloc`` for raw memory allocations such as via +:c:func:`PyMem_RawMalloc` for better performance on :term:`free-threaded +builds `. Patch by Kumar Aditya. + +.. + +.. date: 2026-02-16-12-28-43 +.. gh-issue: 144872 +.. nonce: k9_Q30 +.. section: Core and Builtins + +Fix heap buffer overflow in the parser found by OSS-Fuzz. + +.. + +.. date: 2026-02-13-18-30-59 +.. gh-issue: 144766 +.. nonce: JGu3x3 +.. section: Core and Builtins + +Fix a crash in fork child process when perf support is enabled. + +.. + +.. date: 2026-02-13-12-00-00 +.. gh-issue: 144759 +.. nonce: d3qYpe +.. section: Core and Builtins + +Fix undefined behavior in the lexer when ``start`` and ``multi_line_start`` +pointers are ``NULL`` in ``_PyLexer_remember_fstring_buffers()`` and +``_PyLexer_restore_fstring_buffers()``. The ``NULL`` pointer arithmetic +(``NULL - valid_pointer``) is now guarded with explicit ``NULL`` checks. + +.. + +.. date: 2026-02-12-19-01-13 +.. gh-issue: 141510 +.. nonce: KlKjZg +.. section: Core and Builtins + +Add built-in :class:`frozendict` type. Patch by Victor Stinner. + +.. + +.. date: 2026-02-12-12-39-50 +.. gh-issue: 144681 +.. nonce: Ns2OT2 +.. section: Core and Builtins + +Fix a JIT assertion failure when a conditional branch jumps to the same +target as the fallthrough path. + +.. + +.. date: 2026-02-11-13-30-11 +.. gh-issue: 143300 +.. nonce: yjB63- +.. section: Core and Builtins + +Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as +:term:`immortal`. + +.. + +.. date: 2026-02-11-11-28-25 +.. gh-issue: 144702 +.. nonce: XjFumv +.. section: Core and Builtins + +Clarify the error message raised when a class pattern is used to match on a +non-class object. + +.. + +.. date: 2026-02-08-13-14-00 +.. gh-issue: 144569 +.. nonce: pjlJVe +.. section: Core and Builtins + +Optimize ``BINARY_SLICE`` for list, tuple, and unicode by avoiding temporary +``slice`` object creation. + +.. + +.. date: 2026-02-06-21-45-52 +.. gh-issue: 144438 +.. nonce: GI_uB1LR +.. section: Core and Builtins + +Align the QSBR thread state array to a 64-byte cache line boundary to avoid +false sharing in the :term:`free-threaded build`. + +.. + +.. date: 2025-12-06-15-46-32 +.. gh-issue: 142349 +.. nonce: IdTuYL +.. section: Core and Builtins + +Implement :pep:`810`. Patch by Pablo Galindo and Dino Viehland. + +.. + +.. date: 2025-11-09-15-44-58 +.. gh-issue: 141226 +.. nonce: KTb_3F +.. section: Core and Builtins + +Deprecate :pep:`456` support for providing an external definition of the +string hashing scheme. Removal is scheduled for Python 3.19. Patch by +Bénédikt Tran. + +.. + +.. date: 2025-09-15-13-28-48 +.. gh-issue: 138912 +.. nonce: 61EYbn +.. section: Core and Builtins + +Improve :opcode:`MATCH_CLASS` performance by up to 52% in certain cases. +Patch by Marc Mueller. + +.. + +.. date: 2025-02-19-21-06-30 +.. gh-issue: 130327 +.. nonce: z3TaR8 +.. section: Core and Builtins + +Fix erroneous clearing of an object's :attr:`~object.__dict__` if +overwritten at runtime. + +.. + +.. date: 2023-07-26-00-03-00 +.. gh-issue: 80667 +.. nonce: N7Dh8B +.. section: Core and Builtins + +Literals using the ``\N{name}`` escape syntax can now construct CJK +ideographs and Hangul syllables using case-insensitive names. + +.. + +.. date: 2026-03-03-14-59-57 +.. gh-issue: 142417 +.. nonce: HiNP5j +.. section: C API + +Restore private provisional ``_Py_InitializeMain()`` function removed in +Python 3.14. Patch by Victor Stinner. + +.. + +.. date: 2026-02-24-14-46-05 +.. gh-issue: 144748 +.. nonce: uhnFtE +.. section: C API + +:c:func:`PyErr_CheckSignals` now raises the exception scheduled by +:c:func:`PyThreadState_SetAsyncExc`, if any. + +.. + +.. date: 2026-02-18-15-12-34 +.. gh-issue: 144981 +.. nonce: 4ZdM63 +.. section: C API + +Made :c:func:`PyUnstable_Code_SetExtra`, :c:func:`PyUnstable_Code_GetExtra`, +and :c:func:`PyUnstable_Eval_RequestCodeExtraIndex` thread-safe on the +:term:`free threaded ` build. + +.. + +.. date: 2026-02-12-19-03-31 +.. gh-issue: 141510 +.. nonce: U_1tjz +.. section: C API + +Add the following functions for the new :class:`frozendict` type: + +* :c:func:`PyAnyDict_Check` +* :c:func:`PyAnyDict_CheckExact` +* :c:func:`PyFrozenDict_Check` +* :c:func:`PyFrozenDict_CheckExact` +* :c:func:`PyFrozenDict_New` + +Patch by Victor Stinner. + +.. + +.. date: 2026-02-10-14-49-49 +.. gh-issue: 121617 +.. nonce: 57vMqa +.. section: C API + +``Python.h`` now also includes ```` in the limited C API version +3.11 and newer to fix the :c:macro:`Py_CLEAR` macro which uses ``memcpy()``. +Patch by Victor Stinner. + +.. + +.. date: 2026-01-27-18-15-15 +.. gh-issue: 144175 +.. nonce: qHK5Jf +.. section: C API + +Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` +functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` +calling convention. Patch by Victor Stinner. + +.. + +.. date: 2026-02-27-18-10-02 +.. gh-issue: 144533 +.. nonce: 21fk9L +.. section: Build + +Use wasmtime's ``--argv0`` to auto-discover sysconfig in WASI builds + +.. + +.. date: 2026-02-22-13-35-20 +.. gh-issue: 145110 +.. nonce: KgWofW +.. section: Build + +Fix targets "Clean" and "CLeanAll" in case of PGO builds on Windows. Patch +by Chris Eibl. + +.. + +.. date: 2026-02-10-18-26-04 +.. gh-issue: 144679 +.. nonce: FIH73W +.. section: Build + +When building with Visual Studio 2026 (Version 18), use PlatformToolSet v145 +by default. Patch by Chris Eibl. + +.. + +.. date: 2026-02-10-16-59-56 +.. gh-issue: 144675 +.. nonce: Wrf3Es +.. section: Build + +Update to WASI SDK 30. + +.. + +.. date: 2025-07-21-00-33-38 +.. gh-issue: 136677 +.. nonce: Y1_3ec +.. section: Build + +Introduce executable specific linker flags to ``./configure``. diff --git a/Misc/NEWS.d/next/Build/2025-07-21-00-33-38.gh-issue-136677.Y1_3ec.rst b/Misc/NEWS.d/next/Build/2025-07-21-00-33-38.gh-issue-136677.Y1_3ec.rst deleted file mode 100644 index 30addc4bf64..00000000000 --- a/Misc/NEWS.d/next/Build/2025-07-21-00-33-38.gh-issue-136677.Y1_3ec.rst +++ /dev/null @@ -1 +0,0 @@ -Introduce executable specific linker flags to ``./configure``. diff --git a/Misc/NEWS.d/next/Build/2026-02-10-16-59-56.gh-issue-144675.Wrf3Es.rst b/Misc/NEWS.d/next/Build/2026-02-10-16-59-56.gh-issue-144675.Wrf3Es.rst deleted file mode 100644 index 1018ed95a2a..00000000000 --- a/Misc/NEWS.d/next/Build/2026-02-10-16-59-56.gh-issue-144675.Wrf3Es.rst +++ /dev/null @@ -1 +0,0 @@ -Update to WASI SDK 30. diff --git a/Misc/NEWS.d/next/Build/2026-02-10-18-26-04.gh-issue-144679.FIH73W.rst b/Misc/NEWS.d/next/Build/2026-02-10-18-26-04.gh-issue-144679.FIH73W.rst deleted file mode 100644 index ebcfda54da3..00000000000 --- a/Misc/NEWS.d/next/Build/2026-02-10-18-26-04.gh-issue-144679.FIH73W.rst +++ /dev/null @@ -1,2 +0,0 @@ -When building with Visual Studio 2026 (Version 18), use PlatformToolSet v145 -by default. Patch by Chris Eibl. diff --git a/Misc/NEWS.d/next/Build/2026-02-22-13-35-20.gh-issue-145110.KgWofW.rst b/Misc/NEWS.d/next/Build/2026-02-22-13-35-20.gh-issue-145110.KgWofW.rst deleted file mode 100644 index 035d0c141d3..00000000000 --- a/Misc/NEWS.d/next/Build/2026-02-22-13-35-20.gh-issue-145110.KgWofW.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix targets "Clean" and "CLeanAll" in case of PGO builds on Windows. Patch by -Chris Eibl. diff --git a/Misc/NEWS.d/next/Build/2026-02-27-18-10-02.gh-issue-144533.21fk9L.rst b/Misc/NEWS.d/next/Build/2026-02-27-18-10-02.gh-issue-144533.21fk9L.rst deleted file mode 100644 index d6e0201b90c..00000000000 --- a/Misc/NEWS.d/next/Build/2026-02-27-18-10-02.gh-issue-144533.21fk9L.rst +++ /dev/null @@ -1 +0,0 @@ -Use wasmtime's ``--argv0`` to auto-discover sysconfig in WASI builds diff --git a/Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst b/Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst deleted file mode 100644 index da1e489bb3d..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-01-27-18-15-15.gh-issue-144175.qHK5Jf.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :c:func:`PyArg_ParseArray` and :c:func:`PyArg_ParseArrayAndKeywords` -functions to parse arguments of functions using the :c:macro:`METH_FASTCALL` -calling convention. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2026-02-10-14-49-49.gh-issue-121617.57vMqa.rst b/Misc/NEWS.d/next/C_API/2026-02-10-14-49-49.gh-issue-121617.57vMqa.rst deleted file mode 100644 index cf84f8b1b0d..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-02-10-14-49-49.gh-issue-121617.57vMqa.rst +++ /dev/null @@ -1,3 +0,0 @@ -``Python.h`` now also includes ```` in the limited C API version 3.11 -and newer to fix the :c:macro:`Py_CLEAR` macro which uses ``memcpy()``. Patch -by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2026-02-12-19-03-31.gh-issue-141510.U_1tjz.rst b/Misc/NEWS.d/next/C_API/2026-02-12-19-03-31.gh-issue-141510.U_1tjz.rst deleted file mode 100644 index 57a25fe045f..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-02-12-19-03-31.gh-issue-141510.U_1tjz.rst +++ /dev/null @@ -1,9 +0,0 @@ -Add the following functions for the new :class:`frozendict` type: - -* :c:func:`PyAnyDict_Check` -* :c:func:`PyAnyDict_CheckExact` -* :c:func:`PyFrozenDict_Check` -* :c:func:`PyFrozenDict_CheckExact` -* :c:func:`PyFrozenDict_New` - -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2026-02-18-15-12-34.gh-issue-144981.4ZdM63.rst b/Misc/NEWS.d/next/C_API/2026-02-18-15-12-34.gh-issue-144981.4ZdM63.rst deleted file mode 100644 index d86886ab097..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-02-18-15-12-34.gh-issue-144981.4ZdM63.rst +++ /dev/null @@ -1,3 +0,0 @@ -Made :c:func:`PyUnstable_Code_SetExtra`, :c:func:`PyUnstable_Code_GetExtra`, -and :c:func:`PyUnstable_Eval_RequestCodeExtraIndex` thread-safe on the -:term:`free threaded ` build. diff --git a/Misc/NEWS.d/next/C_API/2026-02-24-14-46-05.gh-issue-144748.uhnFtE.rst b/Misc/NEWS.d/next/C_API/2026-02-24-14-46-05.gh-issue-144748.uhnFtE.rst deleted file mode 100644 index bda7003be94..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-02-24-14-46-05.gh-issue-144748.uhnFtE.rst +++ /dev/null @@ -1,2 +0,0 @@ -:c:func:`PyErr_CheckSignals` now raises the exception scheduled by -:c:func:`PyThreadState_SetAsyncExc`, if any. diff --git a/Misc/NEWS.d/next/C_API/2026-03-03-14-59-57.gh-issue-142417.HiNP5j.rst b/Misc/NEWS.d/next/C_API/2026-03-03-14-59-57.gh-issue-142417.HiNP5j.rst deleted file mode 100644 index 943be5b4533..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-03-03-14-59-57.gh-issue-142417.HiNP5j.rst +++ /dev/null @@ -1,2 +0,0 @@ -Restore private provisional ``_Py_InitializeMain()`` function removed in -Python 3.14. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2023-07-26-00-03-00.gh-issue-80667.N7Dh8B.rst b/Misc/NEWS.d/next/Core_and_Builtins/2023-07-26-00-03-00.gh-issue-80667.N7Dh8B.rst deleted file mode 100644 index db87a5ed9c7..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2023-07-26-00-03-00.gh-issue-80667.N7Dh8B.rst +++ /dev/null @@ -1,2 +0,0 @@ -Literals using the ``\N{name}`` escape syntax can now construct CJK -ideographs and Hangul syllables using case-insensitive names. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-19-21-06-30.gh-issue-130327.z3TaR8.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-19-21-06-30.gh-issue-130327.z3TaR8.rst deleted file mode 100644 index 9b9a282b5ab..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-19-21-06-30.gh-issue-130327.z3TaR8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix erroneous clearing of an object's :attr:`~object.__dict__` if -overwritten at runtime. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-15-13-28-48.gh-issue-138912.61EYbn.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-15-13-28-48.gh-issue-138912.61EYbn.rst deleted file mode 100644 index f5d312a289f..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-15-13-28-48.gh-issue-138912.61EYbn.rst +++ /dev/null @@ -1 +0,0 @@ -Improve :opcode:`MATCH_CLASS` performance by up to 52% in certain cases. Patch by Marc Mueller. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-09-15-44-58.gh-issue-141226.KTb_3F.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-09-15-44-58.gh-issue-141226.KTb_3F.rst deleted file mode 100644 index 3f7ce732618..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-09-15-44-58.gh-issue-141226.KTb_3F.rst +++ /dev/null @@ -1,3 +0,0 @@ -Deprecate :pep:`456` support for providing an external definition -of the string hashing scheme. Removal is scheduled for Python 3.19. -Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-06-15-46-32.gh-issue-142349.IdTuYL.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-06-15-46-32.gh-issue-142349.IdTuYL.rst deleted file mode 100644 index 73cc167fd04..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-06-15-46-32.gh-issue-142349.IdTuYL.rst +++ /dev/null @@ -1 +0,0 @@ -Implement :pep:`810`. Patch by Pablo Galindo and Dino Viehland. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-06-21-45-52.gh-issue-144438.GI_uB1LR.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-06-21-45-52.gh-issue-144438.GI_uB1LR.rst deleted file mode 100644 index 3e33e461ae8..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-06-21-45-52.gh-issue-144438.GI_uB1LR.rst +++ /dev/null @@ -1,2 +0,0 @@ -Align the QSBR thread state array to a 64-byte cache line boundary to -avoid false sharing in the :term:`free-threaded build`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-13-14-00.gh-issue-144569.pjlJVe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-13-14-00.gh-issue-144569.pjlJVe.rst deleted file mode 100644 index bdd0d6c2f7b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-13-14-00.gh-issue-144569.pjlJVe.rst +++ /dev/null @@ -1 +0,0 @@ -Optimize ``BINARY_SLICE`` for list, tuple, and unicode by avoiding temporary ``slice`` object creation. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-11-28-25.gh-issue-144702.XjFumv.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-11-28-25.gh-issue-144702.XjFumv.rst deleted file mode 100644 index 01d2b6570de..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-11-28-25.gh-issue-144702.XjFumv.rst +++ /dev/null @@ -1,2 +0,0 @@ -Clarify the error message raised when a class pattern is used to match on a -non-class object. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-13-30-11.gh-issue-143300.yjB63-.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-13-30-11.gh-issue-143300.yjB63-.rst deleted file mode 100644 index 85c75a224e4..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-11-13-30-11.gh-issue-143300.yjB63-.rst +++ /dev/null @@ -1 +0,0 @@ -Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as :term:`immortal`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst deleted file mode 100644 index c8ca7a7fa19..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-12-39-50.gh-issue-144681.Ns2OT2.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a JIT assertion failure when a conditional branch jumps to the same target as the fallthrough path. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-19-01-13.gh-issue-141510.KlKjZg.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-19-01-13.gh-issue-141510.KlKjZg.rst deleted file mode 100644 index 4596e273fc6..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-12-19-01-13.gh-issue-141510.KlKjZg.rst +++ /dev/null @@ -1 +0,0 @@ -Add built-in :class:`frozendict` type. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-12-00-00.gh-issue-144759.d3qYpe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-12-00-00.gh-issue-144759.d3qYpe.rst deleted file mode 100644 index 46786d0672b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-12-00-00.gh-issue-144759.d3qYpe.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix undefined behavior in the lexer when ``start`` and ``multi_line_start`` -pointers are ``NULL`` in ``_PyLexer_remember_fstring_buffers()`` and -``_PyLexer_restore_fstring_buffers()``. The ``NULL`` pointer arithmetic -(``NULL - valid_pointer``) is now guarded with explicit ``NULL`` checks. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-18-30-59.gh-issue-144766.JGu3x3.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-18-30-59.gh-issue-144766.JGu3x3.rst deleted file mode 100644 index d9613c95af1..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-13-18-30-59.gh-issue-144766.JGu3x3.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a crash in fork child process when perf support is enabled. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-16-12-28-43.gh-issue-144872.k9_Q30.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-16-12-28-43.gh-issue-144872.k9_Q30.rst deleted file mode 100644 index c06bf01baee..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-16-12-28-43.gh-issue-144872.k9_Q30.rst +++ /dev/null @@ -1 +0,0 @@ -Fix heap buffer overflow in the parser found by OSS-Fuzz. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-18-27-28.gh-issue-144914.DcXO4m.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-18-27-28.gh-issue-144914.DcXO4m.rst deleted file mode 100644 index f13b8541a0e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-18-27-28.gh-issue-144914.DcXO4m.rst +++ /dev/null @@ -1 +0,0 @@ -Use ``mimalloc`` for raw memory allocations such as via :c:func:`PyMem_RawMalloc` for better performance on :term:`free-threaded builds `. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-21-04-03.gh-issue-100239.LyVabQ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-21-04-03.gh-issue-100239.LyVabQ.rst deleted file mode 100644 index 3cfc3e930d1..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-21-04-03.gh-issue-100239.LyVabQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Speedup ``BINARY_OP_EXTEND`` for exact floats and medium-size integers by up -to 15%. Patch by Chris Eibl. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-22-27-11.gh-issue-141510.-4yYsf.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-22-27-11.gh-issue-141510.-4yYsf.rst deleted file mode 100644 index b031fb3c75d..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-17-22-27-11.gh-issue-141510.-4yYsf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optimize :meth:`!frozendict.fromkeys` to avoid unnecessary thread-safety operations -in frozendict cases. Patch by Donghee Na. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-18-21-44-39.gh-issue-141510.7LST2O.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-18-21-44-39.gh-issue-141510.7LST2O.rst deleted file mode 100644 index 87d6a2a6df9..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-18-21-44-39.gh-issue-141510.7LST2O.rst +++ /dev/null @@ -1 +0,0 @@ -Update specializer to support frozendict. Patch by Donghee Na. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst deleted file mode 100644 index 83d84b9505c..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optimize :class:`memoryview` comparison: a :class:`memoryview` is equal to -itself, there is no need to compare values. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-09-47-45.gh-issue-145058.e-RBw-.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-09-47-45.gh-issue-145058.e-RBw-.rst deleted file mode 100644 index 05eb296f96e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-09-47-45.gh-issue-145058.e-RBw-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash when :func:`!__lazy_import__` is passed a non-string argument, -by raising an :exc:`TypeError` instead. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst deleted file mode 100644 index c9daaa27717..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-21-12-16-46.gh-issue-145055.VyT-zI.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`exec` and :func:`eval` now accept :class:`frozendict` for *globals*. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-07-51-10.gh-issue-145064.iIMGKA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-07-51-10.gh-issue-145064.iIMGKA.rst deleted file mode 100644 index 1f298e164f4..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-07-51-10.gh-issue-145064.iIMGKA.rst +++ /dev/null @@ -1 +0,0 @@ -Fix JIT optimizer assertion failure during ``CALL_ALLOC_AND_ENTER_INIT`` side exit. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst deleted file mode 100644 index 24507d4a411..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`type` now accepts :class:`frozendict` as an argument. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-20-15-00.gh-issue-144015.pystrhex_simd.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-20-15-00.gh-issue-144015.pystrhex_simd.rst deleted file mode 100644 index 122315e031b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-20-15-00.gh-issue-144015.pystrhex_simd.rst +++ /dev/null @@ -1,5 +0,0 @@ -Speed up :meth:`bytes.hex`, :meth:`bytearray.hex`, :func:`binascii.hexlify`, -and :mod:`hashlib` ``.hexdigest()`` operations with SIMD on x86-64, ARM64, -and ARM32 with NEON when built with gcc (version 12 or higher) or clang -(version 3 or higher) compilers. Around 1.1-3x faster for common 16-64 byte -inputs such as hashlib hex digests, and up to 8x faster for larger data. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-22-05-09.gh-issue-145118.TaKMJE.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-22-05-09.gh-issue-145118.TaKMJE.rst deleted file mode 100644 index fccc3bc2a18..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-22-05-09.gh-issue-145118.TaKMJE.rst +++ /dev/null @@ -1 +0,0 @@ -:meth:`str.maketrans` now accepts :class:`frozendict`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-23-23-18-28.gh-issue-145142.T-XbVe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-23-23-18-28.gh-issue-145142.T-XbVe.rst deleted file mode 100644 index 5f6043cc3d9..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-23-23-18-28.gh-issue-145142.T-XbVe.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash in the free-threaded build when the dictionary argument to -:meth:`str.maketrans` is concurrently modified. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-24-18-30-56.gh-issue-145187.YjPu1Z.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-24-18-30-56.gh-issue-145187.YjPu1Z.rst deleted file mode 100644 index 08c6b44164e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-24-18-30-56.gh-issue-145187.YjPu1Z.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix compiler assertion fail when a type parameter bound contains an invalid -expression in a conditional block. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst deleted file mode 100644 index 6d6afe5abfe..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst +++ /dev/null @@ -1 +0,0 @@ -Fix JIT trace crash when recording function from cleared generator frame. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-12-00-00.gh-issue-130555.TMSOIu.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-12-00-00.gh-issue-130555.TMSOIu.rst deleted file mode 100644 index 5a2106480fb..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-12-00-00.gh-issue-130555.TMSOIu.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix use-after-free in :meth:`dict.clear` when the dictionary values are -embedded in an object and a destructor causes re-entrant mutation of the -dictionary. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-18-00-00.gh-issue-145241.hL2k9Q.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-18-00-00.gh-issue-145241.hL2k9Q.rst deleted file mode 100644 index a3253132a57..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-18-00-00.gh-issue-145241.hL2k9Q.rst +++ /dev/null @@ -1,3 +0,0 @@ -Specialized the parser error for when ``with`` items are followed -by a trailing comma (for example, ``with item,:``), raising a clearer -:exc:`SyntaxError` message. Patch by Pablo Galindo and Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-20-51-54.gh-issue-145273.B5QcUp.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-20-51-54.gh-issue-145273.B5QcUp.rst deleted file mode 100644 index 8d9e4a872d0..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-20-51-54.gh-issue-145273.B5QcUp.rst +++ /dev/null @@ -1,2 +0,0 @@ -A warning is now shown during :ref:`sys-path-init` if it can't find a valid -standard library. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-07-38.gh-issue-145275.qE-3O1.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-07-38.gh-issue-145275.qE-3O1.rst deleted file mode 100644 index 1723a7c8c10..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-07-38.gh-issue-145275.qE-3O1.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added the :option:`-X pathconfig_warnings<-X>` and -:envvar:`PYTHON_PATHCONFIG_WARNINGS` options, allowing to disable warnings -from :ref:`sys-path-init`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-36-00.gh-issue-145234.w0mQ9n.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-36-00.gh-issue-145234.w0mQ9n.rst deleted file mode 100644 index caeffff0be8..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-36-00.gh-issue-145234.w0mQ9n.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fixed a ``SystemError`` in the parser when an encoding cookie (for example, -UTF-7) decodes to carriage returns (``\r``). Newlines are now normalized after -decoding in the string tokenizer. - -Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-16-46-17.gh-issue-145376.lG5u1a.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-16-46-17.gh-issue-145376.lG5u1a.rst deleted file mode 100644 index a5a6908757e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-16-46-17.gh-issue-145376.lG5u1a.rst +++ /dev/null @@ -1 +0,0 @@ -Fix reference leaks in various unusual error scenarios. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst deleted file mode 100644 index 42ed85c7da3..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash in :func:`os.pathconf` when called with ``-1`` as the path -argument. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst deleted file mode 100644 index 9b55459bffd..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-16-16-17.gh-issue-143055.qDUFlY.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix crash in AST unparser when unparsing dict comprehension unpacking. -Found by OSS Fuzz in :oss-fuzz:`489790200`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst deleted file mode 100644 index 723b81ddc5f..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst +++ /dev/null @@ -1,2 +0,0 @@ -In the free threading build, skip the stop-the-world pause when reassigning -``__class__`` on a newly created object. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst deleted file mode 100644 index 212fd7b0290..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-01-36-20.gh-issue-116738.OWVWRx.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make :meth:`!mmap.mmap.set_name` thread-safe on the :term:`free threaded ` build. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst deleted file mode 100644 index 2183eef618d..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-06-21-05-05.gh-issue-145615.NKXXZgDW.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a memory leak in the :term:`free-threaded build` where mimalloc pages -could become permanently unreclaimable until the owning thread exited. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst deleted file mode 100644 index 23796082fb6..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-18-52-03.gh-issue-145701.79KQyO.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix :exc:`SystemError` when ``__classdict__`` or -``__conditional_annotations__`` is in a class-scope inlined comprehension. -Found by OSS Fuzz in :oss-fuzz:`491105000`. diff --git a/Misc/NEWS.d/next/Documentation/2025-08-02-18-59-01.gh-issue-136246.RIK7nE.rst b/Misc/NEWS.d/next/Documentation/2025-08-02-18-59-01.gh-issue-136246.RIK7nE.rst deleted file mode 100644 index 5f83785df13..00000000000 --- a/Misc/NEWS.d/next/Documentation/2025-08-02-18-59-01.gh-issue-136246.RIK7nE.rst +++ /dev/null @@ -1,3 +0,0 @@ -A new "Improve this page" link is available in the left-hand sidebar of the -docs, offering links to create GitHub issues, discussion forum posts, or -pull requests. diff --git a/Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst b/Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst deleted file mode 100644 index d29bde5ca69..00000000000 --- a/Misc/NEWS.d/next/Documentation/2026-01-06-16-04-08.gh-issue-110937.SyO5lk.rst +++ /dev/null @@ -1 +0,0 @@ -Document rest of full public :class:`importlib.metadata.Distribution` API. Also add the (already documented) :class:`~importlib.metadata.PackagePath` to ``__all__``. diff --git a/Misc/NEWS.d/next/Documentation/2026-03-03-08-18-00.gh-issue-145450.VI7GXj.rst b/Misc/NEWS.d/next/Documentation/2026-03-03-08-18-00.gh-issue-145450.VI7GXj.rst deleted file mode 100644 index 681c932b34a..00000000000 --- a/Misc/NEWS.d/next/Documentation/2026-03-03-08-18-00.gh-issue-145450.VI7GXj.rst +++ /dev/null @@ -1 +0,0 @@ -Document missing public :class:`wave.Wave_write` getter methods. diff --git a/Misc/NEWS.d/next/Library/2017-12-15-09-32-57.bpo-32234.XaOkhR.rst b/Misc/NEWS.d/next/Library/2017-12-15-09-32-57.bpo-32234.XaOkhR.rst deleted file mode 100644 index b2228983562..00000000000 --- a/Misc/NEWS.d/next/Library/2017-12-15-09-32-57.bpo-32234.XaOkhR.rst +++ /dev/null @@ -1,2 +0,0 @@ -:class:`mailbox.Mailbox` instances can now be used as a context manager. -The Mailbox is locked on context entry and unlocked and closed at context exit. diff --git a/Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst b/Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst deleted file mode 100644 index bf97bf0231f..00000000000 --- a/Misc/NEWS.d/next/Library/2018-05-11-12-26-16.bpo-3405.CacMw9.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add support for user data of Tk virtual events and detail for -``Enter``, ``Leave``, ``FocusIn``, ``FocusOut``, and -``ConfigureRequest`` events to :mod:`tkinter`. diff --git a/Misc/NEWS.d/next/Library/2020-04-07-05-09-34.bpo-40212.oPYeBs.rst b/Misc/NEWS.d/next/Library/2020-04-07-05-09-34.bpo-40212.oPYeBs.rst deleted file mode 100644 index 2e9c3d81180..00000000000 --- a/Misc/NEWS.d/next/Library/2020-04-07-05-09-34.bpo-40212.oPYeBs.rst +++ /dev/null @@ -1 +0,0 @@ -Re-enable :func:`os.posix_fallocate` and :func:`os.posix_fadvise` on AIX. diff --git a/Misc/NEWS.d/next/Library/2020-04-10-14-29-53.bpo-40243.85HRib.rst b/Misc/NEWS.d/next/Library/2020-04-10-14-29-53.bpo-40243.85HRib.rst deleted file mode 100644 index 1f48525cdbe..00000000000 --- a/Misc/NEWS.d/next/Library/2020-04-10-14-29-53.bpo-40243.85HRib.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :meth:`!unicodedata.ucd_3_2_0.numeric` for non-decimal values. diff --git a/Misc/NEWS.d/next/Library/2022-02-05-00-15-03.bpo-42353.0ebVGG.rst b/Misc/NEWS.d/next/Library/2022-02-05-00-15-03.bpo-42353.0ebVGG.rst deleted file mode 100644 index a3e0a3e14af..00000000000 --- a/Misc/NEWS.d/next/Library/2022-02-05-00-15-03.bpo-42353.0ebVGG.rst +++ /dev/null @@ -1,10 +0,0 @@ -The :mod:`re` module gains a new :func:`re.prefixmatch` function as an -explicit spelling of what has to date always been known as :func:`re.match`. -:class:`re.Pattern` similary gains a :meth:`re.Pattern.prefixmatch` method. - -Why? Explicit is better than implicit. Other widely used languages all use -the term "match" to mean what Python uses the term "search" for. The -unadorened "match" name in Python has been a frequent case of confusion and -coding bugs due to the inconsistency with the rest if the software industry. - -We do not plan to deprecate and remove the older ``match`` name. diff --git a/Misc/NEWS.d/next/Library/2023-02-05-20-02-30.gh-issue-80667.7LmzeA.rst b/Misc/NEWS.d/next/Library/2023-02-05-20-02-30.gh-issue-80667.7LmzeA.rst deleted file mode 100644 index f82f1eeb058..00000000000 --- a/Misc/NEWS.d/next/Library/2023-02-05-20-02-30.gh-issue-80667.7LmzeA.rst +++ /dev/null @@ -1 +0,0 @@ -Add support for Tangut Ideographs names in :mod:`unicodedata`. diff --git a/Misc/NEWS.d/next/Library/2024-09-30-15-31-59.gh-issue-124748.KYzYFp.rst b/Misc/NEWS.d/next/Library/2024-09-30-15-31-59.gh-issue-124748.KYzYFp.rst deleted file mode 100644 index 5067db357fc..00000000000 --- a/Misc/NEWS.d/next/Library/2024-09-30-15-31-59.gh-issue-124748.KYzYFp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve :exc:`TypeError` error message when :meth:`!weakref.WeakKeyDictionary.update` -is used with keyword-only parameters. diff --git a/Misc/NEWS.d/next/Library/2025-06-24-19-07-18.gh-issue-135883.38cePA.rst b/Misc/NEWS.d/next/Library/2025-06-24-19-07-18.gh-issue-135883.38cePA.rst deleted file mode 100644 index 8f3efceaae1..00000000000 --- a/Misc/NEWS.d/next/Library/2025-06-24-19-07-18.gh-issue-135883.38cePA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :mod:`sqlite3`'s :ref:`interactive shell ` keeping part of -previous commands when scrolling history. diff --git a/Misc/NEWS.d/next/Library/2025-08-04-23-20-43.gh-issue-137335.IIjDJN.rst b/Misc/NEWS.d/next/Library/2025-08-04-23-20-43.gh-issue-137335.IIjDJN.rst deleted file mode 100644 index 2311ace10e4..00000000000 --- a/Misc/NEWS.d/next/Library/2025-08-04-23-20-43.gh-issue-137335.IIjDJN.rst +++ /dev/null @@ -1,2 +0,0 @@ -Get rid of any possibility of a name conflict for named pipes in -:mod:`multiprocessing` and :mod:`asyncio` on Windows, no matter how small. diff --git a/Misc/NEWS.d/next/Library/2025-10-10-14-08-58.gh-issue-139899.09leRY.rst b/Misc/NEWS.d/next/Library/2025-10-10-14-08-58.gh-issue-139899.09leRY.rst deleted file mode 100644 index fe5e7d17ab6..00000000000 --- a/Misc/NEWS.d/next/Library/2025-10-10-14-08-58.gh-issue-139899.09leRY.rst +++ /dev/null @@ -1,3 +0,0 @@ -Introduced :meth:`importlib.abc.MetaPathFinder.discover` -and :meth:`importlib.abc.PathEntryFinder.discover` to allow module and submodule -name discovery without assuming the use of traditional filesystem based imports. diff --git a/Misc/NEWS.d/next/Library/2025-12-06-16-14-18.gh-issue-142352.pW5HLX88.rst b/Misc/NEWS.d/next/Library/2025-12-06-16-14-18.gh-issue-142352.pW5HLX88.rst deleted file mode 100644 index 13e38b11817..00000000000 --- a/Misc/NEWS.d/next/Library/2025-12-06-16-14-18.gh-issue-142352.pW5HLX88.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix :meth:`asyncio.StreamWriter.start_tls` to transfer buffered data from -:class:`~asyncio.StreamReader` to the SSL layer, preventing data loss when -upgrading a connection to TLS mid-stream (e.g., when implementing PROXY -protocol support). diff --git a/Misc/NEWS.d/next/Library/2025-12-16-13-34-48.gh-issue-142787.wNitJX.rst b/Misc/NEWS.d/next/Library/2025-12-16-13-34-48.gh-issue-142787.wNitJX.rst deleted file mode 100644 index e928bd2cac7..00000000000 --- a/Misc/NEWS.d/next/Library/2025-12-16-13-34-48.gh-issue-142787.wNitJX.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix assertion failure in :mod:`sqlite3` blob subscript when slicing with -indices that result in an empty slice. diff --git a/Misc/NEWS.d/next/Library/2025-12-18-00-14-16.gh-issue-142781.gcOeYF.rst b/Misc/NEWS.d/next/Library/2025-12-18-00-14-16.gh-issue-142781.gcOeYF.rst deleted file mode 100644 index 772e05766c5..00000000000 --- a/Misc/NEWS.d/next/Library/2025-12-18-00-14-16.gh-issue-142781.gcOeYF.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`zoneinfo`: fix a crash when instantiating :class:`~zoneinfo.ZoneInfo` -objects for which the internal class-level cache is inconsistent. diff --git a/Misc/NEWS.d/next/Library/2026-01-01-05-26-00.gh-issue-143304.Kv7x9Q.rst b/Misc/NEWS.d/next/Library/2026-01-01-05-26-00.gh-issue-143304.Kv7x9Q.rst deleted file mode 100644 index 826b2e9a126..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-01-05-26-00.gh-issue-143304.Kv7x9Q.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :class:`ctypes.CDLL` to honor the ``handle`` parameter on POSIX systems. diff --git a/Misc/NEWS.d/next/Library/2026-01-10-22-58-30.gh-issue-85809.0eW4wt.rst b/Misc/NEWS.d/next/Library/2026-01-10-22-58-30.gh-issue-85809.0eW4wt.rst deleted file mode 100644 index 3993c7a91da..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-10-22-58-30.gh-issue-85809.0eW4wt.rst +++ /dev/null @@ -1 +0,0 @@ -Added :term:`path-like object` support for :func:`shutil.make_archive`. diff --git a/Misc/NEWS.d/next/Library/2026-01-11-13-03-32.gh-issue-142516.u7An-s.rst b/Misc/NEWS.d/next/Library/2026-01-11-13-03-32.gh-issue-142516.u7An-s.rst deleted file mode 100644 index efa7c8a1f62..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-11-13-03-32.gh-issue-142516.u7An-s.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`ssl`: fix reference leaks in :class:`ssl.SSLContext` objects. Patch by -Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-01-11-16-59-22.gh-issue-143698.b-Cpeb.rst b/Misc/NEWS.d/next/Library/2026-01-11-16-59-22.gh-issue-143698.b-Cpeb.rst deleted file mode 100644 index 05dc4941c98..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-11-16-59-22.gh-issue-143698.b-Cpeb.rst +++ /dev/null @@ -1,3 +0,0 @@ -Raise :exc:`TypeError` instead of :exc:`SystemError` when the *scheduler* -in :func:`os.posix_spawn` or :func:`os.posix_spawnp` is not a tuple. -Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-01-11-18-35-52.gh-issue-143698.gXDzsJ.rst b/Misc/NEWS.d/next/Library/2026-01-11-18-35-52.gh-issue-143698.gXDzsJ.rst deleted file mode 100644 index 5f95b0de7d8..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-11-18-35-52.gh-issue-143698.gXDzsJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Allow *scheduler* and *setpgroup* arguments to be explicitly :const:`None` -when calling :func:`os.posix_spawn` or :func:`os.posix_spawnp`. Patch by -Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst b/Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst deleted file mode 100644 index bed126f02f8..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-12-19-39-57.gh-issue-140652.HvM9Bl.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a crash in :func:`!_interpchannels.list_all` after closing a channel. diff --git a/Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst b/Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst deleted file mode 100644 index cbb21194d5b..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash in socket.sendmsg() that could occur if ancillary data is mutated re-entrantly during argument parsing. diff --git a/Misc/NEWS.d/next/Library/2026-02-03-19-57-41.gh-issue-144316.wop870.rst b/Misc/NEWS.d/next/Library/2026-02-03-19-57-41.gh-issue-144316.wop870.rst deleted file mode 100644 index b9d0749f56b..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-03-19-57-41.gh-issue-144316.wop870.rst +++ /dev/null @@ -1 +0,0 @@ -Fix crash in ``_remote_debugging`` that caused ``test_external_inspection`` to intermittently fail. Patch by Taegyun Kim. diff --git a/Misc/NEWS.d/next/Library/2026-02-07-16-31-42.gh-issue-144285.iyH9iL.rst b/Misc/NEWS.d/next/Library/2026-02-07-16-31-42.gh-issue-144285.iyH9iL.rst deleted file mode 100644 index e1119a85e9c..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-07-16-31-42.gh-issue-144285.iyH9iL.rst +++ /dev/null @@ -1,3 +0,0 @@ -Attribute suggestions in :exc:`AttributeError` tracebacks are now formatted differently -to make them easier to understand, for example: ``Did you mean '.datetime.now' instead of '.now'``. -Contributed by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2026-02-07-16-37-42.gh-issue-144475.8tFEXw.rst b/Misc/NEWS.d/next/Library/2026-02-07-16-37-42.gh-issue-144475.8tFEXw.rst deleted file mode 100644 index b458399bb40..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-07-16-37-42.gh-issue-144475.8tFEXw.rst +++ /dev/null @@ -1,3 +0,0 @@ -Calling :func:`repr` on :func:`functools.partial` is now safer -when the partial object's internal attributes are replaced while -the string representation is being generated. diff --git a/Misc/NEWS.d/next/Library/2026-02-08-17-09-10.gh-issue-144321.w58PhQ.rst b/Misc/NEWS.d/next/Library/2026-02-08-17-09-10.gh-issue-144321.w58PhQ.rst deleted file mode 100644 index 45561898e2e..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-08-17-09-10.gh-issue-144321.w58PhQ.rst +++ /dev/null @@ -1,3 +0,0 @@ -The functional syntax for creating :class:`typing.NamedTuple` -classes now supports passing any :term:`iterable` of fields and types. -Previously, only sequences were supported. diff --git a/Misc/NEWS.d/next/Library/2026-02-09-02-16-36.gh-issue-144615.s04x4n.rst b/Misc/NEWS.d/next/Library/2026-02-09-02-16-36.gh-issue-144615.s04x4n.rst deleted file mode 100644 index 1db257ae312..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-09-02-16-36.gh-issue-144615.s04x4n.rst +++ /dev/null @@ -1,3 +0,0 @@ -Methods directly decorated with :deco:`functools.singledispatchmethod` now -dispatch on the second argument when called after being accessed as class -attributes. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2026-02-10-16-56-05.gh-issue-66305.PZ6GN8.rst b/Misc/NEWS.d/next/Library/2026-02-10-16-56-05.gh-issue-66305.PZ6GN8.rst deleted file mode 100644 index 276711e6ba3..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-10-16-56-05.gh-issue-66305.PZ6GN8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a hang on Windows in the :mod:`tempfile` module when -trying to create a temporary file or subdirectory in a non-writable -directory. diff --git a/Misc/NEWS.d/next/Library/2026-02-10-22-05-51.gh-issue-144156.UbrC7F.rst b/Misc/NEWS.d/next/Library/2026-02-10-22-05-51.gh-issue-144156.UbrC7F.rst deleted file mode 100644 index 68e59a6276c..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-10-22-05-51.gh-issue-144156.UbrC7F.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the folding of headers by the :mod:`email` library when :rfc:`2047` encoded words are used. Now whitespace is correctly preserved and also correctly added between adjacent encoded words. The latter property was broken by the fix for gh-92081, which mostly fixed previous failures to preserve whitespace. diff --git a/Misc/NEWS.d/next/Library/2026-02-12-17-56-17.gh-issue-117865.jE1ema.rst b/Misc/NEWS.d/next/Library/2026-02-12-17-56-17.gh-issue-117865.jE1ema.rst deleted file mode 100644 index f45f6682869..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-12-17-56-17.gh-issue-117865.jE1ema.rst +++ /dev/null @@ -1 +0,0 @@ -Reduce the import time of :mod:`inspect` module by ~20%. diff --git a/Misc/NEWS.d/next/Library/2026-02-13-00-00-00.gh-issue-142224.BidiMissing.rst b/Misc/NEWS.d/next/Library/2026-02-13-00-00-00.gh-issue-142224.BidiMissing.rst deleted file mode 100644 index 29fa908d739..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-13-00-00-00.gh-issue-142224.BidiMissing.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`unicodedata.bidirectional` now return the correct default bidi class -for unassigned code points. diff --git a/Misc/NEWS.d/next/Library/2026-02-13-11-14-18.gh-issue-144763.cDwnEE.rst b/Misc/NEWS.d/next/Library/2026-02-13-11-14-18.gh-issue-144763.cDwnEE.rst deleted file mode 100644 index 14eb4f49c8a..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-13-11-14-18.gh-issue-144763.cDwnEE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a race condition in :mod:`tracemalloc`: it no longer detaches the attached -thread state to acquire its internal lock. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst b/Misc/NEWS.d/next/Library/2026-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst deleted file mode 100644 index 871005fd7d9..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :class:`argparse.ArgumentParser` to be :mod:`pickleable `. diff --git a/Misc/NEWS.d/next/Library/2026-02-14-14-56-44.gh-issue-140715.AbSheM.rst b/Misc/NEWS.d/next/Library/2026-02-14-14-56-44.gh-issue-140715.AbSheM.rst deleted file mode 100644 index f7782f2fa4f..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-14-14-56-44.gh-issue-140715.AbSheM.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``'%D'`` support to :meth:`~datetime.datetime.strptime`. diff --git a/Misc/NEWS.d/next/Library/2026-02-15-00-00-00.gh-issue-144833.TUelo1.rst b/Misc/NEWS.d/next/Library/2026-02-15-00-00-00.gh-issue-144833.TUelo1.rst deleted file mode 100644 index 6d5b18f59ee..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-15-00-00-00.gh-issue-144833.TUelo1.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a use-after-free in :mod:`ssl` when ``SSL_new()`` returns NULL in -``newPySSLSocket()``. The error was reported via a dangling pointer after the -object had already been freed. diff --git a/Misc/NEWS.d/next/Library/2026-02-15-12-02-20.gh-issue-144835.w_oS_J.rst b/Misc/NEWS.d/next/Library/2026-02-15-12-02-20.gh-issue-144835.w_oS_J.rst deleted file mode 100644 index 9d603b51c48..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-15-12-02-20.gh-issue-144835.w_oS_J.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added missing explanations for some parameters in :func:`glob.glob` and -:func:`glob.iglob`. diff --git a/Misc/NEWS.d/next/Library/2026-02-17-11-15-17.gh-issue-141510.ZmqEUb.rst b/Misc/NEWS.d/next/Library/2026-02-17-11-15-17.gh-issue-141510.ZmqEUb.rst deleted file mode 100644 index 59a8b4165cd..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-17-11-15-17.gh-issue-141510.ZmqEUb.rst +++ /dev/null @@ -1,2 +0,0 @@ -The :mod:`json` module now supports the :class:`frozendict` type. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst b/Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst deleted file mode 100644 index 5b604124c6d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-17-11-28-37.gh-issue-141510.OpAz0M.rst +++ /dev/null @@ -1,2 +0,0 @@ -The :mod:`copy` module now supports the :class:`frozendict` type. Patch by -Pieter Eendebak based on work by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-02-18-00-00-00.gh-issue-144809.nYpEUx.rst b/Misc/NEWS.d/next/Library/2026-02-18-00-00-00.gh-issue-144809.nYpEUx.rst deleted file mode 100644 index 62c20b7fa06..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-18-00-00-00.gh-issue-144809.nYpEUx.rst +++ /dev/null @@ -1 +0,0 @@ -Make :class:`collections.deque` copy atomic in the :term:`free-threaded build`. diff --git a/Misc/NEWS.d/next/Library/2026-02-18-13-45-00.gh-issue-144777.R97q0a.rst b/Misc/NEWS.d/next/Library/2026-02-18-13-45-00.gh-issue-144777.R97q0a.rst deleted file mode 100644 index fd720bfd3f3..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-18-13-45-00.gh-issue-144777.R97q0a.rst +++ /dev/null @@ -1 +0,0 @@ -Fix data races in :class:`io.IncrementalNewlineDecoder` in the :term:`free-threaded build`. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-00-00-00.gh-issue-144986.atexit-leak.rst b/Misc/NEWS.d/next/Library/2026-02-19-00-00-00.gh-issue-144986.atexit-leak.rst deleted file mode 100644 index 841c3758ec4..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-00-00-00.gh-issue-144986.atexit-leak.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a memory leak in :func:`atexit.register`. -Patch by Shamil Abdulaev. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-10-57-40.gh-issue-88091.N7qGV-.rst b/Misc/NEWS.d/next/Library/2026-02-19-10-57-40.gh-issue-88091.N7qGV-.rst deleted file mode 100644 index 15cf25052bb..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-10-57-40.gh-issue-88091.N7qGV-.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`unicodedata.decomposition` for Hangul characters. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst b/Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst deleted file mode 100644 index 4654dd060a6..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-15-42-06.gh-issue-134872.sjYX1-.rst +++ /dev/null @@ -1 +0,0 @@ -Add valid import name suggestions on :exc:`ModuleNotFoundError`. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-16-26-08.gh-issue-141510.4Qxy8_.rst b/Misc/NEWS.d/next/Library/2026-02-19-16-26-08.gh-issue-141510.4Qxy8_.rst deleted file mode 100644 index cf22e82b841..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-16-26-08.gh-issue-141510.4Qxy8_.rst +++ /dev/null @@ -1,3 +0,0 @@ -``ParameterizedMIMEHeader.params`` of :mod:`email.headerregistry` is now a -:class:`frozendict` instead of a :class:`types.MappingProxyType`. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-17-50-47.gh-issue-145006.9gqA0Q.rst b/Misc/NEWS.d/next/Library/2026-02-19-17-50-47.gh-issue-145006.9gqA0Q.rst deleted file mode 100644 index 69052c7ca92..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-17-50-47.gh-issue-145006.9gqA0Q.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :exc:`ModuleNotFoundError` hints when a module for a different ABI -exists. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-18-02-54.gh-issue-141510.qzvYsO.rst b/Misc/NEWS.d/next/Library/2026-02-19-18-02-54.gh-issue-141510.qzvYsO.rst deleted file mode 100644 index ae46ff0cbdd..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-18-02-54.gh-issue-141510.qzvYsO.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`dataclasses.field`: if *metadata* is ``None``, use an empty -:class:`frozendict`, instead of a :func:`~types.MappingProxyType` of an -empty :class:`dict`. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-20-54-25.gh-issue-145033.X9EBPQ.rst b/Misc/NEWS.d/next/Library/2026-02-19-20-54-25.gh-issue-145033.X9EBPQ.rst deleted file mode 100644 index 6f496bb30e1..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-20-54-25.gh-issue-145033.X9EBPQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :data:`typing.TypeForm`, implementing :pep:`747`. Patch by Jelle -Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2026-02-20-13-03-10.gh-issue-66802.OYcAi_.rst b/Misc/NEWS.d/next/Library/2026-02-20-13-03-10.gh-issue-66802.OYcAi_.rst deleted file mode 100644 index 68a25262c7d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-20-13-03-10.gh-issue-66802.OYcAi_.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :func:`unicodedata.block` function to return the `Unicode block -`_ of a -character. diff --git a/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst b/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst deleted file mode 100644 index 1babcbfd8e6..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-21-17-34-53.gh-issue-123853.6RUwWh.rst +++ /dev/null @@ -1 +0,0 @@ -Removed Windows 95 compatibility for :func:`locale.getdefaultlocale`. diff --git a/Misc/NEWS.d/next/Library/2026-02-23-20-52-55.gh-issue-145158.vWJtxI.rst b/Misc/NEWS.d/next/Library/2026-02-23-20-52-55.gh-issue-145158.vWJtxI.rst deleted file mode 100644 index 60a5e4ad1f0..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-23-20-52-55.gh-issue-145158.vWJtxI.rst +++ /dev/null @@ -1,2 +0,0 @@ -Avoid undefined behaviour from signed integer overflow when parsing format -strings in the :mod:`struct` module. diff --git a/Misc/NEWS.d/next/Library/2026-02-27-18-04-51.gh-issue-76007.17idfK.rst b/Misc/NEWS.d/next/Library/2026-02-27-18-04-51.gh-issue-76007.17idfK.rst deleted file mode 100644 index 4bb230dcb84..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-27-18-04-51.gh-issue-76007.17idfK.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ``version`` attribute of the :mod:`tarfile` module is deprecated and -slated for removal in Python 3.20. diff --git a/Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst b/Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst deleted file mode 100644 index 7aeb6a1145a..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-27-19-00-26.gh-issue-145301.2Wih4b.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`hashlib`: fix a crash when the initialization of the underlying C -extension module fails. diff --git a/Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst b/Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst deleted file mode 100644 index 436ff316b2c..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-28-00-55-00.gh-issue-145301.Lk2bRl.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`hmac`: fix a crash when the initialization of the underlying C -extension module fails. diff --git a/Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst b/Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst deleted file mode 100644 index b6dbda04271..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-02-19-41-39.gh-issue-145376.OOzSOh.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix double free and null pointer dereference in unusual error scenarios -in :mod:`hashlib` and :mod:`hmac` modules. diff --git a/Misc/NEWS.d/next/Library/2026-03-02-20-08-09.gh-issue-145335.lVTBvd.rst b/Misc/NEWS.d/next/Library/2026-03-02-20-08-09.gh-issue-145335.lVTBvd.rst deleted file mode 100644 index 53033b06c2f..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-02-20-08-09.gh-issue-145335.lVTBvd.rst +++ /dev/null @@ -1,5 +0,0 @@ -``os.listdir(-1)`` and ``os.scandir(-1)`` now fail with -``OSError(errno.EBADF)`` rather than listing the current directory. -``os.listxattr(-1)`` now fails with ``OSError(errno.EBADF)`` rather than -listing extended attributes of the current directory. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst b/Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst deleted file mode 100644 index 17d62df72ce..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-03-11-49-44.gh-issue-145417.m_HxIL.rst +++ /dev/null @@ -1,4 +0,0 @@ -:mod:`venv`: Prevent incorrect preservation of SELinux context -when copying the ``Activate.ps1`` script. The script inherited -the SELinux security context of the system template directory, -rather than the destination project directory. diff --git a/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst b/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst deleted file mode 100644 index 280a7b3632d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-05-16-06-09.gh-issue-141510.dFPAQS.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`marshal` now supports :class:`frozendict` objects. The marshal format -version was increased to 6. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst b/Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst deleted file mode 100644 index 15b70d734ca..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-05-19-01-28.gh-issue-145551.gItPRl.rst +++ /dev/null @@ -1 +0,0 @@ -Fix InvalidStateError when cancelling process created by :func:`asyncio.create_subprocess_exec` or :func:`asyncio.create_subprocess_shell`. Patch by Daan De Meyer. diff --git a/Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst b/Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst deleted file mode 100644 index 77b43e79e35..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-07-15-00-00.gh-issue-145623.2Y7LzT.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix crash in :mod:`struct` when calling :func:`repr` or -``__sizeof__()`` on an uninitialized :class:`struct.Struct` -object created via ``Struct.__new__()`` without calling ``__init__()``. diff --git a/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst b/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst deleted file mode 100644 index 2d13a061132..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-31-21-56-54.gh-issue-144370.fp9m8t.rst +++ /dev/null @@ -1,2 +0,0 @@ -Disallow usage of control characters in status in :mod:`wsgiref.handlers` to prevent HTTP header injections. -Patch by Benedikt Johannes. diff --git a/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst b/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst deleted file mode 100644 index dcdb44d4fae..00000000000 --- a/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixes :cve:`2026-2297` by ensuring that ``SourcelessFileLoader`` uses -:func:`io.open_code` when opening ``.pyc`` files. diff --git a/Misc/NEWS.d/next/Tests/2026-02-12-12-12-00.gh-issue-144739.-fx1tN.rst b/Misc/NEWS.d/next/Tests/2026-02-12-12-12-00.gh-issue-144739.-fx1tN.rst deleted file mode 100644 index 8c46ff133f9..00000000000 --- a/Misc/NEWS.d/next/Tests/2026-02-12-12-12-00.gh-issue-144739.-fx1tN.rst +++ /dev/null @@ -1,3 +0,0 @@ -When Python was compiled with system expat older then 2.7.2 but tests run -with newer expat, still skip -:class:`!test.test_pyexpat.MemoryProtectionTest`. diff --git a/Misc/NEWS.d/next/Tests/2026-03-04-17-39-15.gh-issue-144741.0RHhBF.rst b/Misc/NEWS.d/next/Tests/2026-03-04-17-39-15.gh-issue-144741.0RHhBF.rst deleted file mode 100644 index be3092f1c25..00000000000 --- a/Misc/NEWS.d/next/Tests/2026-03-04-17-39-15.gh-issue-144741.0RHhBF.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix ``test_frame_pointer_unwind`` when Python is built with -:option:`--enable-shared`. Classify also libpython frames as ``"python"``. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Windows/2026-02-13-11-07-51.gh-issue-144551.ENtMYD.rst b/Misc/NEWS.d/next/Windows/2026-02-13-11-07-51.gh-issue-144551.ENtMYD.rst deleted file mode 100644 index 810985a352b..00000000000 --- a/Misc/NEWS.d/next/Windows/2026-02-13-11-07-51.gh-issue-144551.ENtMYD.rst +++ /dev/null @@ -1 +0,0 @@ -Updated bundled version of OpenSSL to 3.5.5. diff --git a/Misc/NEWS.d/next/Windows/2026-02-27-10-57-20.gh-issue-145307.ueoT7j.rst b/Misc/NEWS.d/next/Windows/2026-02-27-10-57-20.gh-issue-145307.ueoT7j.rst deleted file mode 100644 index 6f039197962..00000000000 --- a/Misc/NEWS.d/next/Windows/2026-02-27-10-57-20.gh-issue-145307.ueoT7j.rst +++ /dev/null @@ -1,2 +0,0 @@ -Defers loading of the ``psapi.dll`` module until it is used by -:func:`ctypes.util.dllist`. diff --git a/Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst b/Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst deleted file mode 100644 index 676a68e5a91..00000000000 --- a/Misc/NEWS.d/next/Windows/2026-03-10-09-46-44.gh-issue-145731.5uEGgb.rst +++ /dev/null @@ -1 +0,0 @@ -Fix negative timestamp during DST on Windows. Patch by Hugo van Kemenade. diff --git a/README.rst b/README.rst index 68e114e66ab..1d2874e9ca4 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.15.0 alpha 6 +This is Python version 3.15.0 alpha 7 ===================================== .. image:: https://github.com/python/cpython/actions/workflows/build.yml/badge.svg?branch=main&event=push From 2d35f9bc1cf61b27639ed992dfbf363ab436fd8b Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Tue, 10 Mar 2026 06:20:42 -0700 Subject: [PATCH 064/775] gh-145492: Fix defaultdict __repr__ infinite recursion (GH-145659) Co-Authored-By: Thomas Kowalski --- Lib/test/test_defaultdict.py | 15 +++++++++++++++ ...2026-03-09-00-00-00.gh-issue-145492.457Afc.rst | 3 +++ Modules/_collectionsmodule.c | 5 +++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py index fbd7354a915..732e9a876ca 100644 --- a/Lib/test/test_defaultdict.py +++ b/Lib/test/test_defaultdict.py @@ -204,5 +204,20 @@ def default_factory(): self.assertEqual(test_dict[key], 2) self.assertEqual(count, 2) + def test_repr_recursive_factory(self): + # gh-145492: defaultdict.__repr__ should not cause infinite recursion + # when the factory's __repr__ calls repr() on the defaultdict. + class ProblematicFactory: + def __call__(self): + return {} + def __repr__(self): + repr(dd) + return "ProblematicFactory()" + + dd = defaultdict(ProblematicFactory()) + # Should not raise RecursionError + r = repr(dd) + self.assertIn('ProblematicFactory()', r) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst b/Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst new file mode 100644 index 00000000000..297ee4099f1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst @@ -0,0 +1,3 @@ +Fix infinite recursion in :class:`collections.defaultdict` ``__repr__`` +when a ``defaultdict`` contains itself. Based on analysis by KowalskiThomas +in :gh:`145492`. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index c3d63c8aab4..15c9aa41911 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2385,9 +2385,10 @@ defdict_repr(PyObject *op) } defrepr = PyUnicode_FromString("..."); } - else + else { defrepr = PyObject_Repr(dd->default_factory); - Py_ReprLeave(dd->default_factory); + Py_ReprLeave(dd->default_factory); + } } if (defrepr == NULL) { Py_DECREF(baserepr); From ae0d2875bcfa111383e39d9ba0d24c1c317ee597 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 10 Mar 2026 13:58:32 +0000 Subject: [PATCH 065/775] gh-145035: Allows removing the _pyrepl module to completely disable the modern REPL (GH-145159) --- Lib/_sitebuiltins.py | 12 ++++- Lib/asyncio/__main__.py | 14 ++++-- Lib/pdb.py | 8 +++- Lib/pydoc.py | 41 ++++++++++++---- Lib/site.py | 2 + Lib/test/support/__init__.py | 7 +++ Lib/test/test_pyclbr.py | 3 +- Lib/test/test_pyrepl/__init__.py | 3 ++ Lib/test/test_repl.py | 7 +++ ...-02-23-21-28-12.gh-issue-145035.J5UjS6.rst | 3 ++ Modules/main.c | 48 ++++++++++++++----- 11 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst diff --git a/Lib/_sitebuiltins.py b/Lib/_sitebuiltins.py index 81b36efc6c2..84551e3546e 100644 --- a/Lib/_sitebuiltins.py +++ b/Lib/_sitebuiltins.py @@ -65,7 +65,17 @@ def __repr__(self): return "Type %s() to see the full %s text" % ((self.__name,)*2) def __call__(self): - from _pyrepl.pager import get_pager + try: + from _pyrepl.pager import get_pager + except ModuleNotFoundError: + try: + from pydoc import get_pager + except ModuleNotFoundError: + def get_pager(): + def _print(text, title=None): + print(text) + return _print + self.__setup() pager = get_pager() diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py index 44667efc522..0bf3bdded40 100644 --- a/Lib/asyncio/__main__.py +++ b/Lib/asyncio/__main__.py @@ -12,13 +12,16 @@ import types import warnings -from _colorize import get_theme -from _pyrepl.console import InteractiveColoredConsole +try: + from _colorize import get_theme + from _pyrepl.console import InteractiveColoredConsole as InteractiveConsole +except ModuleNotFoundError: + from code import InteractiveConsole from . import futures -class AsyncIOInteractiveConsole(InteractiveColoredConsole): +class AsyncIOInteractiveConsole(InteractiveConsole): def __init__(self, locals, loop): super().__init__(locals, filename="") @@ -185,7 +188,10 @@ def interrupt(self) -> None: if os.getenv('PYTHON_BASIC_REPL'): CAN_USE_PYREPL = False else: - from _pyrepl.main import CAN_USE_PYREPL + try: + from _pyrepl.main import CAN_USE_PYREPL + except ModuleNotFoundError: + CAN_USE_PYREPL = False return_code = 0 loop = asyncio.new_event_loop() diff --git a/Lib/pdb.py b/Lib/pdb.py index b5d8f827827..7b08d2bb701 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -97,12 +97,16 @@ import selectors import threading import _colorize -import _pyrepl.utils from contextlib import ExitStack, closing, contextmanager from types import CodeType from warnings import deprecated +try: + import _pyrepl.utils +except ModuleNotFoundError: + _pyrepl = None + class Restart(Exception): """Causes a debugger to be restarted for the debugged python program.""" @@ -1097,7 +1101,7 @@ def handle_command_def(self, line): return False def _colorize_code(self, code): - if self.colorize: + if self.colorize and _pyrepl: colors = list(_pyrepl.utils.gen_colors(code)) chars, _ = _pyrepl.utils.disp_str(code, colors=colors, force_color=True) code = "".join(chars) diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 69c83e08511..a1a6aad434d 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -78,20 +78,41 @@ class or function within a module or module in a package. If the from reprlib import Repr from traceback import format_exception_only -from _pyrepl.pager import (get_pager, pipe_pager, - plain_pager, tempfile_pager, tty_pager) +try: + from _pyrepl.pager import (get_pager, pipe_pager, + plain_pager, tempfile_pager, tty_pager) -# Expose plain() as pydoc.plain() -from _pyrepl.pager import plain # noqa: F401 + # Expose plain() as pydoc.plain() + from _pyrepl.pager import plain # noqa: F401 + # --------------------------------------------------------- old names + getpager = get_pager + pipepager = pipe_pager + plainpager = plain_pager + tempfilepager = tempfile_pager + ttypager = tty_pager -# --------------------------------------------------------- old names +except ModuleNotFoundError: + # Minimal alternatives for cases where _pyrepl is absent. -getpager = get_pager -pipepager = pipe_pager -plainpager = plain_pager -tempfilepager = tempfile_pager -ttypager = tty_pager + def plain(text: str) -> str: + """Remove boldface formatting from text.""" + return re.sub('.\b', '', text) + + def plain_pager(text: str, title: str = '') -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8' + text = text.encode(encoding, 'backslashreplace').decode(encoding) + text = plain(text) + sys.stdout.write(text) + + def get_pager(): + """Unconditionally return the plain pager, since _pyrepl is absent.""" + return plain_pager + + # --------------------------------------------------------- old names + getpager = get_pager + plainpager = plain_pager # --------------------------------------------------------- common routines diff --git a/Lib/site.py b/Lib/site.py index 5f09a7dd8c9..30015b3f26b 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -529,6 +529,8 @@ def register_readline(): import _pyrepl.unix_console console_errors = _pyrepl.unix_console._error from _pyrepl.main import CAN_USE_PYREPL + except ModuleNotFoundError: + CAN_USE_PYREPL = False finally: sys.path = original_path except ImportError: diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index d4d3c7f1aef..3da662b0c4d 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -3023,6 +3023,13 @@ def force_color(color: bool): import _colorize from .os_helper import EnvironmentVarGuard + if color: + try: + import _pyrepl # noqa: F401 + except ModuleNotFoundError: + # Can't force enable color without _pyrepl, so just skip. + raise unittest.SkipTest("_pyrepl is missing") + with ( swap_attr(_colorize, "can_colorize", lambda *, file=None: color), EnvironmentVarGuard() as env, diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py index 79ef178f380..b5ec41b17f7 100644 --- a/Lib/test/test_pyclbr.py +++ b/Lib/test/test_pyclbr.py @@ -252,7 +252,8 @@ def test_others(self): ignore=('Union', '_ModuleTarget', '_ScriptTarget', '_ZipTarget', 'curframe_locals', '_InteractState', 'rlcompleter'), ) - cm('pydoc', ignore=('input', 'output',)) # properties + cm('pydoc', ignore=('input', 'output', # properties + 'getpager', 'plainpager', )) # aliases # Tests for modules inside packages cm('email.parser') diff --git a/Lib/test/test_pyrepl/__init__.py b/Lib/test/test_pyrepl/__init__.py index 2f37bff6df8..1534d63352c 100644 --- a/Lib/test/test_pyrepl/__init__.py +++ b/Lib/test/test_pyrepl/__init__.py @@ -3,6 +3,9 @@ from test.support import import_helper, load_package_tests +import_helper.import_module("_pyrepl") + + if sys.platform != "win32": import_helper.import_module("termios") diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index 40965835bce..27cd125078e 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -426,6 +426,13 @@ def test_toplevel_contextvars_async(self): p = spawn_asyncio_repl() p.stdin.write(user_input) user_input2 = "async def set_var(): var.set('ok')\n" + try: + import _pyrepl # noqa: F401 + except ModuleNotFoundError: + # If we're going to be forced into the regular REPL, then we need an + # extra newline here. Omit it by default to catch any breakage to + # the new REPL's behavior. + user_input2 += "\n" p.stdin.write(user_input2) user_input3 = "await set_var()\n" p.stdin.write(user_input3) diff --git a/Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst b/Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst new file mode 100644 index 00000000000..b20da3b54c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst @@ -0,0 +1,3 @@ +Allows omitting the internal library ``_pyrepl`` with limited loss of +functionality. This allows complete removal of the modern REPL, which is an +unsupported configuration, but still desirable for some distributions. diff --git a/Modules/main.c b/Modules/main.c index 95ba541d98c..7731fa0c7c6 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -562,13 +562,25 @@ pymain_run_stdin(PyConfig *config) return pymain_exit_err_print(); } - if (!isatty(fileno(stdin)) - || _Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { - PyCompilerFlags cf = _PyCompilerFlags_INIT; - int run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); - return (run != 0); + int run; + if (isatty(fileno(stdin)) + && !_Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { + PyObject *pyrepl = PyImport_ImportModule("_pyrepl"); + if (pyrepl != NULL) { + run = pymain_start_pyrepl(0); + Py_DECREF(pyrepl); + return run; + } + if (!PyErr_ExceptionMatches(PyExc_ModuleNotFoundError)) { + fprintf(stderr, "Could not import _pyrepl.main\n"); + return pymain_exit_err_print(); + } + PyErr_Clear(); } - return pymain_start_pyrepl(0); + + PyCompilerFlags cf = _PyCompilerFlags_INIT; + run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); + return (run != 0); } @@ -594,14 +606,24 @@ pymain_repl(PyConfig *config, int *exitcode) return; } - if (!isatty(fileno(stdin)) - || _Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { - PyCompilerFlags cf = _PyCompilerFlags_INIT; - int run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); - *exitcode = (run != 0); - return; + if (isatty(fileno(stdin)) + && !_Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) { + PyObject *pyrepl = PyImport_ImportModule("_pyrepl"); + if (pyrepl != NULL) { + int run = pymain_start_pyrepl(1); + *exitcode = (run != 0); + Py_DECREF(pyrepl); + return; + } + if (!PyErr_ExceptionMatches(PyExc_ModuleNotFoundError)) { + PyErr_Clear(); + fprintf(stderr, "Could not import _pyrepl.main\n"); + return; + } + PyErr_Clear(); } - int run = pymain_start_pyrepl(1); + PyCompilerFlags cf = _PyCompilerFlags_INIT; + int run = PyRun_AnyFileExFlags(stdin, "", 0, &cf); *exitcode = (run != 0); return; } From 9585f509d796cc3f89e85d4cb9e52e4f10604a01 Mon Sep 17 00:00:00 2001 From: Adorilson Bezerra Date: Tue, 10 Mar 2026 14:19:24 +0000 Subject: [PATCH 066/775] gh-106318: Add examples for str.isspace() docs (#145399) --- Doc/library/stdtypes.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index c930b876b3c..bfa49b62ec5 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2247,17 +2247,34 @@ expression support in the :mod:`re` module). >>> '\t'.isprintable(), '\n'.isprintable() (False, False) + See also :meth:`isspace`. + .. method:: str.isspace() Return ``True`` if there are only whitespace characters in the string and there is at least one character, ``False`` otherwise. + For example: + + .. doctest:: + + >>> ''.isspace() + False + >>> ' '.isspace() + True + >>> '\t\n'.isspace() # TAB and BREAK LINE + True + >>> '\u3000'.isspace() # IDEOGRAPHIC SPACE + True + A character is *whitespace* if in the Unicode character database (see :mod:`unicodedata`), either its general category is ``Zs`` ("Separator, space"), or its bidirectional class is one of ``WS``, ``B``, or ``S``. + See also :meth:`isprintable`. + .. method:: str.istitle() From 1900aa9d36f49cc3fc6c6e6d50ddc8c64b01f978 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:40:10 +0200 Subject: [PATCH 067/775] Post 3.15.0a7 --- Include/patchlevel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 3cc12a2b2d3..7cffd74125f 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -27,7 +27,7 @@ #define PY_RELEASE_SERIAL 7 /* Version as a string */ -#define PY_VERSION "3.15.0a7" +#define PY_VERSION "3.15.0a7+" /*--end constants--*/ From 7990313afa3234d5145b32ead3ef3f6278735f4f Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 10 Mar 2026 10:57:13 -0400 Subject: [PATCH 068/775] Docs: Improve the C API documentation involving threads (GH-145520) Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- Doc/c-api/threads.rst | 218 +++++++++++++++++++++++++----------------- 1 file changed, 129 insertions(+), 89 deletions(-) diff --git a/Doc/c-api/threads.rst b/Doc/c-api/threads.rst index 41c7fbda230..3b761d0c657 100644 --- a/Doc/c-api/threads.rst +++ b/Doc/c-api/threads.rst @@ -10,43 +10,63 @@ Thread states and the global interpreter lock single: interpreter lock single: lock, interpreter -Unless on a :term:`free-threaded ` build of :term:`CPython`, -the Python interpreter is not fully thread-safe. In order to support +Unless on a :term:`free-threaded build` of :term:`CPython`, +the Python interpreter is generally not thread-safe. In order to support multi-threaded Python programs, there's a global lock, called the :term:`global -interpreter lock` or :term:`GIL`, that must be held by the current thread before -it can safely access Python objects. Without the lock, even the simplest -operations could cause problems in a multi-threaded program: for example, when +interpreter lock` or :term:`GIL`, that must be held by a thread before +accessing Python objects. Without the lock, even the simplest operations +could cause problems in a multi-threaded program: for example, when two threads simultaneously increment the reference count of the same object, the reference count could end up being incremented only once instead of twice. +As such, only a thread that holds the GIL may operate on Python objects or +invoke Python's C API. + .. index:: single: setswitchinterval (in module sys) -Therefore, the rule exists that only the thread that has acquired the -:term:`GIL` may operate on Python objects or call Python/C API functions. -In order to emulate concurrency of execution, the interpreter regularly -tries to switch threads (see :func:`sys.setswitchinterval`). The lock is also -released around potentially blocking I/O operations like reading or writing -a file, so that other Python threads can run in the meantime. +In order to emulate concurrency, the interpreter regularly tries to switch +threads between bytecode instructions (see :func:`sys.setswitchinterval`). +This is why locks are also necessary for thread-safety in pure-Python code. + +Additionally, the global interpreter lock is released around blocking I/O +operations, such as reading or writing to a file. From the C API, this is done +by :ref:`detaching the thread state `. + .. index:: single: PyThreadState (C type) -The Python interpreter keeps some thread-specific bookkeeping information -inside a data structure called :c:type:`PyThreadState`, known as a :term:`thread state`. -Each OS thread has a thread-local pointer to a :c:type:`PyThreadState`; a thread state +The Python interpreter keeps some thread-local information inside +a data structure called :c:type:`PyThreadState`, known as a :term:`thread state`. +Each thread has a thread-local pointer to a :c:type:`PyThreadState`; a thread state referenced by this pointer is considered to be :term:`attached `. A thread can only have one :term:`attached thread state` at a time. An attached -thread state is typically analogous with holding the :term:`GIL`, except on -:term:`free-threaded ` builds. On builds with the :term:`GIL` enabled, -:term:`attaching ` a thread state will block until the :term:`GIL` -can be acquired. However, even on builds with the :term:`GIL` disabled, it is still required -to have an attached thread state to call most of the C API. +thread state is typically analogous with holding the GIL, except on +free-threaded builds. On builds with the GIL enabled, attaching a thread state +will block until the GIL can be acquired. However, even on builds with the GIL +disabled, it is still required to have an attached thread state, as the interpreter +needs to keep track of which threads may access Python objects. -In general, there will always be an :term:`attached thread state` when using Python's C API. -Only in some specific cases (such as in a :c:macro:`Py_BEGIN_ALLOW_THREADS` block) will the -thread not have an attached thread state. If uncertain, check if :c:func:`PyThreadState_GetUnchecked` returns -``NULL``. +.. note:: + + Even on the free-threaded build, attaching a thread state may block, as the + GIL can be re-enabled or threads might be temporarily suspended (such as during + a garbage collection). + +Generally, there will always be an attached thread state when using Python's +C API, including during embedding and when implementing methods, so it's uncommon +to need to set up a thread state on your own. Only in some specific cases, such +as in a :c:macro:`Py_BEGIN_ALLOW_THREADS` block or in a fresh thread, will the +thread not have an attached thread state. +If uncertain, check if :c:func:`PyThreadState_GetUnchecked` returns ``NULL``. + +If it turns out that you do need to create a thread state, call :c:func:`PyThreadState_New` +followed by :c:func:`PyThreadState_Swap`, or use the dangerous +:c:func:`PyGILState_Ensure` function. + + +.. _detaching-thread-state: Detaching the thread state from extension code ---------------------------------------------- @@ -86,28 +106,37 @@ The block above expands to the following code:: Here is how these functions work: -The :term:`attached thread state` holds the :term:`GIL` for the entire interpreter. When detaching -the :term:`attached thread state`, the :term:`GIL` is released, allowing other threads to attach -a thread state to their own thread, thus getting the :term:`GIL` and can start executing. -The pointer to the prior :term:`attached thread state` is stored as a local variable. -Upon reaching :c:macro:`Py_END_ALLOW_THREADS`, the thread state that was -previously :term:`attached ` is passed to :c:func:`PyEval_RestoreThread`. -This function will block until another releases its :term:`thread state `, -thus allowing the old :term:`thread state ` to get re-attached and the -C API can be called again. +The attached thread state implies that the GIL is held for the interpreter. +To detach it, :c:func:`PyEval_SaveThread` is called and the result is stored +in a local variable. -For :term:`free-threaded ` builds, the :term:`GIL` is normally -out of the question, but detaching the :term:`thread state ` is still required -for blocking I/O and long operations. The difference is that threads don't have to wait for the :term:`GIL` -to be released to attach their thread state, allowing true multi-core parallelism. +By detaching the thread state, the GIL is released, which allows other threads +to attach to the interpreter and execute while the current thread performs +blocking I/O. When the I/O operation is complete, the old thread state is +reattached by calling :c:func:`PyEval_RestoreThread`, which will wait until +the GIL can be acquired. .. note:: - Calling system I/O functions is the most common use case for detaching - the :term:`thread state `, but it can also be useful before calling - long-running computations which don't need access to Python objects, such - as compression or cryptographic functions operating over memory buffers. + Performing blocking I/O is the most common use case for detaching + the thread state, but it is also useful to call it over long-running + native code that doesn't need access to Python objects or Python's C API. For example, the standard :mod:`zlib` and :mod:`hashlib` modules detach the - :term:`thread state ` when compressing or hashing data. + :term:`thread state ` when compressing or hashing + data. + +On a :term:`free-threaded build`, the :term:`GIL` is usually out of the question, +but **detaching the thread state is still required**, because the interpreter +periodically needs to block all threads to get a consistent view of Python objects +without the risk of race conditions. +For example, CPython currently suspends all threads for a short period of time +while running the garbage collector. + +.. warning:: + + Detaching the thread state can lead to unexpected behavior during interpreter + finalization. See :ref:`cautions-regarding-runtime-finalization` for more + details. + APIs ^^^^ @@ -149,28 +178,74 @@ example usage in the Python source distribution. declaration. -.. _gilstate: - Non-Python created threads -------------------------- When threads are created using the dedicated Python APIs (such as the -:mod:`threading` module), a thread state is automatically associated to them -and the code shown above is therefore correct. However, when threads are -created from C (for example by a third-party library with its own thread -management), they don't hold the :term:`GIL`, because they don't have an -:term:`attached thread state`. +:mod:`threading` module), a thread state is automatically associated with them, +However, when a thread is created from native code (for example, by a +third-party library with its own thread management), it doesn't hold an +attached thread state. If you need to call Python code from these threads (often this will be part of a callback API provided by the aforementioned third-party library), you must first register these threads with the interpreter by -creating an :term:`attached thread state` before you can start using the Python/C -API. When you are done, you should detach the :term:`thread state `, and -finally free it. +creating a new thread state and attaching it. -The :c:func:`PyGILState_Ensure` and :c:func:`PyGILState_Release` functions do -all of the above automatically. The typical idiom for calling into Python -from a C thread is:: +The most robust way to do this is through :c:func:`PyThreadState_New` followed +by :c:func:`PyThreadState_Swap`. + +.. note:: + ``PyThreadState_New`` requires an argument pointing to the desired + interpreter; such a pointer can be acquired via a call to + :c:func:`PyInterpreterState_Get` from the code where the thread was + created. + +For example:: + + /* The return value of PyInterpreterState_Get() from the + function that created this thread. */ + PyInterpreterState *interp = thread_data->interp; + + /* Create a new thread state for the interpreter. It does not start out + attached. */ + PyThreadState *tstate = PyThreadState_New(interp); + + /* Attach the thread state, which will acquire the GIL. */ + PyThreadState_Swap(tstate); + + /* Perform Python actions here. */ + result = CallSomeFunction(); + /* evaluate result or handle exception */ + + /* Destroy the thread state. No Python API allowed beyond this point. */ + PyThreadState_Clear(tstate); + PyThreadState_DeleteCurrent(); + +.. warning:: + + If the interpreter finalized before ``PyThreadState_Swap`` was called, then + ``interp`` will be a dangling pointer! + +.. _gilstate: + +Legacy API +---------- + +Another common pattern to call Python code from a non-Python thread is to use +:c:func:`PyGILState_Ensure` followed by a call to :c:func:`PyGILState_Release`. + +These functions do not work well when multiple interpreters exist in the Python +process. If no Python interpreter has ever been used in the current thread (which +is common for threads created outside Python), ``PyGILState_Ensure`` will create +and attach a thread state for the "main" interpreter (the first interpreter in +the Python process). + +Additionally, these functions have thread-safety issues during interpreter +finalization. Using ``PyGILState_Ensure`` during finalization will likely +crash the process. + +Usage of these functions look like such:: PyGILState_STATE gstate; gstate = PyGILState_Ensure(); @@ -182,41 +257,6 @@ from a C thread is:: /* Release the thread. No Python API allowed beyond this point. */ PyGILState_Release(gstate); -Note that the ``PyGILState_*`` functions assume there is only one global -interpreter (created automatically by :c:func:`Py_Initialize`). Python -supports the creation of additional interpreters (using -:c:func:`Py_NewInterpreter`), but mixing multiple interpreters and the -``PyGILState_*`` API is unsupported. This is because :c:func:`PyGILState_Ensure` -and similar functions default to :term:`attaching ` a -:term:`thread state` for the main interpreter, meaning that the thread can't safely -interact with the calling subinterpreter. - -Supporting subinterpreters in non-Python threads ------------------------------------------------- - -If you would like to support subinterpreters with non-Python created threads, you -must use the ``PyThreadState_*`` API instead of the traditional ``PyGILState_*`` -API. - -In particular, you must store the interpreter state from the calling -function and pass it to :c:func:`PyThreadState_New`, which will ensure that -the :term:`thread state` is targeting the correct interpreter:: - - /* The return value of PyInterpreterState_Get() from the - function that created this thread. */ - PyInterpreterState *interp = ThreadData->interp; - PyThreadState *tstate = PyThreadState_New(interp); - PyThreadState_Swap(tstate); - - /* GIL of the subinterpreter is now held. - Perform Python actions here. */ - result = CallSomeFunction(); - /* evaluate result or handle exception */ - - /* Destroy the thread state. No Python API allowed beyond this point. */ - PyThreadState_Clear(tstate); - PyThreadState_DeleteCurrent(); - .. _fork-and-threads: From 467507a651e351712f18fcafad64d1b5eed89b7d Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Tue, 10 Mar 2026 11:21:33 -0400 Subject: [PATCH 069/775] gh-145697: Add `.sql` and `.sqlite3` recognition in `mimetypes` (GH-145698) Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Co-authored-by: Benedikt Johannes --- Doc/whatsnew/3.15.rst | 2 ++ Lib/mimetypes.py | 3 +++ Lib/test/test_mimetypes.py | 2 ++ .../Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst | 1 + 4 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index ead4e7cbf28..e749ef2a455 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -825,6 +825,8 @@ mimetypes * Add ``application/node`` MIME type for ``.cjs`` extension. (Contributed by John Franey in :gh:`140937`.) * Add ``application/toml``. (Contributed by Gil Forcada in :gh:`139959`.) +* Add ``application/sql`` and ``application/vnd.sqlite3``. + (Contributed by Charlie Lin in :gh:`145698`.) * Add ``image/jxl``. (Contributed by Foolbar in :gh:`144213`.) * Rename ``application/x-texinfo`` to ``application/texinfo``. (Contributed by Charlie Lin in :gh:`140165`.) diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index fc916c470a0..ee66160be63 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -501,6 +501,7 @@ def _default_mime_types(): '.ps' : 'application/postscript', '.eps' : 'application/postscript', '.rtf' : 'application/rtf', + '.sql' : 'application/sql', '.texi' : 'application/texinfo', '.texinfo': 'application/texinfo', '.toml' : 'application/toml', @@ -525,6 +526,8 @@ def _default_mime_types(): '.xlsx' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', '.docx' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', '.rar' : 'application/vnd.rar', + '.sqlite3': 'application/vnd.sqlite3', + '.sqlite' : 'application/vnd.sqlite3', '.wasm' : 'application/wasm', '.7z' : 'application/x-7z-compressed', '.bcpio' : 'application/x-bcpio', diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index fe7584f1f9d..2d618081521 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -232,6 +232,7 @@ def check_extensions(): ("application/pdf", ".pdf"), ("application/postscript", ".ps"), ("application/rtf", ".rtf"), + ("application/sql", ".sql"), ("application/texinfo", ".texi"), ("application/toml", ".toml"), ("application/vnd.apple.mpegurl", ".m3u"), @@ -246,6 +247,7 @@ def check_extensions(): ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx"), ("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx"), ("application/vnd.rar", ".rar"), + ("application/vnd.sqlite3", ".sqlite3"), ("application/x-7z-compressed", ".7z"), ("application/x-debian-package", ".deb"), ("application/x-httpd-php", ".php"), diff --git a/Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst b/Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst new file mode 100644 index 00000000000..c3a476df75f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst @@ -0,0 +1 @@ +Add ``application/sql`` and ``application/vnd.sqlite3`` into ``mimetypes``. From 2114da976c3d85a85283d1a9437bdf8604626be8 Mon Sep 17 00:00:00 2001 From: Ali Towaiji <145403626+Towaiji@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:48:41 -0400 Subject: [PATCH 070/775] gh-145591: Move slicing note to __getitem__ (GH-145606) --- Doc/reference/datamodel.rst | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index cf5a0e71a10..062d301f628 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -3223,21 +3223,6 @@ through the object's keys; for sequences, it should iterate through the values. .. versionadded:: 3.4 -.. index:: pair: object; slice - -.. note:: - - Slicing is done exclusively with the following three methods. A call like :: - - a[1:2] = b - - is translated to :: - - a[slice(1, 2, None)] = b - - and so forth. Missing slice items are always filled in with ``None``. - - .. method:: object.__getitem__(self, subscript) Called to implement *subscription*, that is, ``self[subscript]``. @@ -3260,6 +3245,22 @@ through the object's keys; for sequences, it should iterate through the values. should raise an :exc:`LookupError` or one of its subclasses (:exc:`IndexError` for sequences; :exc:`KeyError` for mappings). + .. index:: pair: object; slice + + .. note:: + + Slicing is handled by :meth:`!__getitem__`, :meth:`~object.__setitem__`, + and :meth:`~object.__delitem__`. + A call like :: + + a[1:2] = b + + is translated to :: + + a[slice(1, 2, None)] = b + + and so forth. Missing slice items are always filled in with ``None``. + .. note:: The sequence iteration protocol (used, for example, in :keyword:`for` From 2756d56eefe86c4df696d8c65e21e4583ffe7511 Mon Sep 17 00:00:00 2001 From: Alexander Shadchin Date: Tue, 10 Mar 2026 19:02:57 +0300 Subject: [PATCH 071/775] gh-85277: Fix building without `stropts.h` or empty `stropts.h` (#143521) --- ...6-01-08-22-27-07.gh-issue-85277.TotySi.rst | 1 + Modules/posixmodule.c | 4 +- configure | 296 +++++++++--------- configure.ac | 12 +- 4 files changed, 167 insertions(+), 146 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst diff --git a/Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst b/Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst new file mode 100644 index 00000000000..538995538d7 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst @@ -0,0 +1 @@ +Fix building without ``stropts.h`` or empty ``stropts.h`` diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index aa3d682a19b..8c360ce3b79 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9397,13 +9397,13 @@ os_openpty_impl(PyObject *module) if (_Py_set_inheritable(master_fd, 0, NULL) < 0) goto posix_error; -#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) +#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ #ifndef __hpux ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ #endif /* __hpux */ -#endif /* HAVE_CYGWIN */ +#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */ #endif /* HAVE_OPENPTY */ return Py_BuildValue("(ii)", master_fd, slave_fd); diff --git a/configure b/configure index eca5f03cdcf..95bb6ba4e84 100755 --- a/configure +++ b/configure @@ -2340,6 +2340,60 @@ fi } # ac_fn_c_try_run +# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR +# ------------------------------------------------------------------ +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. +ac_fn_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +printf %s "checking whether $as_decl_name is declared... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + eval ac_save_FLAGS=\$$6 + as_fn_append $6 " $5" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$3=yes" +else case e in #( + e) eval "$3=no" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + eval $6=\$ac_save_FLAGS + ;; +esac +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_check_decl + # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -2658,60 +2712,6 @@ printf "%s\n" "$ac_res" >&6; } } # ac_fn_c_check_func -# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR -# ------------------------------------------------------------------ -# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR -# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. -ac_fn_check_decl () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - as_decl_name=`echo $2|sed 's/ *(.*//'` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 -printf %s "checking whether $as_decl_name is declared... " >&6; } -if eval test \${$3+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` - eval ac_save_FLAGS=\$$6 - as_fn_append $6 " $5" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main (void) -{ -#ifndef $as_decl_name -#ifdef __cplusplus - (void) $as_decl_use; -#else - (void) $as_decl_name; -#endif -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - eval "$3=yes" -else case e in #( - e) eval "$3=no" ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - eval $6=\$ac_save_FLAGS - ;; -esac -fi -eval ac_res=\$$3 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_check_decl - # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including @@ -11461,12 +11461,6 @@ if test "x$ac_cv_header_spawn_h" = xyes then : printf "%s\n" "#define HAVE_SPAWN_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "stropts.h" "ac_cv_header_stropts_h" "$ac_includes_default" -if test "x$ac_cv_header_stropts_h" = xyes -then : - printf "%s\n" "#define HAVE_STROPTS_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "sys/audioio.h" "ac_cv_header_sys_audioio_h" "$ac_includes_default" if test "x$ac_cv_header_sys_audioio_h" = xyes @@ -11951,6 +11945,105 @@ fi fi +# On Linux, stropts.h may be empty +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 +printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } +if test ${ac_cv_c_undeclared_builtin_options+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_save_CFLAGS=$CFLAGS + ac_cv_c_undeclared_builtin_options='cannot detect' + for ac_arg in '' -fno-builtin; do + CFLAGS="$ac_save_CFLAGS $ac_arg" + # This test program should *not* compile successfully. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +(void) strchr; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else case e in #( + e) # This test program should compile successfully. + # No library function is consistently available on + # freestanding implementations, so test against a dummy + # declaration. Include always-available headers on the + # off chance that they somehow elicit warnings. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +extern void ac_decl (int, char *); + +int +main (void) +{ +(void) ac_decl (0, (char *) 0); + (void) ac_decl; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + if test x"$ac_arg" = x +then : + ac_cv_c_undeclared_builtin_options='none needed' +else case e in #( + e) ac_cv_c_undeclared_builtin_options=$ac_arg ;; +esac +fi + break +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + done + CFLAGS=$ac_save_CFLAGS + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 +printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } + case $ac_cv_c_undeclared_builtin_options in #( + 'cannot detect') : + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} +as_fn_error $? "cannot make $CC report undeclared builtins +See 'config.log' for more details" "$LINENO" 5; } ;; #( + 'none needed') : + ac_c_undeclared_builtin_options='' ;; #( + *) : + ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; +esac + +ac_fn_check_decl "$LINENO" "I_PUSH" "ac_cv_have_decl_I_PUSH" " + #ifdef HAVE_SYS_TYPES_H + # include + #endif + #include + +" "$ac_c_undeclared_builtin_options" "CFLAGS" +if test "x$ac_cv_have_decl_I_PUSH" = xyes +then : + + +printf "%s\n" "#define HAVE_STROPTS_H 1" >>confdefs.h + +fi + # bluetooth/bluetooth.h has been known to not compile with -std=c99. # http://permalink.gmane.org/gmane.linux.bluez.kernel/22294 SAVE_CFLAGS=$CFLAGS @@ -20608,89 +20701,6 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 -printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } -if test ${ac_cv_c_undeclared_builtin_options+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) ac_save_CFLAGS=$CFLAGS - ac_cv_c_undeclared_builtin_options='cannot detect' - for ac_arg in '' -fno-builtin; do - CFLAGS="$ac_save_CFLAGS $ac_arg" - # This test program should *not* compile successfully. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main (void) -{ -(void) strchr; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -else case e in #( - e) # This test program should compile successfully. - # No library function is consistently available on - # freestanding implementations, so test against a dummy - # declaration. Include always-available headers on the - # off chance that they somehow elicit warnings. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include -extern void ac_decl (int, char *); - -int -main (void) -{ -(void) ac_decl (0, (char *) 0); - (void) ac_decl; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - if test x"$ac_arg" = x -then : - ac_cv_c_undeclared_builtin_options='none needed' -else case e in #( - e) ac_cv_c_undeclared_builtin_options=$ac_arg ;; -esac -fi - break -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - done - CFLAGS=$ac_save_CFLAGS - ;; -esac -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 -printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } - case $ac_cv_c_undeclared_builtin_options in #( - 'cannot detect') : - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} -as_fn_error $? "cannot make $CC report undeclared builtins -See 'config.log' for more details" "$LINENO" 5; } ;; #( - 'none needed') : - ac_c_undeclared_builtin_options='' ;; #( - *) : - ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; -esac - ac_fn_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "#include #include " "$ac_c_undeclared_builtin_options" "CFLAGS" diff --git a/configure.ac b/configure.ac index c21024a1e77..e049f568417 100644 --- a/configure.ac +++ b/configure.ac @@ -3011,7 +3011,7 @@ AC_CHECK_HEADERS([ \ io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/limits.h linux/memfd.h \ linux/netfilter_ipv4.h linux/random.h linux/soundcard.h linux/sched.h \ linux/tipc.h linux/wait.h netdb.h net/ethernet.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ - sched.h setjmp.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \ + sched.h setjmp.h shadow.h signal.h spawn.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \ sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \ sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/pidfd.h sys/poll.h \ sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \ @@ -3022,6 +3022,16 @@ AC_CHECK_HEADERS([ \ AC_HEADER_DIRENT AC_HEADER_MAJOR +# On Linux, stropts.h may be empty +AC_CHECK_DECL([I_PUSH], [ + AC_DEFINE([HAVE_STROPTS_H], [1], + [Define to 1 if you have the header file.])], [], [ + #ifdef HAVE_SYS_TYPES_H + # include + #endif + #include +]) + # bluetooth/bluetooth.h has been known to not compile with -std=c99. # http://permalink.gmane.org/gmane.linux.bluez.kernel/22294 SAVE_CFLAGS=$CFLAGS From bf4017b16149ba17d723abacfe93aec79b2235fe Mon Sep 17 00:00:00 2001 From: Farhan Saif Date: Tue, 10 Mar 2026 11:23:39 -0500 Subject: [PATCH 072/775] gh-125053: Document that ob_mutex must only be used via critical section API (#144599) Add a warning in the free-threading extensions howto explaining that PyObject.ob_mutex is reserved for the critical section API and must not be locked directly with PyMutex_Lock, as this can cause deadlocks. Extension authors who need their own lock should add a separate PyMutex field to their object struct. Also add an ob_mutex member entry under PyObject in the C API reference (Doc/c-api/structures.rst) with a cross-reference to the howto. Co-authored-by: Victor Stinner --- Doc/c-api/structures.rst | 13 +++++++++++++ Doc/howto/free-threading-extensions.rst | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 70c4de543b7..c0d2663adef 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -48,6 +48,19 @@ under :ref:`reference counting `. Do not use this field directly; use :c:macro:`Py_TYPE` and :c:func:`Py_SET_TYPE` instead. + .. c:member:: PyMutex ob_mutex + + A :ref:`per-object lock `, present only in the :term:`free-threaded ` + build (when :c:macro:`Py_GIL_DISABLED` is defined). + + This field is **reserved for use by the critical section API** + (:c:macro:`Py_BEGIN_CRITICAL_SECTION` / :c:macro:`Py_END_CRITICAL_SECTION`). + Do **not** lock it directly with ``PyMutex_Lock``; doing so can cause + deadlocks. If you need your own lock, add a separate :c:type:`PyMutex` + field to your object struct. + + .. versionadded:: 3.13 + .. c:type:: PyVarObject diff --git a/Doc/howto/free-threading-extensions.rst b/Doc/howto/free-threading-extensions.rst index 83eba8cfea3..2f089a3d896 100644 --- a/Doc/howto/free-threading-extensions.rst +++ b/Doc/howto/free-threading-extensions.rst @@ -384,6 +384,30 @@ Important Considerations internal extension state, standard mutexes or other synchronization primitives might be more appropriate. +.. _per-object-locks: + +Per-Object Locks (``ob_mutex``) +............................... + +In the free-threaded build, each Python object contains a :c:member:`~PyObject.ob_mutex` +field of type :c:type:`PyMutex`. This mutex is **reserved for use by the +critical section API** (:c:macro:`Py_BEGIN_CRITICAL_SECTION` / +:c:macro:`Py_END_CRITICAL_SECTION`). + +.. warning:: + + Do **not** lock ``ob_mutex`` directly with ``PyMutex_Lock(&obj->ob_mutex)``. + Mixing direct ``PyMutex_Lock`` calls with the critical section API on the + same mutex can cause deadlocks. + +Even if your own code never uses critical sections on a particular object type, +**CPython internals may use the critical section API on any Python object**. + +If your extension type needs its own lock, add a separate :c:type:`PyMutex` +field (or another synchronization primitive) to your object struct. +:c:type:`PyMutex` is very lightweight, so there is negligible cost to having +an additional one. + Building Extensions for the Free-Threaded Build =============================================== From 3f33bf83e8496737b86333bc9ec55dc3ccb3faca Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 10 Mar 2026 18:29:23 +0200 Subject: [PATCH 073/775] gh-145743: Fix inconsistency after calling Struct.__init__() with invalid format (GH-145744) Only set the format attribute after successful (re-)initialization. --- Lib/test/test_struct.py | 20 ++++++++++++++++++-- Modules/_struct.c | 29 +++++++++++++++-------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 4cbfd7ad8b1..6904572d095 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -584,8 +584,24 @@ def test_Struct_reinitialization(self): # Issue 9422: there was a memory leak when reinitializing a # Struct instance. This test can be used to detect the leak # when running with regrtest -L. - s = struct.Struct('i') - s.__init__('ii') + s = struct.Struct('>h') + s.__init__('>hh') + self.assertEqual(s.format, '>hh') + packed = b'\x00\x01\x00\x02' + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) + + with self.assertRaises(UnicodeEncodeError): + s.__init__('\udc00') + self.assertEqual(s.format, '>hh') + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) + + with self.assertRaises(struct.error): + s.__init__('$') + self.assertEqual(s.format, '>hh') + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) def check_sizeof(self, format_str, number_of_codes): # The size of 'PyStructObject' diff --git a/Modules/_struct.c b/Modules/_struct.c index dcc3c7ec63e..c2f7b1fe0e8 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1620,11 +1620,11 @@ align(Py_ssize_t size, char c, const formatdef *e) /* calculate the size of a format string */ static int -prepare_s(PyStructObject *self) +prepare_s(PyStructObject *self, PyObject *format) { const formatdef *f; const formatdef *e; - formatcode *codes; + formatcode *codes, *codes0; const char *s; const char *fmt; @@ -1634,8 +1634,8 @@ prepare_s(PyStructObject *self) _structmodulestate *state = get_struct_state_structinst(self); - fmt = PyBytes_AS_STRING(self->s_format); - if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(self->s_format)) { + fmt = PyBytes_AS_STRING(format); + if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(format)) { PyErr_SetString(state->StructError, "embedded null character"); return -1; @@ -1711,13 +1711,7 @@ prepare_s(PyStructObject *self) PyErr_NoMemory(); return -1; } - /* Free any s_codes value left over from a previous initialization. */ - if (self->s_codes != NULL) - PyMem_Free(self->s_codes); - self->s_codes = codes; - self->s_size = size; - self->s_len = len; - + codes0 = codes; s = fmt; size = 0; while ((c = *s++) != '\0') { @@ -1757,6 +1751,14 @@ prepare_s(PyStructObject *self) codes->size = 0; codes->repeat = 0; + /* Free any s_codes value left over from a previous initialization. */ + if (self->s_codes != NULL) + PyMem_Free(self->s_codes); + self->s_codes = codes0; + self->s_size = size; + self->s_len = len; + Py_XSETREF(self->s_format, Py_NewRef(format)); + return 0; overflow: @@ -1820,9 +1822,8 @@ Struct___init___impl(PyStructObject *self, PyObject *format) return -1; } - Py_SETREF(self->s_format, format); - - ret = prepare_s(self); + ret = prepare_s(self, format); + Py_DECREF(format); return ret; } From 9e0802330caca51fed7fc0c8c1dcce2daf03d8bd Mon Sep 17 00:00:00 2001 From: bkap123 <97006829+bkap123@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:30:11 -0400 Subject: [PATCH 074/775] gh-145036: Fix data race for list capacity in free-threading (#145365) Co-authored-by: Kumar Aditya --- Lib/test/test_free_threading/test_list.py | 21 +++++++++++++++++++ ...-02-28-18-42-36.gh-issue-145036.70Kbfz.rst | 1 + Objects/listobject.c | 10 +++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst diff --git a/Lib/test/test_free_threading/test_list.py b/Lib/test/test_free_threading/test_list.py index 27ddc9c2d26..0ede4df103f 100644 --- a/Lib/test/test_free_threading/test_list.py +++ b/Lib/test/test_free_threading/test_list.py @@ -149,6 +149,27 @@ def reader_list(b, l): with threading_helper.start_threads(threads): pass + # gh-145036: race condition with list.__sizeof__() + def test_list_sizeof_free_threaded_build(self): + L = [] + + def mutate_function(): + for _ in range(100): + L.append(1) + L.pop() + + def size_function(): + for _ in range(100): + L.__sizeof__() + + threads = [] + for _ in range(4): + threads.append(Thread(target=mutate_function)) + threads.append(Thread(target=size_function)) + + with threading_helper.start_threads(threads): + pass + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst new file mode 100644 index 00000000000..2a565c1d02b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst @@ -0,0 +1 @@ +In free-threaded build, fix race condition when calling :meth:`!__sizeof__` on a :class:`list` diff --git a/Objects/listobject.c b/Objects/listobject.c index 7fc21907fef..62d04ab150a 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3582,8 +3582,14 @@ list___sizeof___impl(PyListObject *self) /*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/ { size_t res = _PyObject_SIZE(Py_TYPE(self)); - Py_ssize_t allocated = FT_ATOMIC_LOAD_SSIZE_RELAXED(self->allocated); - res += (size_t)allocated * sizeof(void*); +#ifdef Py_GIL_DISABLED + PyObject **ob_item = _Py_atomic_load_ptr(&self->ob_item); + if (ob_item != NULL) { + res += list_capacity(ob_item) * sizeof(PyObject *); + } +#else + res += (size_t)self->allocated * sizeof(PyObject *); +#endif return PyLong_FromSize_t(res); } From 50f82d062b3b59a09d6b63648df22d46f7f2b010 Mon Sep 17 00:00:00 2001 From: Benedikt Johannes Date: Tue, 10 Mar 2026 17:33:56 +0100 Subject: [PATCH 075/775] gh-145044: avoid calling `Py_DECREF` in `unsafe_object_compare` on immortal objects (#145045) --- Objects/listobject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Objects/listobject.c b/Objects/listobject.c index 62d04ab150a..1fcedd3a28c 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2795,11 +2795,12 @@ unsafe_object_compare(PyObject *v, PyObject *w, MergeState *ms) if (PyBool_Check(res_obj)) { res = (res_obj == Py_True); + assert(_Py_IsImmortal(res_obj)); } else { res = PyObject_IsTrue(res_obj); + Py_DECREF(res_obj); } - Py_DECREF(res_obj); /* Note that we can't assert * res == PyObject_RichCompareBool(v, w, Py_LT); From c4333a12708a917d1cfb6418c04be45793ecc392 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 10 Mar 2026 19:40:51 +0300 Subject: [PATCH 076/775] gh-144173: fix flaky test_complex.test_truediv() (#144355) Previously, component-wise relative error bound was tested. However, such bound can't exist already for complex multiplication as one can be used to perform subtraction of floating-point numbers, e.g. x and y for z0=1+1j and z1=x+yj. ```pycon >>> x, y = 1e-9+1j, 1+1j >>> a = x*y*y.conjugate()/2;a (1.0000000272292198e-09+1j) >>> b = x*(y*y.conjugate()/2);b (1e-09+1j) >>> b == x True >>> (a.real-b.real)/math.ulp(b.real) 131672427.0 ``` --- Lib/test/test_complex.py | 41 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index 0c7e7341f13..bee2aceb187 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -72,8 +72,8 @@ def assertAlmostEqual(self, a, b): else: unittest.TestCase.assertAlmostEqual(self, a, b) - def assertCloseAbs(self, x, y, eps=1e-9): - """Return true iff floats x and y "are close".""" + def assertClose(self, x, y, eps=1e-9): + """Return true iff complexes x and y "are close".""" # put the one with larger magnitude second if abs(x) > abs(y): x, y = y, x @@ -82,26 +82,15 @@ def assertCloseAbs(self, x, y, eps=1e-9): if x == 0: return abs(y) < eps # check that relative difference < eps - self.assertTrue(abs((x-y)/y) < eps) - - def assertClose(self, x, y, eps=1e-9): - """Return true iff complexes x and y "are close".""" - self.assertCloseAbs(x.real, y.real, eps) - self.assertCloseAbs(x.imag, y.imag, eps) + self.assertTrue(abs(x-y)/abs(y) < eps) def check_div(self, x, y): """Compute complex z=x*y, and check that z/x==y and z/y==x.""" z = x * y - if x != 0: - q = z / x - self.assertClose(q, y) - q = z.__truediv__(x) - self.assertClose(q, y) - if y != 0: - q = z / y - self.assertClose(q, x) - q = z.__truediv__(y) - self.assertClose(q, x) + if x: + self.assertClose(z / x, y) + if y: + self.assertClose(z / y, x) def test_truediv(self): simple_real = [float(i) for i in range(-5, 6)] @@ -115,10 +104,20 @@ def test_truediv(self): self.check_div(complex(1e200, 1e200), 1+0j) self.check_div(complex(1e-200, 1e-200), 1+0j) + # Smith's algorithm has several sources of inaccuracy + # for components of the result. In examples below, + # it's cancellation of digits in computation of sum. + self.check_div(1e-09+1j, 1+1j) + self.check_div(8.289760544677449e-09+0.13257307440728516j, + 0.9059966714925808+0.5054864708672686j) + # Just for fun. for i in range(100): - self.check_div(complex(random(), random()), - complex(random(), random())) + x = complex(random(), random()) + y = complex(random(), random()) + self.check_div(x, y) + y = complex(1e10*y.real, y.imag) + self.check_div(x, y) self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j) self.assertRaises(TypeError, operator.truediv, 1j, None) @@ -454,7 +453,7 @@ def test_boolcontext(self): self.assertTrue(1j) def test_conjugate(self): - self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j) + self.assertEqual(complex(5.3, 9.8).conjugate(), 5.3-9.8j) def test_constructor(self): def check(z, x, y): From f26eca7732ca9d0e6893e3fdfdfd4c25339c7155 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 10 Mar 2026 12:47:12 -0400 Subject: [PATCH 077/775] gh-145685: Update find_name_in_mro() to return a _PyStackRef (gh-145693) --- Objects/typeobject.c | 80 +++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 81abb0990ee..5dc96bf251b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5978,15 +5978,16 @@ PyObject_GetItemData(PyObject *obj) } /* Internal API to look for a name through the MRO, bypassing the method cache. - This returns a borrowed reference, and might set an exception. - 'error' is set to: -1: error with exception; 1: error without exception; 0: ok */ -static PyObject * -find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) + The result is stored as a _PyStackRef in `out`. It never set an exception. + Returns -1 if there was an error, 0 if the name was not found, and 1 if + the name was found. */ +static int +find_name_in_mro(PyTypeObject *type, PyObject *name, _PyStackRef *out) { Py_hash_t hash = _PyObject_HashFast(name); if (hash == -1) { - *error = -1; - return NULL; + PyErr_Clear(); + return -1; } /* Look in tp_dict of types in MRO */ @@ -5994,37 +5995,42 @@ find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) if (mro == NULL) { if (!is_readying(type)) { if (PyType_Ready(type) < 0) { - *error = -1; - return NULL; + PyErr_Clear(); + return -1; } mro = lookup_tp_mro(type); } if (mro == NULL) { - *error = 1; - return NULL; + return -1; } } - PyObject *res = NULL; + int res = 0; + PyThreadState *tstate = _PyThreadState_GET(); /* Keep a strong reference to mro because type->tp_mro can be replaced during dict lookup, e.g. when comparing to non-string keys. */ - Py_INCREF(mro); + _PyCStackRef mro_ref; + _PyThreadState_PushCStackRef(tstate, &mro_ref); + mro_ref.ref = PyStackRef_FromPyObjectNew(mro); Py_ssize_t n = PyTuple_GET_SIZE(mro); for (Py_ssize_t i = 0; i < n; i++) { PyObject *base = PyTuple_GET_ITEM(mro, i); PyObject *dict = lookup_tp_dict(_PyType_CAST(base)); assert(dict && PyDict_Check(dict)); - if (_PyDict_GetItemRef_KnownHash((PyDictObject *)dict, name, hash, &res) < 0) { - *error = -1; + Py_ssize_t ix = _Py_dict_lookup_threadsafe_stackref( + (PyDictObject *)dict, name, hash, out); + if (ix == DKIX_ERROR) { + PyErr_Clear(); + res = -1; goto done; } - if (res != NULL) { + if (!PyStackRef_IsNull(*out)) { + res = 1; break; } } - *error = 0; done: - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return res; } @@ -6179,11 +6185,11 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef // We need to atomically do the lookup and capture the version before // anyone else can modify our mro or mutate the type. - PyObject *res; - int error; + int res; PyInterpreterState *interp = _PyInterpreterState_GET(); int has_version = 0; unsigned int assigned_version = 0; + BEGIN_TYPE_LOCK(); // We must assign the version before doing the lookup. If // find_name_in_mro() blocks and releases the critical section @@ -6192,35 +6198,24 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef has_version = assign_version_tag(interp, type); assigned_version = type->tp_version_tag; } - res = find_name_in_mro(type, name, &error); + res = find_name_in_mro(type, name, out); END_TYPE_LOCK(); /* Only put NULL results into cache if there was no error. */ - if (error) { - /* It's not ideal to clear the error condition, - but this function is documented as not setting - an exception, and I don't want to change that. - E.g., when PyType_Ready() can't proceed, it won't - set the "ready" flag, so future attempts to ready - the same type will call it again -- hopefully - in a context that propagates the exception out. - */ - if (error == -1) { - PyErr_Clear(); - } + if (res < 0) { *out = PyStackRef_NULL; return 0; } if (has_version) { + PyObject *res_obj = PyStackRef_AsPyObjectBorrow(*out); #if Py_GIL_DISABLED - update_cache_gil_disabled(entry, name, assigned_version, res); + update_cache_gil_disabled(entry, name, assigned_version, res_obj); #else - PyObject *old_value = update_cache(entry, name, assigned_version, res); + PyObject *old_value = update_cache(entry, name, assigned_version, res_obj); Py_DECREF(old_value); #endif } - *out = res ? PyStackRef_FromPyObjectSteal(res) : PyStackRef_NULL; return has_version ? assigned_version : 0; } @@ -11709,7 +11704,6 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, int use_generic = 0; int offset = p->offset; - int error; void **ptr = slotptr(type, offset); if (ptr == NULL) { @@ -11725,19 +11719,15 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, assert(!PyErr_Occurred()); do { /* Use faster uncached lookup as we won't get any cache hits during type setup. */ - descr = find_name_in_mro(type, p->name_strobj, &error); - if (descr == NULL) { - if (error == -1) { - /* It is unlikely but not impossible that there has been an exception - during lookup. Since this function originally expected no errors, - we ignore them here in order to keep up the interface. */ - PyErr_Clear(); - } + _PyStackRef descr_ref; + int res = find_name_in_mro(type, p->name_strobj, &descr_ref); + if (res <= 0) { if (ptr == (void**)&type->tp_iternext) { specific = (void *)_PyObject_NextNotImplemented; } continue; } + descr = PyStackRef_AsPyObjectBorrow(descr_ref); if (Py_IS_TYPE(descr, &PyWrapperDescr_Type) && ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr; @@ -11815,7 +11805,7 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, } } } - Py_DECREF(descr); + PyStackRef_CLOSE(descr_ref); } while ((++p)->offset == offset); void *slot_value; From 9c1c71066e34b11649735e8acb4765a85c76336f Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 10 Mar 2026 12:55:29 -0400 Subject: [PATCH 078/775] gh-145010: Fix Python.h compilation with -masm=intel (#145011) --- Include/object.h | 6 +++--- Lib/test/test_cppext/__init__.py | 20 ++++++++++++++++--- Lib/test/test_cppext/setup.py | 4 ++++ ...-02-19-18-39-11.gh-issue-145010.mKzjci.rst | 2 ++ 4 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst diff --git a/Include/object.h b/Include/object.h index ad452be8405..3fb28035a50 100644 --- a/Include/object.h +++ b/Include/object.h @@ -206,11 +206,11 @@ _Py_ThreadId(void) #elif defined(__MINGW32__) && defined(_M_ARM64) tid = __getReg(18); #elif defined(__i386__) - __asm__("movl %%gs:0, %0" : "=r" (tid)); // 32-bit always uses GS + __asm__("{movl %%gs:0, %0|mov %0, dword ptr gs:[0]}" : "=r" (tid)); // 32-bit always uses GS #elif defined(__MACH__) && defined(__x86_64__) - __asm__("movq %%gs:0, %0" : "=r" (tid)); // x86_64 macOSX uses GS + __asm__("{movq %%gs:0, %0|mov %0, qword ptr gs:[0]}" : "=r" (tid)); // x86_64 macOSX uses GS #elif defined(__x86_64__) - __asm__("movq %%fs:0, %0" : "=r" (tid)); // x86_64 Linux, BSD uses FS + __asm__("{movq %%fs:0, %0|mov %0, qword ptr fs:[0]}" : "=r" (tid)); // x86_64 Linux, BSD uses FS #elif defined(__arm__) && __ARM_ARCH >= 7 __asm__ ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tid)); #elif defined(__aarch64__) && defined(__APPLE__) diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py index 1fd01702f64..5b4c97c181b 100644 --- a/Lib/test/test_cppext/__init__.py +++ b/Lib/test/test_cppext/__init__.py @@ -1,6 +1,7 @@ # gh-91321: Build a basic C++ test extension to check that the Python C API is # compatible with C++ and does not emit C++ compiler warnings. import os.path +import platform import shlex import shutil import subprocess @@ -28,13 +29,16 @@ class BaseTests: TEST_INTERNAL_C_API = False - def check_build(self, extension_name, std=None, limited=False): + def check_build(self, extension_name, std=None, limited=False, + extra_cflags=None): venv_dir = 'env' with support.setup_venv_with_pip_setuptools(venv_dir) as python_exe: self._check_build(extension_name, python_exe, - std=std, limited=limited) + std=std, limited=limited, + extra_cflags=extra_cflags) - def _check_build(self, extension_name, python_exe, std, limited): + def _check_build(self, extension_name, python_exe, std, limited, + extra_cflags=None): pkg_dir = 'pkg' os.mkdir(pkg_dir) shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP))) @@ -48,6 +52,8 @@ def run_cmd(operation, cmd): env['CPYTHON_TEST_LIMITED'] = '1' env['CPYTHON_TEST_EXT_NAME'] = extension_name env['TEST_INTERNAL_C_API'] = str(int(self.TEST_INTERNAL_C_API)) + if extra_cflags: + env['CPYTHON_TEST_EXTRA_CFLAGS'] = extra_cflags if support.verbose: print('Run:', ' '.join(map(shlex.quote, cmd))) subprocess.run(cmd, check=True, env=env) @@ -116,6 +122,14 @@ def test_build_cpp11(self): def test_build_cpp14(self): self.check_build('_testcpp14ext', std='c++14') + # Test that headers compile with Intel asm syntax, which may conflict + # with inline assembly in free-threading headers that use AT&T syntax. + @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support -masm=intel") + @unittest.skipUnless(platform.machine() in ('x86_64', 'i686', 'AMD64'), + "x86-specific flag") + def test_build_intel_asm(self): + self.check_build('_testcppext_asm', extra_cflags='-masm=intel') + class TestInteralCAPI(BaseTests, unittest.TestCase): TEST_INTERNAL_C_API = True diff --git a/Lib/test/test_cppext/setup.py b/Lib/test/test_cppext/setup.py index 2d9052a6b87..14aeafefcaa 100644 --- a/Lib/test/test_cppext/setup.py +++ b/Lib/test/test_cppext/setup.py @@ -86,6 +86,10 @@ def main(): if internal: cppflags.append('-DTEST_INTERNAL_C_API=1') + extra_cflags = os.environ.get("CPYTHON_TEST_EXTRA_CFLAGS", "") + if extra_cflags: + cppflags.extend(shlex.split(extra_cflags)) + # On Windows, add PCbuild\amd64\ to include and library directories include_dirs = [] library_dirs = [] diff --git a/Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst b/Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst new file mode 100644 index 00000000000..7f5be699c63 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst @@ -0,0 +1,2 @@ +Use GCC dialect alternatives for inline assembly in ``object.h`` so that the +Python headers compile correctly with ``-masm=intel``. From 4d0dce0c8ddc4d0321bd590a1a33990edc2e1b08 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:57:34 +0000 Subject: [PATCH 079/775] Fix integer overflow for formats "s" and "p" in the struct module (GH-145750) --- Lib/test/test_struct.py | 6 ++++++ .../2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst | 3 +++ Modules/_struct.c | 8 +++++++- 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 6904572d095..55e2ce590a2 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -555,6 +555,12 @@ def test_count_overflow(self): hugecount3 = '{}i{}q'.format(sys.maxsize // 4, sys.maxsize // 8) self.assertRaises(struct.error, struct.calcsize, hugecount3) + hugecount4 = '{}?s'.format(sys.maxsize) + self.assertRaises(struct.error, struct.calcsize, hugecount4) + + hugecount5 = '{}?p'.format(sys.maxsize) + self.assertRaises(struct.error, struct.calcsize, hugecount5) + def test_trailing_counter(self): store = array.array('b', b' '*100) diff --git a/Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst b/Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst new file mode 100644 index 00000000000..a909bea2caf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst @@ -0,0 +1,3 @@ +Avoid undefined behaviour from signed integer overflow when parsing format +strings in the :mod:`struct` module. Found by OSS Fuzz in +:oss-fuzz:`488466741`. diff --git a/Modules/_struct.c b/Modules/_struct.c index c2f7b1fe0e8..f8574322b40 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1676,7 +1676,13 @@ prepare_s(PyStructObject *self, PyObject *format) switch (c) { case 's': _Py_FALLTHROUGH; - case 'p': len++; ncodes++; break; + case 'p': + if (len == PY_SSIZE_T_MAX) { + goto overflow; + } + len++; + ncodes++; + break; case 'x': break; default: if (num > PY_SSIZE_T_MAX - len) { From 665c1db94f46f8e1a18a8c2f89adb3bc72cb83dc Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 10 Mar 2026 14:47:58 -0400 Subject: [PATCH 080/775] gh-142763: Fix race in ZoneInfo cache eviction (gh-144978) The cache may be cleared between the evaluation of the if statement and the call to popitem. --- Lib/zoneinfo/_zoneinfo.py | 6 +++++- .../2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst diff --git a/Lib/zoneinfo/_zoneinfo.py b/Lib/zoneinfo/_zoneinfo.py index 3ffdb4c8371..bd3fefc6c9d 100644 --- a/Lib/zoneinfo/_zoneinfo.py +++ b/Lib/zoneinfo/_zoneinfo.py @@ -47,7 +47,11 @@ def __new__(cls, key): cls._strong_cache[key] = cls._strong_cache.pop(key, instance) if len(cls._strong_cache) > cls._strong_cache_size: - cls._strong_cache.popitem(last=False) + try: + cls._strong_cache.popitem(last=False) + except KeyError: + # another thread may have already emptied the cache + pass return instance diff --git a/Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst b/Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst new file mode 100644 index 00000000000..a5330365e3e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst @@ -0,0 +1,2 @@ +Fix a race condition between :class:`zoneinfo.ZoneInfo` creation and +:func:`zoneinfo.ZoneInfo.clear_cache` that could raise :exc:`KeyError`. From 5197ecb5e4df30ba0f6792d8bc0e36846154f58a Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Tue, 10 Mar 2026 20:51:17 +0100 Subject: [PATCH 081/775] gh-143050: Remove redundant decref in _PyLong_Negate (gh-143051) --- Objects/longobject.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 7ce5d0535b8..185226db43a 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -48,6 +48,17 @@ _Py_DECREF_INT(PyLongObject *op) _Py_DECREF_SPECIALIZED((PyObject *)op, _PyLong_ExactDealloc); } +static inline int +/// Return 1 if the object is one of the immortal small ints +_long_is_small_int(PyObject *op) +{ + assert(PyLong_Check(op)); + PyLongObject *long_object = (PyLongObject *)op; + int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; + assert((!is_small_int) || PyLong_CheckExact(op)); + return is_small_int; +} + static inline int is_medium_int(stwodigits x) { @@ -344,8 +355,6 @@ medium_from_stwodigits(stwodigits x) } -/* If a freshly-allocated int is already shared, it must - be a small integer, so negating it must go to PyLong_FromLong */ Py_LOCAL_INLINE(void) _PyLong_Negate(PyLongObject **x_p) { @@ -357,8 +366,10 @@ _PyLong_Negate(PyLongObject **x_p) return; } - *x_p = _PyLong_FromSTwoDigits(-medium_value(x)); - Py_DECREF(x); + /* If a freshly-allocated int is already shared, it must + be a small integer, so negating it will fit a single digit */ + assert(_long_is_small_int((PyObject *)x)); + *x_p = (PyLongObject *)_PyLong_FromSTwoDigits(-medium_value(x)); } #define PYLONG_FROM_INT(UINT_TYPE, INT_TYPE, ival) \ @@ -3622,16 +3633,6 @@ long_richcompare(PyObject *self, PyObject *other, int op) Py_RETURN_RICHCOMPARE(result, 0, op); } -static inline int -/// Return 1 if the object is one of the immortal small ints -_long_is_small_int(PyObject *op) -{ - PyLongObject *long_object = (PyLongObject *)op; - int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; - assert((!is_small_int) || PyLong_CheckExact(op)); - return is_small_int; -} - void _PyLong_ExactDealloc(PyObject *self) { From ebb150e76ab4988fdcd5e8caa36b9014497573a5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 11 Mar 2026 01:43:27 +0100 Subject: [PATCH 082/775] gh-145219: Cache Emscripten build dependencies, add install-emscripten (#145664) Modifies the Emscripten build script to allow for caching of dependencies, and for automated installation of new EMSDK versions. Co-authored-by: Russell Keith-Magee --- Tools/wasm/emscripten/__main__.py | 214 +++++++++++++++---- Tools/wasm/emscripten/config.toml | 14 ++ Tools/wasm/emscripten/emscripten_version.txt | 1 - 3 files changed, 184 insertions(+), 45 deletions(-) create mode 100644 Tools/wasm/emscripten/config.toml delete mode 100644 Tools/wasm/emscripten/emscripten_version.txt diff --git a/Tools/wasm/emscripten/__main__.py b/Tools/wasm/emscripten/__main__.py index 14d32279a8c..b1a779777ae 100644 --- a/Tools/wasm/emscripten/__main__.py +++ b/Tools/wasm/emscripten/__main__.py @@ -4,6 +4,7 @@ import contextlib import functools import hashlib +import json import os import shutil import subprocess @@ -14,6 +15,8 @@ from textwrap import dedent from urllib.request import urlopen +import tomllib + try: from os import process_cpu_count as cpu_count except ImportError: @@ -22,25 +25,51 @@ EMSCRIPTEN_DIR = Path(__file__).parent CHECKOUT = EMSCRIPTEN_DIR.parent.parent.parent -EMSCRIPTEN_VERSION_FILE = EMSCRIPTEN_DIR / "emscripten_version.txt" +CONFIG_FILE = EMSCRIPTEN_DIR / "config.toml" DEFAULT_CROSS_BUILD_DIR = CHECKOUT / "cross-build" HOST_TRIPLE = "wasm32-emscripten" -def get_build_paths(cross_build_dir=None): +@functools.cache +def load_config_toml(): + with CONFIG_FILE.open("rb") as file: + return tomllib.load(file) + + +@functools.cache +def required_emscripten_version(): + return load_config_toml()["emscripten-version"] + + +@functools.cache +def emsdk_cache_root(emsdk_cache): + required_version = required_emscripten_version() + return Path(emsdk_cache).absolute() / required_version + + +@functools.cache +def emsdk_activate_path(emsdk_cache): + return emsdk_cache_root(emsdk_cache) / "emsdk/emsdk_env.sh" + + +def get_build_paths(cross_build_dir=None, emsdk_cache=None): """Compute all build paths from the given cross-build directory.""" if cross_build_dir is None: cross_build_dir = DEFAULT_CROSS_BUILD_DIR cross_build_dir = Path(cross_build_dir).absolute() host_triple_dir = cross_build_dir / HOST_TRIPLE + prefix_dir = host_triple_dir / "prefix" + if emsdk_cache: + prefix_dir = emsdk_cache_root(emsdk_cache) / "prefix" + return { "cross_build_dir": cross_build_dir, "native_build_dir": cross_build_dir / "build", "host_triple_dir": host_triple_dir, "host_build_dir": host_triple_dir / "build", "host_dir": host_triple_dir / "build" / "python", - "prefix_dir": host_triple_dir / "prefix", + "prefix_dir": prefix_dir, } @@ -48,22 +77,10 @@ def get_build_paths(cross_build_dir=None): LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n" -@functools.cache -def get_required_emscripten_version(): - """Read the required emscripten version from emscripten_version.txt.""" - return EMSCRIPTEN_VERSION_FILE.read_text().strip() - - -@functools.cache -def get_emsdk_activate_path(emsdk_cache): - required_version = get_required_emscripten_version() - return Path(emsdk_cache) / required_version / "emsdk_env.sh" - - def validate_emsdk_version(emsdk_cache): """Validate that the emsdk cache contains the required emscripten version.""" - required_version = get_required_emscripten_version() - emsdk_env = get_emsdk_activate_path(emsdk_cache) + required_version = required_emscripten_version() + emsdk_env = emsdk_activate_path(emsdk_cache) if not emsdk_env.is_file(): print( f"Required emscripten version {required_version} not found in {emsdk_cache}", @@ -90,7 +107,7 @@ def get_emsdk_environ(emsdk_cache): [ "bash", "-c", - f"EMSDK_QUIET=1 source {get_emsdk_activate_path(emsdk_cache)} && env", + f"EMSDK_QUIET=1 source {emsdk_activate_path(emsdk_cache)} && env", ], text=True, ) @@ -207,6 +224,35 @@ def build_python_path(context): return binary +def install_emscripten(context): + emsdk_cache = context.emsdk_cache + if emsdk_cache is None: + print("install-emscripten requires --emsdk-cache", file=sys.stderr) + sys.exit(1) + version = required_emscripten_version() + emsdk_target = emsdk_cache_root(emsdk_cache) / "emsdk" + if emsdk_target.exists(): + if not context.quiet: + print(f"Emscripten version {version} already installed") + return + if not context.quiet: + print(f"Installing emscripten version {version}") + emsdk_target.mkdir(parents=True) + call( + [ + "git", + "clone", + "https://github.com/emscripten-core/emsdk.git", + emsdk_target, + ], + quiet=context.quiet, + ) + call([emsdk_target / "emsdk", "install", version], quiet=context.quiet) + call([emsdk_target / "emsdk", "activate", version], quiet=context.quiet) + if not context.quiet: + print(f"Installed emscripten version {version}") + + @subdir("native_build_dir", clean_ok=True) def configure_build_python(context, working_dir): """Configure the build/host Python.""" @@ -258,35 +304,87 @@ def download_and_unpack(working_dir: Path, url: str, expected_shasum: str): shutil.unpack_archive(tmp_file.name, working_dir) +def should_build_library(prefix, name, config, quiet): + cached_config = prefix / (name + ".json") + if not cached_config.exists(): + if not quiet: + print( + f"No cached build of {name} version {config['version']} found, building" + ) + return True + + try: + with cached_config.open("rb") as f: + cached_config = json.load(f) + except json.JSONDecodeError: + if not quiet: + print(f"Cached data for {name} invalid, rebuilding") + return True + if config == cached_config: + if not quiet: + print( + f"Found cached build of {name} version {config['version']}, not rebuilding" + ) + return False + + if not quiet: + print( + f"Found cached build of {name} version {config['version']} but it's out of date, rebuilding" + ) + return True + + +def write_library_config(prefix, name, config, quiet): + cached_config = prefix / (name + ".json") + with cached_config.open("w") as f: + json.dump(config, f) + if not quiet: + print(f"Succeded building {name}, wrote config to {cached_config}") + + @subdir("host_build_dir", clean_ok=True) def make_emscripten_libffi(context, working_dir): - ver = "3.4.6" - libffi_dir = working_dir / f"libffi-{ver}" + prefix = context.build_paths["prefix_dir"] + libffi_config = load_config_toml()["libffi"] + if not should_build_library( + prefix, "libffi", libffi_config, context.quiet + ): + return + url = libffi_config["url"] + version = libffi_config["version"] + shasum = libffi_config["shasum"] + libffi_dir = working_dir / f"libffi-{version}" shutil.rmtree(libffi_dir, ignore_errors=True) download_and_unpack( working_dir, - f"https://github.com/libffi/libffi/releases/download/v{ver}/libffi-{ver}.tar.gz", - "b0dea9df23c863a7a50e825440f3ebffabd65df1497108e5d437747843895a4e", + url.format(version=version), + shasum, ) call( [EMSCRIPTEN_DIR / "make_libffi.sh"], - env=updated_env( - {"PREFIX": context.build_paths["prefix_dir"]}, context.emsdk_cache - ), + env=updated_env({"PREFIX": prefix}, context.emsdk_cache), cwd=libffi_dir, quiet=context.quiet, ) + write_library_config(prefix, "libffi", libffi_config, context.quiet) @subdir("host_build_dir", clean_ok=True) def make_mpdec(context, working_dir): - ver = "4.0.1" - mpdec_dir = working_dir / f"mpdecimal-{ver}" + prefix = context.build_paths["prefix_dir"] + mpdec_config = load_config_toml()["mpdec"] + if not should_build_library(prefix, "mpdec", mpdec_config, context.quiet): + return + + url = mpdec_config["url"] + version = mpdec_config["version"] + shasum = mpdec_config["shasum"] + mpdec_dir = working_dir / f"mpdecimal-{version}" shutil.rmtree(mpdec_dir, ignore_errors=True) download_and_unpack( working_dir, - f"https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-{ver}.tar.gz", - "96d33abb4bb0070c7be0fed4246cd38416188325f820468214471938545b1ac8", + url.format(version=version), + shasum, ) call( [ @@ -294,7 +392,7 @@ def make_mpdec(context, working_dir): mpdec_dir / "configure", "CFLAGS=-fPIC", "--prefix", - context.build_paths["prefix_dir"], + prefix, "--disable-shared", ], cwd=mpdec_dir, @@ -306,6 +404,7 @@ def make_mpdec(context, working_dir): cwd=mpdec_dir, quiet=context.quiet, ) + write_library_config(prefix, "mpdec", mpdec_config, context.quiet) @subdir("host_dir", clean_ok=True) @@ -436,16 +535,24 @@ def make_emscripten_python(context, working_dir): subprocess.check_call([exec_script, "--version"]) -def build_all(context): - """Build everything.""" - steps = [ - configure_build_python, - make_build_python, - make_emscripten_libffi, - make_mpdec, - configure_emscripten_python, - make_emscripten_python, - ] +def build_target(context): + """Build one or more targets.""" + steps = [] + if context.target in {"all"}: + steps.append(install_emscripten) + if context.target in {"build", "all"}: + steps.extend([ + configure_build_python, + make_build_python, + ]) + if context.target in {"host", "all"}: + steps.extend([ + make_emscripten_libffi, + make_mpdec, + configure_emscripten_python, + make_emscripten_python, + ]) + for step in steps: step(context) @@ -475,7 +582,22 @@ def main(): parser = argparse.ArgumentParser() subcommands = parser.add_subparsers(dest="subcommand") + install_emscripten_cmd = subcommands.add_parser( + "install-emscripten", + help="Install the appropriate version of Emscripten", + ) build = subcommands.add_parser("build", help="Build everything") + build.add_argument( + "target", + nargs="?", + default="all", + choices=["all", "host", "build"], + help=( + "What should be built. 'build' for just the build platform, or " + "'host' for the host platform, or 'all' for both. Defaults to 'all'." + ), + ) + configure_build = subcommands.add_parser( "configure-build-python", help="Run `configure` for the build Python" ) @@ -512,6 +634,7 @@ def main(): ) for subcommand in ( + install_emscripten_cmd, build, configure_build, make_libffi_cmd, @@ -568,22 +691,25 @@ def main(): context = parser.parse_args() - context.build_paths = get_build_paths(context.cross_build_dir) - - if context.emsdk_cache: + if context.emsdk_cache and context.subcommand != "install-emscripten": validate_emsdk_version(context.emsdk_cache) context.emsdk_cache = Path(context.emsdk_cache).absolute() else: print("Build will use EMSDK from current environment.") + context.build_paths = get_build_paths( + context.cross_build_dir, context.emsdk_cache + ) + dispatch = { + "install-emscripten": install_emscripten, "make-libffi": make_emscripten_libffi, "make-mpdec": make_mpdec, "configure-build-python": configure_build_python, "make-build-python": make_build_python, "configure-host": configure_emscripten_python, "make-host": make_emscripten_python, - "build": build_all, + "build": build_target, "clean": clean_contents, } diff --git a/Tools/wasm/emscripten/config.toml b/Tools/wasm/emscripten/config.toml new file mode 100644 index 00000000000..98edaebe992 --- /dev/null +++ b/Tools/wasm/emscripten/config.toml @@ -0,0 +1,14 @@ +# Any data that can vary between Python versions is to be kept in this file. +# This allows for blanket copying of the Emscripten build code between supported +# Python versions. +emscripten-version = "4.0.12" + +[libffi] +url = "https://github.com/libffi/libffi/releases/download/v{version}/libffi-{version}.tar.gz" +version = "3.4.6" +shasum = "b0dea9df23c863a7a50e825440f3ebffabd65df1497108e5d437747843895a4e" + +[mpdec] +url = "https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-{version}.tar.gz" +version = "4.0.1" +shasum = "96d33abb4bb0070c7be0fed4246cd38416188325f820468214471938545b1ac8" diff --git a/Tools/wasm/emscripten/emscripten_version.txt b/Tools/wasm/emscripten/emscripten_version.txt deleted file mode 100644 index 4c05e4ef57d..00000000000 --- a/Tools/wasm/emscripten/emscripten_version.txt +++ /dev/null @@ -1 +0,0 @@ -4.0.12 From c3955e049fd5dbd3d92bc95fed4442964156293d Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Wed, 11 Mar 2026 08:27:26 +0100 Subject: [PATCH 083/775] gh-145713: make bytearray.resize thread-safe on free-threading (#145714) Co-authored-by: Kumar Aditya --- Lib/test/test_bytes.py | 16 ++++++++++++++++ ...6-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst | 3 +++ Objects/bytearrayobject.c | 5 +++-- Objects/clinic/bytearrayobject.c.h | 4 +++- 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 1c64bf888f9..876ecd4467b 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -2908,6 +2908,22 @@ def check(funcs, it): check([iter_next] + [iter_reduce] * 10, iter(ba)) # for tsan check([iter_next] + [iter_setstate] * 10, iter(ba)) # for tsan + @unittest.skipUnless(support.Py_GIL_DISABLED, 'this test can only possibly fail with GIL disabled') + @threading_helper.reap_threads + @threading_helper.requires_working_threading() + def test_free_threading_bytearray_resize(self): + def resize_stress(ba): + for _ in range(1000): + try: + ba.resize(1000) + ba.resize(1) + except (BufferError, ValueError): + pass + + ba = bytearray(100) + threads = [threading.Thread(target=resize_stress, args=(ba,)) for _ in range(4)] + with threading_helper.start_threads(threads): + pass if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst new file mode 100644 index 00000000000..2cf83eff310 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst @@ -0,0 +1,3 @@ +Make :meth:`bytearray.resize` thread-safe in the free-threaded build by +using a critical section and calling the lock-held variant of the resize +function. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 7f09769e12f..e2fea94e099 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1506,6 +1506,7 @@ bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix) /*[clinic input] +@critical_section bytearray.resize size: Py_ssize_t New size to resize to. @@ -1515,10 +1516,10 @@ Resize the internal buffer of bytearray to len. static PyObject * bytearray_resize_impl(PyByteArrayObject *self, Py_ssize_t size) -/*[clinic end generated code: output=f73524922990b2d9 input=6c9a260ca7f72071]*/ +/*[clinic end generated code: output=f73524922990b2d9 input=116046316a2b5cfc]*/ { Py_ssize_t start_size = PyByteArray_GET_SIZE(self); - int result = PyByteArray_Resize((PyObject *)self, size); + int result = bytearray_resize_lock_held((PyObject *)self, size); if (result < 0) { return NULL; } diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index be704ccf68f..cf60d0ceadc 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -625,7 +625,9 @@ bytearray_resize(PyObject *self, PyObject *arg) } size = ival; } + Py_BEGIN_CRITICAL_SECTION(self); return_value = bytearray_resize_impl((PyByteArrayObject *)self, size); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -1833,4 +1835,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl((PyByteArrayObject *)self); } -/*[clinic end generated code: output=5eddefde2a001ceb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2d76ef023928424f input=a9049054013a1b77]*/ From cf7c67b7c6b96527dfb0da2d6305923a92e3d766 Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Wed, 11 Mar 2026 01:02:23 -0700 Subject: [PATCH 084/775] gh-101100: Fix sphinx reference warnings around I/O (#139592) Co-authored-by: Carol Willing --- Doc/library/email.parser.rst | 2 +- Doc/library/exceptions.rst | 2 +- Doc/library/os.rst | 10 +++++----- Doc/reference/datamodel.rst | 16 ++++++++++++++++ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Doc/library/email.parser.rst b/Doc/library/email.parser.rst index e0fcce8f0cb..6a67bf7c8e5 100644 --- a/Doc/library/email.parser.rst +++ b/Doc/library/email.parser.rst @@ -155,7 +155,7 @@ message body, instead setting the payload to the raw body. Read all the data from the binary file-like object *fp*, parse the resulting bytes, and return the message object. *fp* must support - both the :meth:`~io.IOBase.readline` and the :meth:`~io.IOBase.read` + both the :meth:`~io.IOBase.readline` and the :meth:`~io.BufferedIOBase.read` methods. The bytes contained in *fp* must be formatted as a block of :rfc:`5322` diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index 3db3c7a1350..7fc6055aa9a 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -221,7 +221,7 @@ The following exceptions are the exceptions that are usually raised. .. exception:: EOFError Raised when the :func:`input` function hits an end-of-file condition (EOF) - without reading any data. (Note: the :meth:`!io.IOBase.read` and + without reading any data. (Note: the :meth:`io.TextIOBase.read` and :meth:`io.IOBase.readline` methods return an empty string when they hit EOF.) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 940d04ccc92..7547967c6b3 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1294,8 +1294,8 @@ as internal buffering of data. This function is intended for low-level I/O. For normal usage, use the built-in function :func:`open`, which returns a :term:`file object` with - :meth:`~file.read` and :meth:`~file.write` methods (and many more). To - wrap a file descriptor in a file object, use :func:`fdopen`. + :meth:`~io.BufferedIOBase.read` and :meth:`~io.BufferedIOBase.write` methods. + To wrap a file descriptor in a file object, use :func:`fdopen`. .. versionchanged:: 3.3 Added the *dir_fd* parameter. @@ -1670,7 +1670,7 @@ or `the MSDN `_ on Windo descriptor as returned by :func:`os.open` or :func:`pipe`. To read a "file object" returned by the built-in function :func:`open` or by :func:`popen` or :func:`fdopen`, or :data:`sys.stdin`, use its - :meth:`~file.read` or :meth:`~file.readline` methods. + :meth:`~io.TextIOBase.read` or :meth:`~io.IOBase.readline` methods. .. versionchanged:: 3.5 If the system call is interrupted and the signal handler does not raise an @@ -1905,7 +1905,7 @@ or `the MSDN `_ on Windo descriptor as returned by :func:`os.open` or :func:`pipe`. To write a "file object" returned by the built-in function :func:`open` or by :func:`popen` or :func:`fdopen`, or :data:`sys.stdout` or :data:`sys.stderr`, use its - :meth:`~file.write` method. + :meth:`~io.TextIOBase.write` method. .. versionchanged:: 3.5 If the system call is interrupted and the signal handler does not raise an @@ -4720,7 +4720,7 @@ to be ignored. The current process is replaced immediately. Open file objects and descriptors are not flushed, so if there may be data buffered on these open files, you should flush them using - :func:`sys.stdout.flush` or :func:`os.fsync` before calling an + :func:`~io.IOBase.flush` or :func:`os.fsync` before calling an :func:`exec\* ` function. The "l" and "v" variants of the :func:`exec\* ` functions differ in how diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 062d301f628..90b8821daaf 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1401,12 +1401,28 @@ also :func:`os.popen`, :func:`os.fdopen`, and the :meth:`~socket.socket.makefile` method of socket objects (and perhaps by other functions or methods provided by extension modules). +File objects implement common methods, listed below, to simplify usage in +generic code. They are expected to be :ref:`context-managers`. + The objects ``sys.stdin``, ``sys.stdout`` and ``sys.stderr`` are initialized to file objects corresponding to the interpreter's standard input, output and error streams; they are all open in text mode and therefore follow the interface defined by the :class:`io.TextIOBase` abstract class. +.. method:: file.read(size=-1, /) + + Retrieve up to *size* data from the file. As a convenience if *size* is + unspecified or -1 retrieve all data available. + +.. method:: file.write(data, /) + + Store *data* to the file. + +.. method:: file.close() + + Flush any buffers and close the underlying file. + Internal types -------------- From bdf6de8c3f0c2ec0d737f38014a32c1eed02c7f1 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Wed, 11 Mar 2026 07:19:32 -0400 Subject: [PATCH 085/775] gh-145685: Avoid contention on TYPE_LOCK in super() lookups (gh-145775) --- Include/internal/pycore_stackref.h | 7 +++++++ Objects/typeobject.c | 20 +++++++++----------- Tools/ftscalingbench/ftscalingbench.py | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 69d667b4be4..188da775eb1 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -770,6 +770,13 @@ _PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref) ref->ref = PyStackRef_NULL; } +static inline void +_PyThreadState_PushCStackRefNew(PyThreadState *tstate, _PyCStackRef *ref, PyObject *obj) +{ + _PyThreadState_PushCStackRef(tstate, ref); + ref->ref = PyStackRef_FromPyObjectNew(obj); +} + static inline void _PyThreadState_PopCStackRef(PyThreadState *tstate, _PyCStackRef *ref) { diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5dc96bf251b..bb473dce68f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -12360,18 +12360,16 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * PyObject *mro, *res; Py_ssize_t i, n; - BEGIN_TYPE_LOCK(); mro = lookup_tp_mro(su_obj_type); - /* keep a strong reference to mro because su_obj_type->tp_mro can be - replaced during PyDict_GetItemRef(dict, name, &res) and because - another thread can modify it after we end the critical section - below */ - Py_XINCREF(mro); - END_TYPE_LOCK(); - if (mro == NULL) return NULL; + /* Keep a strong reference to mro because su_obj_type->tp_mro can be + replaced during PyDict_GetItemRef(dict, name, &res). */ + PyThreadState *tstate = _PyThreadState_GET(); + _PyCStackRef mro_ref; + _PyThreadState_PushCStackRefNew(tstate, &mro_ref, mro); + assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); @@ -12382,7 +12380,7 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * } i++; /* skip su->type (if any) */ if (i >= n) { - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return NULL; } @@ -12393,13 +12391,13 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * if (PyDict_GetItemRef(dict, name, &res) != 0) { // found or error - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return res; } i++; } while (i < n); - Py_DECREF(mro); + _PyThreadState_PopCStackRef(tstate, &mro_ref); return NULL; } diff --git a/Tools/ftscalingbench/ftscalingbench.py b/Tools/ftscalingbench/ftscalingbench.py index f60f5adba5c..8d8bbc88e7f 100644 --- a/Tools/ftscalingbench/ftscalingbench.py +++ b/Tools/ftscalingbench/ftscalingbench.py @@ -241,6 +241,22 @@ def instantiate_typing_namedtuple(): for _ in range(1000 * WORK_SCALE): obj = MyTypingNamedTuple(x=1, y=2, z=3) +@register_benchmark +def super_call(): + # TODO: super() on the same class from multiple threads still doesn't + # scale well, so use a class per-thread here for now. + class Base: + def method(self): + return 1 + + class Derived(Base): + def method(self): + return super().method() + + obj = Derived() + for _ in range(1000 * WORK_SCALE): + obj.method() + @register_benchmark def deepcopy(): From dae85c4d9393b706657a4eb1febc71647a5f544e Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 11 Mar 2026 14:39:24 +0300 Subject: [PATCH 086/775] gh-145633: Remove support for ancient ARM platforms with mixed-endian doubles (#145634) * Drop DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 macro. * Use DOUBLE_IS_BIG/LITTLE_ENDIAN_IEEE754 to detect endianness of float/doubles. * Drop "unknown_format" code path in PyFloat_Pack/Unpack*(). Co-authored-by: Victor Stinner --- Doc/c-api/float.rst | 8 - Include/internal/pycore_floatobject.h | 10 +- Include/internal/pycore_pymath.h | 3 +- Include/internal/pycore_runtime_init.h | 8 +- Include/internal/pycore_runtime_structs.h | 12 - Include/pymacconfig.h | 1 - ...-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst | 3 + Objects/clinic/floatobject.c.h | 4 +- Objects/floatobject.c | 636 ++++-------------- Python/dtoa.c | 6 +- Python/pylifecycle.c | 2 - configure | 13 - configure.ac | 14 +- pyconfig.h.in | 4 - 14 files changed, 134 insertions(+), 590 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst index dcd54547827..ca8d44c25c1 100644 --- a/Doc/c-api/float.rst +++ b/Doc/c-api/float.rst @@ -224,11 +224,6 @@ endian processor, or ``0`` on little endian processor. Return value: ``0`` if all is OK, ``-1`` if error (and an exception is set, most likely :exc:`OverflowError`). -There are two problems on non-IEEE platforms: - -* What this does is undefined if *x* is a NaN or infinity. -* ``-0.0`` and ``+0.0`` produce the same bytes string. - .. c:function:: int PyFloat_Pack2(double x, char *p, int le) Pack a C double as the IEEE 754 binary16 half-precision format. @@ -256,9 +251,6 @@ Return value: The unpacked double. On error, this is ``-1.0`` and :c:func:`PyErr_Occurred` is true (and an exception is set, most likely :exc:`OverflowError`). -Note that on a non-IEEE platform this will refuse to unpack a bytes string that -represents a NaN or infinity. - .. c:function:: double PyFloat_Unpack2(const char *p, int le) Unpack the IEEE 754 binary16 half-precision format as a C double. diff --git a/Include/internal/pycore_floatobject.h b/Include/internal/pycore_floatobject.h index 317f984188b..62501cdaf44 100644 --- a/Include/internal/pycore_floatobject.h +++ b/Include/internal/pycore_floatobject.h @@ -12,7 +12,6 @@ extern "C" { /* runtime lifecycle */ -extern void _PyFloat_InitState(PyInterpreterState *); extern PyStatus _PyFloat_InitTypes(PyInterpreterState *); extern void _PyFloat_FiniType(PyInterpreterState *); @@ -42,6 +41,15 @@ extern double _Py_parse_inf_or_nan(const char *p, char **endptr); extern int _Py_convert_int_to_double(PyObject **v, double *dbl); +/* Should match endianness of the platform in most (all?) cases. */ + +#ifdef DOUBLE_IS_BIG_ENDIAN_IEEE754 +# define _PY_FLOAT_BIG_ENDIAN 1 +# define _PY_FLOAT_LITTLE_ENDIAN 0 +#else +# define _PY_FLOAT_BIG_ENDIAN 0 +# define _PY_FLOAT_LITTLE_ENDIAN 1 +#endif #ifdef __cplusplus } diff --git a/Include/internal/pycore_pymath.h b/Include/internal/pycore_pymath.h index f66325aa59c..532c5ceafb5 100644 --- a/Include/internal/pycore_pymath.h +++ b/Include/internal/pycore_pymath.h @@ -182,8 +182,7 @@ extern void _Py_set_387controlword(unsigned short); // (extended precision), and we don't know how to change // the rounding precision. #if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \ - !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \ - !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) + !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) # define _PY_SHORT_FLOAT_REPR 0 #endif diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index b182f7825a2..e8d1098c207 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -13,7 +13,7 @@ extern "C" { #include "pycore_debug_offsets.h" // _Py_DebugOffsets_INIT() #include "pycore_dtoa.h" // _dtoa_state_INIT() #include "pycore_faulthandler.h" // _faulthandler_runtime_state_INIT -#include "pycore_floatobject.h" // _py_float_format_unknown +#include "pycore_floatobject.h" // _py_float_format_* #include "pycore_function.h" #include "pycore_hamt.h" // _PyHamt_BitmapNode_Type #include "pycore_import.h" // IMPORTS_INIT @@ -84,10 +84,6 @@ extern PyTypeObject _PyExc_MemoryError; .stoptheworld = { \ .is_global = 1, \ }, \ - .float_state = { \ - .float_format = _py_float_format_unknown, \ - .double_format = _py_float_format_unknown, \ - }, \ .types = { \ .next_version_tag = _Py_TYPE_VERSION_NEXT, \ }, \ @@ -233,4 +229,4 @@ extern PyTypeObject _PyExc_MemoryError; #ifdef __cplusplus } #endif -#endif /* !Py_INTERNAL_RUNTIME_INIT_H */ \ No newline at end of file +#endif /* !Py_INTERNAL_RUNTIME_INIT_H */ diff --git a/Include/internal/pycore_runtime_structs.h b/Include/internal/pycore_runtime_structs.h index 90e6625ad1f..05369ef9f00 100644 --- a/Include/internal/pycore_runtime_structs.h +++ b/Include/internal/pycore_runtime_structs.h @@ -35,17 +35,6 @@ struct _pymem_allocators { PyObjectArenaAllocator obj_arena; }; -enum _py_float_format_type { - _py_float_format_unknown, - _py_float_format_ieee_big_endian, - _py_float_format_ieee_little_endian, -}; - -struct _Py_float_runtime_state { - enum _py_float_format_type float_format; - enum _py_float_format_type double_format; -}; - struct pyhash_runtime_state { struct { #ifndef MS_WINDOWS @@ -270,7 +259,6 @@ struct pyruntimestate { } audit_hooks; struct _py_object_runtime_state object_state; - struct _Py_float_runtime_state float_state; struct _Py_unicode_runtime_state unicode_state; struct _types_runtime_state types; struct _Py_time_runtime_state time; diff --git a/Include/pymacconfig.h b/Include/pymacconfig.h index 615abe103ca..9d63ddf8a71 100644 --- a/Include/pymacconfig.h +++ b/Include/pymacconfig.h @@ -18,7 +18,6 @@ #undef SIZEOF_UINTPTR_T #undef SIZEOF_PTHREAD_T #undef WORDS_BIGENDIAN -#undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 #undef DOUBLE_IS_BIG_ENDIAN_IEEE754 #undef DOUBLE_IS_LITTLE_ENDIAN_IEEE754 #undef HAVE_GCC_ASM_FOR_X87 diff --git a/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst b/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst new file mode 100644 index 00000000000..2c4da1b60c0 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst @@ -0,0 +1,3 @@ +Remove support for ancient ARM platforms (ARMv4L and ARMv5L OABI boards), +using mixed-endian representation +for doubles. Patch by Sergey B Kirpichev. diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h index 4051131f480..c0ae9d3ff9b 100644 --- a/Objects/clinic/floatobject.c.h +++ b/Objects/clinic/floatobject.c.h @@ -290,7 +290,7 @@ PyDoc_STRVAR(float___getformat____doc__, "\n" "It exists mainly to be used in Python\'s test suite.\n" "\n" -"This function returns whichever of \'unknown\', \'IEEE, big-endian\' or \'IEEE,\n" +"This function returns whichever of \'IEEE, big-endian\' or \'IEEE,\n" "little-endian\' best describes the format of floating-point numbers used by the\n" "C type named by typestr."); @@ -353,4 +353,4 @@ float___format__(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=927035897ea3573f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f0b2af257213c8b0 input=a9049054013a1b77]*/ diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 579765281ca..18871a4f3c5 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1666,15 +1666,6 @@ float___getnewargs___impl(PyObject *self) return Py_BuildValue("(d)", ((PyFloatObject *)self)->ob_fval); } -/* this is for the benefit of the pack/unpack routines below */ -typedef enum _py_float_format_type float_format_type; -#define unknown_format _py_float_format_unknown -#define ieee_big_endian_format _py_float_format_ieee_big_endian -#define ieee_little_endian_format _py_float_format_ieee_little_endian - -#define float_format (_PyRuntime.float_state.float_format) -#define double_format (_PyRuntime.float_state.double_format) - /*[clinic input] @permit_long_docstring_body @@ -1689,45 +1680,25 @@ You probably don't want to use this function. It exists mainly to be used in Python's test suite. -This function returns whichever of 'unknown', 'IEEE, big-endian' or 'IEEE, +This function returns whichever of 'IEEE, big-endian' or 'IEEE, little-endian' best describes the format of floating-point numbers used by the C type named by typestr. [clinic start generated code]*/ static PyObject * float___getformat___impl(PyTypeObject *type, const char *typestr) -/*[clinic end generated code: output=2bfb987228cc9628 input=d2735823bfe8e81e]*/ +/*[clinic end generated code: output=2bfb987228cc9628 input=0ae1ba35d192f704]*/ { - float_format_type r; - - if (strcmp(typestr, "double") == 0) { - r = double_format; - } - else if (strcmp(typestr, "float") == 0) { - r = float_format; - } - else { + if (strcmp(typestr, "double") != 0 && strcmp(typestr, "float") != 0) { PyErr_SetString(PyExc_ValueError, "__getformat__() argument 1 must be " "'double' or 'float'"); return NULL; } - - switch (r) { - case unknown_format: - return PyUnicode_FromString("unknown"); - case ieee_little_endian_format: - return PyUnicode_FromString("IEEE, little-endian"); - case ieee_big_endian_format: - return PyUnicode_FromString("IEEE, big-endian"); - default: - PyErr_SetString(PyExc_RuntimeError, - "insane float_format or double_format"); - return NULL; - } + return PyUnicode_FromString(_PY_FLOAT_LITTLE_ENDIAN ? + "IEEE, little-endian" : "IEEE, big-endian"); } - static PyObject * float_getreal(PyObject *v, void *Py_UNUSED(closure)) { @@ -1878,67 +1849,6 @@ PyTypeObject PyFloat_Type = { .tp_version_tag = _Py_TYPE_VERSION_FLOAT, }; -static void -_init_global_state(void) -{ - float_format_type detected_double_format, detected_float_format; - - /* We attempt to determine if this machine is using IEEE - floating-point formats by peering at the bits of some - carefully chosen values. If it looks like we are on an - IEEE platform, the float packing/unpacking routines can - just copy bits, if not they resort to arithmetic & shifts - and masks. The shifts & masks approach works on all finite - values, but what happens to infinities, NaNs and signed - zeroes on packing is an accident, and attempting to unpack - a NaN or an infinity will raise an exception. - - Note that if we're on some whacked-out platform which uses - IEEE formats but isn't strictly little-endian or big- - endian, we will fall back to the portable shifts & masks - method. */ - -#if SIZEOF_DOUBLE == 8 - { - double x = 9006104071832581.0; - if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0) - detected_double_format = ieee_big_endian_format; - else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0) - detected_double_format = ieee_little_endian_format; - else - detected_double_format = unknown_format; - } -#else - detected_double_format = unknown_format; -#endif - -#if SIZEOF_FLOAT == 4 - { - float y = 16711938.0; - if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0) - detected_float_format = ieee_big_endian_format; - else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0) - detected_float_format = ieee_little_endian_format; - else - detected_float_format = unknown_format; - } -#else - detected_float_format = unknown_format; -#endif - - double_format = detected_double_format; - float_format = detected_float_format; -} - -void -_PyFloat_InitState(PyInterpreterState *interp) -{ - if (!_Py_IsMainInterpreter(interp)) { - return; - } - _init_global_state(); -} - PyStatus _PyFloat_InitTypes(PyInterpreterState *interp) { @@ -2092,278 +2002,87 @@ int PyFloat_Pack4(double x, char *data, int le) { unsigned char *p = (unsigned char *)data; - if (float_format == unknown_format) { - unsigned char sign; - int e; - double f; - unsigned int fbits; - int incr = 1; - - if (le) { - p += 3; - incr = -1; - } - - if (x < 0) { - sign = 1; - x = -x; - } - else - sign = 0; - - f = frexp(x, &e); - - /* Normalize f to be in the range [1.0, 2.0) */ - if (0.5 <= f && f < 1.0) { - f *= 2.0; - e--; - } - else if (f == 0.0) - e = 0; - else { - PyErr_SetString(PyExc_SystemError, - "frexp() result out of range"); - return -1; - } - - if (e >= 128) - goto Overflow; - else if (e < -126) { - /* Gradual underflow */ - f = ldexp(f, 126 + e); - e = 0; - } - else if (!(e == 0 && f == 0.0)) { - e += 127; - f -= 1.0; /* Get rid of leading 1 */ - } - - f *= 8388608.0; /* 2**23 */ - fbits = (unsigned int)(f + 0.5); /* Round */ - assert(fbits <= 8388608); - if (fbits >> 23) { - /* The carry propagated out of a string of 23 1 bits. */ - fbits = 0; - ++e; - if (e >= 255) - goto Overflow; - } - - /* First byte */ - *p = (sign << 7) | (e >> 1); - p += incr; - - /* Second byte */ - *p = (char) (((e & 1) << 7) | (fbits >> 16)); - p += incr; - - /* Third byte */ - *p = (fbits >> 8) & 0xFF; - p += incr; - - /* Fourth byte */ - *p = fbits & 0xFF; - - /* Done */ - return 0; + float y = (float)x; + int i, incr = 1; + if (isinf(y) && !isinf(x)) { + PyErr_SetString(PyExc_OverflowError, + "float too large to pack with f format"); + return -1; } - else { - float y = (float)x; - int i, incr = 1; - if (isinf(y) && !isinf(x)) - goto Overflow; + /* correct y if x was a sNaN, transformed to qNaN by conversion */ + if (isnan(x)) { + uint64_t v; - /* correct y if x was a sNaN, transformed to qNaN by conversion */ - if (isnan(x)) { - uint64_t v; - - memcpy(&v, &x, 8); + memcpy(&v, &x, 8); #ifndef __riscv - if ((v & (1ULL << 51)) == 0) { - uint32_t u32; - memcpy(&u32, &y, 4); - /* if have payload, make sNaN */ - if (u32 & 0x3fffff) { - u32 &= ~(1 << 22); - } - memcpy(&y, &u32, 4); - } -#else + if ((v & (1ULL << 51)) == 0) { uint32_t u32; - memcpy(&u32, &y, 4); - /* Workaround RISC-V: "If a NaN value is converted to a - * different floating-point type, the result is the - * canonical NaN of the new type". The canonical NaN here - * is a positive qNaN with zero payload. */ - if (v & (1ULL << 63)) { - u32 |= (1 << 31); /* set sign */ - } - /* add payload */ - u32 -= (u32 & 0x3fffff); - u32 += (uint32_t)((v & 0x7ffffffffffffULL) >> 29); /* if have payload, make sNaN */ - if ((v & (1ULL << 51)) == 0 && (u32 & 0x3fffff)) { + if (u32 & 0x3fffff) { u32 &= ~(1 << 22); } - memcpy(&y, &u32, 4); + } +#else + uint32_t u32; + + memcpy(&u32, &y, 4); + /* Workaround RISC-V: "If a NaN value is converted to a + * different floating-point type, the result is the + * canonical NaN of the new type". The canonical NaN here + * is a positive qNaN with zero payload. */ + if (v & (1ULL << 63)) { + u32 |= (1 << 31); /* set sign */ + } + /* add payload */ + u32 -= (u32 & 0x3fffff); + u32 += (uint32_t)((v & 0x7ffffffffffffULL) >> 29); + /* if have payload, make sNaN */ + if ((v & (1ULL << 51)) == 0 && (u32 & 0x3fffff)) { + u32 &= ~(1 << 22); + } + + memcpy(&y, &u32, 4); #endif - } - - unsigned char s[sizeof(float)]; - memcpy(s, &y, sizeof(float)); - - if ((float_format == ieee_little_endian_format && !le) - || (float_format == ieee_big_endian_format && le)) { - p += 3; - incr = -1; - } - - for (i = 0; i < 4; i++) { - *p = s[i]; - p += incr; - } - return 0; } - Overflow: - PyErr_SetString(PyExc_OverflowError, - "float too large to pack with f format"); - return -1; + + unsigned char s[sizeof(float)]; + memcpy(s, &y, sizeof(float)); + + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + p += 3; + incr = -1; + } + + for (i = 0; i < 4; i++) { + *p = s[i]; + p += incr; + } + return 0; } int PyFloat_Pack8(double x, char *data, int le) { unsigned char *p = (unsigned char *)data; - if (double_format == unknown_format) { - unsigned char sign; - int e; - double f; - unsigned int fhi, flo; - int incr = 1; + unsigned char as_bytes[8]; + memcpy(as_bytes, &x, 8); + const unsigned char *s = as_bytes; + int i, incr = 1; - if (le) { - p += 7; - incr = -1; - } - - if (x < 0) { - sign = 1; - x = -x; - } - else - sign = 0; - - f = frexp(x, &e); - - /* Normalize f to be in the range [1.0, 2.0) */ - if (0.5 <= f && f < 1.0) { - f *= 2.0; - e--; - } - else if (f == 0.0) - e = 0; - else { - PyErr_SetString(PyExc_SystemError, - "frexp() result out of range"); - return -1; - } - - if (e >= 1024) - goto Overflow; - else if (e < -1022) { - /* Gradual underflow */ - f = ldexp(f, 1022 + e); - e = 0; - } - else if (!(e == 0 && f == 0.0)) { - e += 1023; - f -= 1.0; /* Get rid of leading 1 */ - } - - /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */ - f *= 268435456.0; /* 2**28 */ - fhi = (unsigned int)f; /* Truncate */ - assert(fhi < 268435456); - - f -= (double)fhi; - f *= 16777216.0; /* 2**24 */ - flo = (unsigned int)(f + 0.5); /* Round */ - assert(flo <= 16777216); - if (flo >> 24) { - /* The carry propagated out of a string of 24 1 bits. */ - flo = 0; - ++fhi; - if (fhi >> 28) { - /* And it also propagated out of the next 28 bits. */ - fhi = 0; - ++e; - if (e >= 2047) - goto Overflow; - } - } - - /* First byte */ - *p = (sign << 7) | (e >> 4); - p += incr; - - /* Second byte */ - *p = (unsigned char) (((e & 0xF) << 4) | (fhi >> 24)); - p += incr; - - /* Third byte */ - *p = (fhi >> 16) & 0xFF; - p += incr; - - /* Fourth byte */ - *p = (fhi >> 8) & 0xFF; - p += incr; - - /* Fifth byte */ - *p = fhi & 0xFF; - p += incr; - - /* Sixth byte */ - *p = (flo >> 16) & 0xFF; - p += incr; - - /* Seventh byte */ - *p = (flo >> 8) & 0xFF; - p += incr; - - /* Eighth byte */ - *p = flo & 0xFF; - /* p += incr; */ - - /* Done */ - return 0; - - Overflow: - PyErr_SetString(PyExc_OverflowError, - "float too large to pack with d format"); - return -1; + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + p += 7; + incr = -1; } - else { - unsigned char as_bytes[8]; - memcpy(as_bytes, &x, 8); - const unsigned char *s = as_bytes; - int i, incr = 1; - if ((double_format == ieee_little_endian_format && !le) - || (double_format == ieee_big_endian_format && le)) { - p += 7; - incr = -1; - } - - for (i = 0; i < 8; i++) { - *p = *s++; - p += incr; - } - return 0; + for (i = 0; i < 8; i++) { + *p = *s++; + p += incr; } + return 0; } double @@ -2426,208 +2145,79 @@ double PyFloat_Unpack4(const char *data, int le) { unsigned char *p = (unsigned char *)data; - if (float_format == unknown_format) { - unsigned char sign; - int e; - unsigned int f; - double x; - int incr = 1; + float x; - if (le) { - p += 3; - incr = -1; + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + char buf[4]; + char *d = &buf[3]; + int i; + + for (i = 0; i < 4; i++) { + *d-- = *p++; } - - /* First byte */ - sign = (*p >> 7) & 1; - e = (*p & 0x7F) << 1; - p += incr; - - /* Second byte */ - e |= (*p >> 7) & 1; - f = (*p & 0x7F) << 16; - p += incr; - - if (e == 255) { - PyErr_SetString( - PyExc_ValueError, - "can't unpack IEEE 754 special value " - "on non-IEEE platform"); - return -1; - } - - /* Third byte */ - f |= *p << 8; - p += incr; - - /* Fourth byte */ - f |= *p; - - x = (double)f / 8388608.0; - - /* XXX This sadly ignores Inf/NaN issues */ - if (e == 0) - e = -126; - else { - x += 1.0; - e -= 127; - } - x = ldexp(x, e); - - if (sign) - x = -x; - - return x; + memcpy(&x, buf, 4); } else { - float x; + memcpy(&x, p, 4); + } - if ((float_format == ieee_little_endian_format && !le) - || (float_format == ieee_big_endian_format && le)) { - char buf[4]; - char *d = &buf[3]; - int i; - - for (i = 0; i < 4; i++) { - *d-- = *p++; - } - memcpy(&x, buf, 4); - } - else { - memcpy(&x, p, 4); - } - - /* return sNaN double if x was sNaN float */ - if (isnan(x)) { - uint32_t v; - memcpy(&v, &x, 4); + /* return sNaN double if x was sNaN float */ + if (isnan(x)) { + uint32_t v; + memcpy(&v, &x, 4); #ifndef __riscv - if ((v & (1 << 22)) == 0) { - double y = x; /* will make qNaN double */ - uint64_t u64; - memcpy(&u64, &y, 8); - u64 &= ~(1ULL << 51); /* make sNaN */ - memcpy(&y, &u64, 8); - return y; - } -#else - double y = x; + if ((v & (1 << 22)) == 0) { + double y = x; /* will make qNaN double */ uint64_t u64; - memcpy(&u64, &y, 8); - if ((v & (1 << 22)) == 0) { - u64 &= ~(1ULL << 51); - } - /* Workaround RISC-V, see PyFloat_Pack4() */ - if (v & (1 << 31)) { - u64 |= (1ULL << 63); /* set sign */ - } - /* add payload */ - u64 -= (u64 & 0x7ffffffffffffULL); - u64 += ((v & 0x3fffffULL) << 29); - + u64 &= ~(1ULL << 51); /* make sNaN */ memcpy(&y, &u64, 8); return y; -#endif } +#else + double y = x; + uint64_t u64; - return x; + memcpy(&u64, &y, 8); + if ((v & (1 << 22)) == 0) { + u64 &= ~(1ULL << 51); + } + /* Workaround RISC-V, see PyFloat_Pack4() */ + if (v & (1 << 31)) { + u64 |= (1ULL << 63); /* set sign */ + } + /* add payload */ + u64 -= (u64 & 0x7ffffffffffffULL); + u64 += ((v & 0x3fffffULL) << 29); + + memcpy(&y, &u64, 8); + return y; +#endif } + + return x; } double PyFloat_Unpack8(const char *data, int le) { unsigned char *p = (unsigned char *)data; - if (double_format == unknown_format) { - unsigned char sign; - int e; - unsigned int fhi, flo; - double x; - int incr = 1; + double x; - if (le) { - p += 7; - incr = -1; + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + char buf[8]; + char *d = &buf[7]; + int i; + + for (i = 0; i < 8; i++) { + *d-- = *p++; } - - /* First byte */ - sign = (*p >> 7) & 1; - e = (*p & 0x7F) << 4; - - p += incr; - - /* Second byte */ - e |= (*p >> 4) & 0xF; - fhi = (*p & 0xF) << 24; - p += incr; - - if (e == 2047) { - PyErr_SetString( - PyExc_ValueError, - "can't unpack IEEE 754 special value " - "on non-IEEE platform"); - return -1.0; - } - - /* Third byte */ - fhi |= *p << 16; - p += incr; - - /* Fourth byte */ - fhi |= *p << 8; - p += incr; - - /* Fifth byte */ - fhi |= *p; - p += incr; - - /* Sixth byte */ - flo = *p << 16; - p += incr; - - /* Seventh byte */ - flo |= *p << 8; - p += incr; - - /* Eighth byte */ - flo |= *p; - - x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */ - x /= 268435456.0; /* 2**28 */ - - if (e == 0) - e = -1022; - else { - x += 1.0; - e -= 1023; - } - x = ldexp(x, e); - - if (sign) - x = -x; - - return x; + memcpy(&x, buf, 8); } else { - double x; - - if ((double_format == ieee_little_endian_format && !le) - || (double_format == ieee_big_endian_format && le)) { - char buf[8]; - char *d = &buf[7]; - int i; - - for (i = 0; i < 8; i++) { - *d-- = *p++; - } - memcpy(&x, buf, 8); - } - else { - memcpy(&x, p, 8); - } - - return x; + memcpy(&x, p, 8); } + + return x; } diff --git a/Python/dtoa.c b/Python/dtoa.c index 3de150351a4..89fadd33391 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -139,8 +139,7 @@ #ifdef DOUBLE_IS_LITTLE_ENDIAN_IEEE754 # define IEEE_8087 #endif -#if defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) || \ - defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) +#if defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) # define IEEE_MC68k #endif #if defined(IEEE_8087) + defined(IEEE_MC68k) != 1 @@ -149,8 +148,7 @@ /* The code below assumes that the endianness of integers matches the endianness of the two 32-bit words of a double. Check this. */ -#if defined(WORDS_BIGENDIAN) && (defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) || \ - defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754)) +#if defined(WORDS_BIGENDIAN) && defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) #error "doubles and ints have incompatible endianness" #endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 711e7bc89b7..21d1e036d31 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -706,8 +706,6 @@ pycore_init_global_objects(PyInterpreterState *interp) { PyStatus status; - _PyFloat_InitState(interp); - status = _PyUnicode_InitGlobalObjects(interp); if (_PyStatus_EXCEPTION(status)) { return status; diff --git a/configure b/configure index 95bb6ba4e84..a3eeef373bf 100755 --- a/configure +++ b/configure @@ -26212,20 +26212,7 @@ printf "%s\n" "#define DOUBLE_IS_BIG_ENDIAN_IEEE754 1" >>confdefs.h printf "%s\n" "#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1" >>confdefs.h ;; *) - case $host_cpu in #( - *arm*) : - # Some ARM platforms use a mixed-endian representation for - # doubles. While Python doesn't currently have full support - # for these platforms (see e.g., issue 1762561), we can at - # least make sure that float <-> string conversions work. - # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case, - # but if it's not big or little, then it must be this? - -printf "%s\n" "#define DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 1" >>confdefs.h - ;; #( - *) : as_fn_error $? "Unknown float word ordering. You need to manually preset ax_cv_c_float_words_bigendian=no (or yes) according to your system." "$LINENO" 5 ;; -esac ;; esac diff --git a/configure.ac b/configure.ac index e049f568417..75e81761f95 100644 --- a/configure.ac +++ b/configure.ac @@ -6178,21 +6178,11 @@ AX_C_FLOAT_WORDS_BIGENDIAN( [AC_DEFINE([DOUBLE_IS_LITTLE_ENDIAN_IEEE754], [1], [Define if C doubles are 64-bit IEEE 754 binary format, stored with the least significant byte first])], - [AS_CASE([$host_cpu], - [*arm*], [# Some ARM platforms use a mixed-endian representation for - # doubles. While Python doesn't currently have full support - # for these platforms (see e.g., issue 1762561), we can at - # least make sure that float <-> string conversions work. - # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case, - # but if it's not big or little, then it must be this? - AC_DEFINE([DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754], [1], - [Define if C doubles are 64-bit IEEE 754 binary format, - stored in ARM mixed-endian order (byte order 45670123)])], - [AC_MSG_ERROR([m4_normalize([ + [AC_MSG_ERROR([m4_normalize([ Unknown float word ordering. You need to manually preset ax_cv_c_float_words_bigendian=no (or yes) according to your system. - ])])])]) + ])])]) # The short float repr introduced in Python 3.1 requires the # correctly-rounded string <-> double conversion functions from diff --git a/pyconfig.h.in b/pyconfig.h.in index fbd5d4d6259..9da33c954a5 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -32,10 +32,6 @@ /* The Android API level. */ #undef ANDROID_API_LEVEL -/* Define if C doubles are 64-bit IEEE 754 binary format, stored in ARM - mixed-endian order (byte order 45670123) */ -#undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 - /* Define if C doubles are 64-bit IEEE 754 binary format, stored with the most significant byte first */ #undef DOUBLE_IS_BIG_ENDIAN_IEEE754 From 5d6e8dd683b25348bfe45f6321f9734868199a23 Mon Sep 17 00:00:00 2001 From: Shrey Naithani Date: Wed, 11 Mar 2026 17:38:48 +0530 Subject: [PATCH 087/775] gh-145587: fix busy loop in multiprocessing.connection.wait on Windows (GH-145597) Ensure wait() blocks for the specified timeout when object_list is empty, preventing 100% CPU usage. This aligns the Windows behavior with the Unix implementation. Co-authored-by: AN Long --- Lib/multiprocessing/connection.py | 12 ++++++++++-- Lib/test/_test_multiprocessing.py | 13 +++++++++++++ .../2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index 41b36066c62..9ce996c9ccd 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -1085,14 +1085,22 @@ def wait(object_list, timeout=None): Returns list of those objects in object_list which are ready/readable. ''' + object_list = list(object_list) + + if not object_list: + if timeout is None: + while True: + time.sleep(1e6) + elif timeout > 0: + time.sleep(timeout) + return [] + if timeout is None: timeout = INFINITE elif timeout < 0: timeout = 0 else: timeout = int(timeout * 1000 + 0.5) - - object_list = list(object_list) waithandle_to_obj = {} ov_list = [] ready_objects = set() diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index cc07062eee6..d67fd13fa33 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3890,6 +3890,19 @@ def test_context(self): self.assertRaises(OSError, a.recv) self.assertRaises(OSError, b.recv) + @warnings_helper.ignore_fork_in_thread_deprecation_warnings() + def test_wait_empty(self): + if self.TYPE != 'processes': + self.skipTest('test not appropriate for {}'.format(self.TYPE)) + # gh-145587: wait() with empty list should respect timeout + timeout = 0.5 + start = time.monotonic() + res = self.connection.wait([], timeout=timeout) + duration = time.monotonic() - start + + self.assertEqual(res, []) + self.assertGreaterEqual(duration, timeout - 0.1) + class _TestListener(BaseTestCase): ALLOWED_TYPES = ('processes',) diff --git a/Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst b/Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst new file mode 100644 index 00000000000..c17d01f36b8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst @@ -0,0 +1 @@ +Resolved a performance regression in ``multiprocessing.connection.wait`` on Windows that caused infinite busy loops when called with no objects. The function now properly yields control to the OS to conserve CPU resources. Patch By Shrey Naithani From ece712197d2d23bcc80937d122e7b9f07338350e Mon Sep 17 00:00:00 2001 From: Stefan Zetzsche <120379523+stefanzetzsche@users.noreply.github.com> Date: Wed, 11 Mar 2026 12:21:22 +0000 Subject: [PATCH 088/775] gh-145546: unittest.util: fix `sorted_list_difference` tail deduplication (GH-145547) * fix(unittest.util): Deduplicate tail elements in sorted_list_difference sorted_list_difference failed to deduplicate remaining elements when one list was exhausted, causing duplicate values in the result. Deduplicate before extending. Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Lib/test/test_unittest/test_util.py | 33 +++++++++++++++++++ Lib/unittest/util.py | 12 +++++-- ...-03-05-14-13-10.gh-issue-145546.3tnlxx.rst | 2 ++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst diff --git a/Lib/test/test_unittest/test_util.py b/Lib/test/test_unittest/test_util.py index d590a333930..09ce09b91b7 100644 --- a/Lib/test/test_unittest/test_util.py +++ b/Lib/test/test_unittest/test_util.py @@ -26,6 +26,39 @@ def test_sorted_list_difference(self): self.assertEqual(sorted_list_difference([2], [1, 1]), ([2], [1])) self.assertEqual(sorted_list_difference([1, 2], [1, 1]), ([2], [])) + def test_sorted_list_difference_tail_deduplication(self): + # Tail deduplication when one list is exhausted before the other. + # These exercise the except-IndexError path in sorted_list_difference. + self.assertEqual(sorted_list_difference([], [0, 0]), ([], [0])) + self.assertEqual(sorted_list_difference([0, 0], []), ([0], [])) + self.assertEqual(sorted_list_difference([], [1, 1, 2, 2]), ([], [1, 2])) + self.assertEqual(sorted_list_difference([1, 1, 2, 2], []), ([1, 2], [])) + # One list exhausts mid-way, leaving duplicated tail in the other. + self.assertEqual(sorted_list_difference([1], [1, 2, 2, 3, 3]), ([], [2, 3])) + self.assertEqual(sorted_list_difference([1, 2, 2, 3, 3], [1]), ([2, 3], [])) + + def test_sorted_list_difference_strings(self): + self.assertEqual( + sorted_list_difference(['a', 'b'], ['b', 'c']), + (['a'], ['c'])) + self.assertEqual( + sorted_list_difference([], ['a', 'a', 'b']), + ([], ['a', 'b'])) + self.assertEqual( + sorted_list_difference(['a', 'a', 'b'], []), + (['a', 'b'], [])) + + def test_sorted_list_difference_unhashable(self): + self.assertEqual( + sorted_list_difference([[1], [2]], [[2], [3]]), + ([[1]], [[3]])) + self.assertEqual( + sorted_list_difference([], [[0], [0]]), + ([], [[0]])) + self.assertEqual( + sorted_list_difference([[0], [0]], []), + ([[0]], [])) + def test_unorderable_list_difference(self): self.assertEqual(unorderable_list_difference([], []), ([], [])) self.assertEqual(unorderable_list_difference([1, 2], []), ([2, 1], [])) diff --git a/Lib/unittest/util.py b/Lib/unittest/util.py index c7e6b941978..0681163c979 100644 --- a/Lib/unittest/util.py +++ b/Lib/unittest/util.py @@ -63,6 +63,14 @@ def safe_repr(obj, short=False): def strclass(cls): return "%s.%s" % (cls.__module__, cls.__qualname__) +def _dedupe_sorted(lst): + """Remove consecutive duplicate elements from a sorted list.""" + result = [] + for item in lst: + if not result or result[-1] != item: + result.append(item) + return result + def sorted_list_difference(expected, actual): """Finds elements in only one or the other of two, sorted input lists. @@ -98,8 +106,8 @@ def sorted_list_difference(expected, actual): while actual[j] == a: j += 1 except IndexError: - missing.extend(expected[i:]) - unexpected.extend(actual[j:]) + missing.extend(_dedupe_sorted(expected[i:])) + unexpected.extend(_dedupe_sorted(actual[j:])) break return missing, unexpected diff --git a/Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst b/Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst new file mode 100644 index 00000000000..e9401bb08c6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst @@ -0,0 +1,2 @@ +Fix ``unittest.util.sorted_list_difference()`` to deduplicate remaining +elements when one input list is exhausted before the other. From eb9ae65e5b1cdfcf4f60d36c0353c857bc27b92f Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Wed, 11 Mar 2026 12:29:43 +0000 Subject: [PATCH 089/775] Warn that overriding `__builtins__` for `eval` is not a security mechanism (GH-145773) Co-authored-by: Ned Batchelder --- Doc/library/functions.rst | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 1d83cb6f2bb..483e5b1d8fd 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -606,17 +606,18 @@ are always available. They are listed here in alphabetical order. .. warning:: This function executes arbitrary code. Calling it with - user-supplied input may lead to security vulnerabilities. + untrusted user-supplied input will lead to security vulnerabilities. The *source* argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the *globals* and *locals* mappings as global and local namespace. If the *globals* dictionary is present and does not contain a value for the key ``__builtins__``, a reference to the dictionary of the built-in module :mod:`builtins` is - inserted under that key before *source* is parsed. That way you can - control what builtins are available to the executed code by inserting your - own ``__builtins__`` dictionary into *globals* before passing it to - :func:`eval`. If the *locals* mapping is omitted it defaults to the + inserted under that key before *source* is parsed. + Overriding ``__builtins__`` can be used to restrict or change the available + names, but this is **not** a security mechanism: the executed code can + still access all builtins. + If the *locals* mapping is omitted it defaults to the *globals* dictionary. If both mappings are omitted, the source is executed with the *globals* and *locals* in the environment where :func:`eval` is called. Note, *eval()* will only have access to the @@ -671,7 +672,7 @@ are always available. They are listed here in alphabetical order. .. warning:: This function executes arbitrary code. Calling it with - user-supplied input may lead to security vulnerabilities. + untrusted user-supplied input will lead to security vulnerabilities. This function supports dynamic execution of Python code. *source* must be either a string or a code object. If it is a string, the string is parsed as @@ -702,9 +703,10 @@ are always available. They are listed here in alphabetical order. If the *globals* dictionary does not contain a value for the key ``__builtins__``, a reference to the dictionary of the built-in module - :mod:`builtins` is inserted under that key. That way you can control what - builtins are available to the executed code by inserting your own - ``__builtins__`` dictionary into *globals* before passing it to :func:`exec`. + :mod:`builtins` is inserted under that key. + Overriding ``__builtins__`` can be used to restrict or change the available + names, but this is **not** a security mechanism: the executed code can + still access all builtins. The *closure* argument specifies a closure--a tuple of cellvars. It's only valid when the *object* is a code object containing From aa4240ebea1aacc907b1efa58e7f547d90cff3b1 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Wed, 11 Mar 2026 14:02:23 +0100 Subject: [PATCH 090/775] gh-145492: fix regression test for defaultdict factory repr (GH-145788) --- Lib/test/test_defaultdict.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py index 732e9a876ca..a193eb10f16 100644 --- a/Lib/test/test_defaultdict.py +++ b/Lib/test/test_defaultdict.py @@ -212,12 +212,12 @@ def __call__(self): return {} def __repr__(self): repr(dd) - return "ProblematicFactory()" + return f"ProblematicFactory for {dd}" dd = defaultdict(ProblematicFactory()) # Should not raise RecursionError r = repr(dd) - self.assertIn('ProblematicFactory()', r) + self.assertIn("ProblematicFactory for", r) if __name__ == "__main__": unittest.main() From 4f87c99a5ae9c74a5f94b91335d85f4662e1ed48 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 11 Mar 2026 14:24:15 +0100 Subject: [PATCH 091/775] gh-145376: Fix refleak & pointer type bug in uncommon code paths in Parser/ (GH-145684) --- Parser/pegen.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Parser/pegen.c b/Parser/pegen.c index 7ecc55eee13..569f5afb312 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -924,7 +924,6 @@ _PyPegen_set_syntax_error_metadata(Parser *p) { the_source // N gives ownership to metadata ); if (!metadata) { - Py_DECREF(the_source); PyErr_Clear(); return; } @@ -1026,8 +1025,8 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena if (tok->fp_interactive && tok->interactive_src_start && result && interactive_src != NULL) { *interactive_src = PyUnicode_FromString(tok->interactive_src_start); - if (!interactive_src || _PyArena_AddPyObject(arena, *interactive_src) < 0) { - Py_XDECREF(interactive_src); + if (!*interactive_src || _PyArena_AddPyObject(arena, *interactive_src) < 0) { + Py_XDECREF(*interactive_src); result = NULL; goto error; } From ce1abaf9b83f8535749c6d3d0a0fabf15d87079f Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 11 Mar 2026 16:25:24 +0300 Subject: [PATCH 092/775] gh-99875: Document rounding mode for old-style formatting (#126382) --- Doc/library/stdtypes.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index a70bda47da6..6b55daa9b6e 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3202,6 +3202,10 @@ The conversion types are: | | character in the result. | | +------------+-----------------------------------------------------+-------+ +For floating-point formats, the result should be correctly rounded to a given +precision ``p`` of digits after the decimal point. The rounding mode matches +that of the :func:`round` builtin. + Notes: (1) From 42d754e34c06e57ad6b8e7f92f32af679912d8ab Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Wed, 11 Mar 2026 08:47:55 -0500 Subject: [PATCH 093/775] gh-141707: Skip TarInfo DIRTYPE normalization during GNU long name handling Co-authored-by: Eashwar Ranganathan --- Lib/tarfile.py | 29 ++++++++++++++++--- Lib/test/test_tarfile.py | 19 ++++++++++++ Misc/ACKS | 1 + ...-11-18-06-35-53.gh-issue-141707.DBmQIy.rst | 2 ++ 4 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 7abda3653e7..7f0b0b3c632 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1276,6 +1276,20 @@ def _create_pax_generic_header(cls, pax_headers, type, encoding): @classmethod def frombuf(cls, buf, encoding, errors): """Construct a TarInfo object from a 512 byte bytes object. + + To support the old v7 tar format AREGTYPE headers are + transformed to DIRTYPE headers if their name ends in '/'. + """ + return cls._frombuf(buf, encoding, errors) + + @classmethod + def _frombuf(cls, buf, encoding, errors, *, dircheck=True): + """Construct a TarInfo object from a 512 byte bytes object. + + If ``dircheck`` is set to ``True`` then ``AREGTYPE`` headers will + be normalized to ``DIRTYPE`` if the name ends in a trailing slash. + ``dircheck`` must be set to ``False`` if this function is called + on a follow-up header such as ``GNUTYPE_LONGNAME``. """ if len(buf) == 0: raise EmptyHeaderError("empty header") @@ -1306,7 +1320,7 @@ def frombuf(cls, buf, encoding, errors): # Old V7 tar format represents a directory as a regular # file with a trailing slash. - if obj.type == AREGTYPE and obj.name.endswith("/"): + if dircheck and obj.type == AREGTYPE and obj.name.endswith("/"): obj.type = DIRTYPE # The old GNU sparse format occupies some of the unused @@ -1341,8 +1355,15 @@ def fromtarfile(cls, tarfile): """Return the next TarInfo object from TarFile object tarfile. """ + return cls._fromtarfile(tarfile) + + @classmethod + def _fromtarfile(cls, tarfile, *, dircheck=True): + """ + See dircheck documentation in _frombuf(). + """ buf = tarfile.fileobj.read(BLOCKSIZE) - obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) + obj = cls._frombuf(buf, tarfile.encoding, tarfile.errors, dircheck=dircheck) obj.offset = tarfile.fileobj.tell() - BLOCKSIZE return obj._proc_member(tarfile) @@ -1400,7 +1421,7 @@ def _proc_gnulong(self, tarfile): # Fetch the next header and process it. try: - next = self.fromtarfile(tarfile) + next = self._fromtarfile(tarfile, dircheck=False) except HeaderError as e: raise SubsequentHeaderError(str(e)) from None @@ -1535,7 +1556,7 @@ def _proc_pax(self, tarfile): # Fetch the next header. try: - next = self.fromtarfile(tarfile) + next = self._fromtarfile(tarfile, dircheck=False) except HeaderError as e: raise SubsequentHeaderError(str(e)) from None diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 139840dd9c1..f2babaacc27 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1234,6 +1234,25 @@ def test_longname_directory(self): self.assertIsNotNone(tar.getmember(longdir)) self.assertIsNotNone(tar.getmember(longdir.removesuffix('/'))) + def test_longname_file_not_directory(self): + # Test reading a longname file and ensure it is not handled as a directory + # Issue #141707 + buf = io.BytesIO() + with tarfile.open(mode='w', fileobj=buf, format=self.format) as tar: + ti = tarfile.TarInfo() + ti.type = tarfile.AREGTYPE + ti.name = ('a' * 99) + '/' + ('b' * 3) + tar.addfile(ti) + + expected = {t.name: t.type for t in tar.getmembers()} + + buf.seek(0) + with tarfile.open(mode='r', fileobj=buf) as tar: + actual = {t.name: t.type for t in tar.getmembers()} + + self.assertEqual(expected, actual) + + class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase): subdir = "gnu" diff --git a/Misc/ACKS b/Misc/ACKS index 88c0a68f1e6..d7762f8c875 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1557,6 +1557,7 @@ Ashwin Ramaswami Jeff Ramnani Grant Ramsay Bayard Randel +Eashwar Ranganathan Varpu Rantala Brodie Rao Rémi Rampin diff --git a/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst b/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst new file mode 100644 index 00000000000..1f5b8ed90b8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst @@ -0,0 +1,2 @@ +Don't change :class:`tarfile.TarInfo` type from ``AREGTYPE`` to ``DIRTYPE`` when parsing +GNU long name or link headers. From 805ca4f292ef18b89a2d25246feb916973acec64 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Wed, 11 Mar 2026 08:51:25 -0500 Subject: [PATCH 094/775] Add GitHub team for maintaining fuzzers Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- .github/CODEOWNERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5bf60348f68..63ec65ac0db 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -132,7 +132,9 @@ Tools/c-analyzer/ @ericsnowcurrently Tools/check-c-api-docs/ @ZeroIntensity # Fuzzing -Modules/_xxtestfuzz/ @ammaraskar +Modules/_xxtestfuzz/ @python/fuzzers +Lib/test/test_xxtestfuzz.py @python/fuzzers +.github/workflows/reusable-cifuzz.yml @python/fuzzers # Limited C API & Stable ABI Doc/c-api/stable.rst @encukou From 7a1da4575b1d8fa87efb62334a8e99cd513d86e9 Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Wed, 11 Mar 2026 15:14:47 +0100 Subject: [PATCH 095/775] gh-142518: Improve mimalloc allocator docs (#145224) --- Doc/c-api/memory.rst | 61 ++++++++++++++++++++++++++++++----------- Doc/using/cmdline.rst | 14 ++++++++-- Doc/using/configure.rst | 3 ++ 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst index 563c5d96b05..9f84e4bc6df 100644 --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -204,8 +204,11 @@ The following function sets, modeled after the ANSI C standard, but specifying behavior when requesting zero bytes, are available for allocating and releasing memory from the Python heap. -The :ref:`default memory allocator ` uses the -:ref:`pymalloc memory allocator `. +In the GIL-enabled build (default build) the +:ref:`default memory allocator ` uses the +:ref:`pymalloc memory allocator `, whereas in the +:term:`free-threaded build`, the default is the +:ref:`mimalloc memory allocator ` instead. .. warning:: @@ -215,6 +218,11 @@ The :ref:`default memory allocator ` uses the The default allocator is now pymalloc instead of system :c:func:`malloc`. +.. versionchanged:: 3.13 + + In the :term:`free-threaded ` build, the default allocator + is now :ref:`mimalloc `. + .. c:function:: void* PyMem_Malloc(size_t n) Allocates *n* bytes and returns a pointer of type :c:expr:`void*` to the @@ -340,7 +348,9 @@ memory from the Python heap. the :ref:`Customize Memory Allocators ` section. The :ref:`default object allocator ` uses the -:ref:`pymalloc memory allocator `. +:ref:`pymalloc memory allocator `. In the +:term:`free-threaded ` build, the default is the +:ref:`mimalloc memory allocator ` instead. .. warning:: @@ -420,14 +430,16 @@ Default Memory Allocators Default memory allocators: -=============================== ==================== ================== ===================== ==================== -Configuration Name PyMem_RawMalloc PyMem_Malloc PyObject_Malloc -=============================== ==================== ================== ===================== ==================== -Release build ``"pymalloc"`` ``malloc`` ``pymalloc`` ``pymalloc`` -Debug build ``"pymalloc_debug"`` ``malloc`` + debug ``pymalloc`` + debug ``pymalloc`` + debug -Release build, without pymalloc ``"malloc"`` ``malloc`` ``malloc`` ``malloc`` -Debug build, without pymalloc ``"malloc_debug"`` ``malloc`` + debug ``malloc`` + debug ``malloc`` + debug -=============================== ==================== ================== ===================== ==================== +=================================== ======================= ==================== ====================== ====================== +Configuration Name PyMem_RawMalloc PyMem_Malloc PyObject_Malloc +=================================== ======================= ==================== ====================== ====================== +Release build ``"pymalloc"`` ``malloc`` ``pymalloc`` ``pymalloc`` +Debug build ``"pymalloc_debug"`` ``malloc`` + debug ``pymalloc`` + debug ``pymalloc`` + debug +Release build, without pymalloc ``"malloc"`` ``malloc`` ``malloc`` ``malloc`` +Debug build, without pymalloc ``"malloc_debug"`` ``malloc`` + debug ``malloc`` + debug ``malloc`` + debug +Free-threaded build ``"mimalloc"`` ``mimalloc`` ``mimalloc`` ``mimalloc`` +Free-threaded debug build ``"mimalloc_debug"`` ``mimalloc`` + debug ``mimalloc`` + debug ``mimalloc`` + debug +=================================== ======================= ==================== ====================== ====================== Legend: @@ -435,8 +447,7 @@ Legend: * ``malloc``: system allocators from the standard C library, C functions: :c:func:`malloc`, :c:func:`calloc`, :c:func:`realloc` and :c:func:`free`. * ``pymalloc``: :ref:`pymalloc memory allocator `. -* ``mimalloc``: :ref:`mimalloc memory allocator `. The pymalloc - allocator will be used if mimalloc support isn't available. +* ``mimalloc``: :ref:`mimalloc memory allocator `. * "+ debug": with :ref:`debug hooks on the Python memory allocators `. * "Debug build": :ref:`Python build in debug mode `. @@ -733,9 +744,27 @@ The mimalloc allocator .. versionadded:: 3.13 -Python supports the mimalloc allocator when the underlying platform support is available. -mimalloc "is a general purpose allocator with excellent performance characteristics. -Initially developed by Daan Leijen for the runtime systems of the Koka and Lean languages." +Python supports the `mimalloc `__ +allocator when the underlying platform support is available. +mimalloc is a general purpose allocator with excellent performance +characteristics, initially developed by Daan Leijen for the runtime systems +of the Koka and Lean languages. + +Unlike :ref:`pymalloc `, which is optimized for small objects (512 +bytes or fewer), mimalloc handles allocations of any size. + +In the :term:`free-threaded ` build, mimalloc is the default +and **required** allocator for the :c:macro:`PYMEM_DOMAIN_MEM` and +:c:macro:`PYMEM_DOMAIN_OBJ` domains. It cannot be disabled in free-threaded +builds. The free-threaded build uses per-thread mimalloc heaps, which allows +allocation and deallocation to proceed without locking in most cases. + +In the default (non-free-threaded) build, mimalloc is available but not the +default allocator. It can be selected at runtime using +:envvar:`PYTHONMALLOC`\ ``=mimalloc`` (or ``mimalloc_debug`` to include +:ref:`debug hooks `). It can be disabled at build time +using the :option:`--without-mimalloc` configure option, but this option +cannot be combined with :option:`--disable-gil`. tracemalloc C API ================= diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 5c3d44395c0..ce6872f3c0f 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -1085,6 +1085,13 @@ conflict. * ``pymalloc_debug``: same as ``pymalloc`` but also install debug hooks. * ``mimalloc_debug``: same as ``mimalloc`` but also install debug hooks. + .. note:: + + In the :term:`free-threaded ` build, the ``malloc``, + ``malloc_debug``, ``pymalloc``, and ``pymalloc_debug`` values are not + supported. Only ``default``, ``debug``, ``mimalloc``, and + ``mimalloc_debug`` are accepted. + .. versionadded:: 3.6 .. versionchanged:: 3.7 @@ -1094,12 +1101,13 @@ conflict. .. envvar:: PYTHONMALLOCSTATS If set to a non-empty string, Python will print statistics of the - :ref:`pymalloc memory allocator ` every time a new pymalloc object - arena is created, and on shutdown. + :ref:`pymalloc memory allocator ` or the + :ref:`mimalloc memory allocator ` (whichever is in use) + every time a new object arena is created, and on shutdown. This variable is ignored if the :envvar:`PYTHONMALLOC` environment variable is used to force the :c:func:`malloc` allocator of the C library, or if - Python is configured without ``pymalloc`` support. + Python is configured without both ``pymalloc`` and ``mimalloc`` support. .. versionchanged:: 3.6 This variable can now also be used on Python compiled in release mode. diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 813127663ed..6bef290d181 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -774,6 +774,9 @@ also be used to improve performance. Disable the fast :ref:`mimalloc ` allocator (enabled by default). + This option cannot be used together with :option:`--disable-gil` + because the :term:`free-threaded ` build requires mimalloc. + See also :envvar:`PYTHONMALLOC` environment variable. .. option:: --without-pymalloc From 4722202a1a81974089801e6173d269836b6a074f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:30:09 +0100 Subject: [PATCH 096/775] gh-139933: correctly suggest attributes for classes with a custom `__dir__` (GH-139950) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Łukasz Langa --- Lib/test/test_traceback.py | 21 ++++++++++++++ Lib/traceback.py | 29 ++++++++++--------- ...-10-11-11-50-59.gh-issue-139933.05MHlx.rst | 3 ++ 3 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 2fbc2a04126..14a08995bf1 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -4213,6 +4213,27 @@ def method(self, name): self.assertIn("'._bluch'", self.get_suggestion(partial(B().method, '_luch'))) self.assertIn("'._bluch'", self.get_suggestion(partial(B().method, 'bluch'))) + def test_suggestions_with_custom___dir__(self): + class M(type): + def __dir__(cls): + return [None, "fox"] + + class C0: + def __dir__(self): + return [..., "bluch"] + + class C1(C0, metaclass=M): + pass + + self.assertNotIn("'.bluch'", self.get_suggestion(C0, "blach")) + self.assertIn("'.bluch'", self.get_suggestion(C0(), "blach")) + + self.assertIn("'.fox'", self.get_suggestion(C1, "foo")) + self.assertNotIn("'.fox'", self.get_suggestion(C1(), "foo")) + + self.assertNotIn("'.bluch'", self.get_suggestion(C1, "blach")) + self.assertIn("'.bluch'", self.get_suggestion(C1(), "blach")) + def test_do_not_trigger_for_long_attributes(self): class A: diff --git a/Lib/traceback.py b/Lib/traceback.py index 4e809acb7a0..956cab49131 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1698,6 +1698,19 @@ def _check_for_nested_attribute(obj, wrong_name, attrs): return None +def _get_safe___dir__(obj): + # Use obj.__dir__() to avoid a TypeError when calling dir(obj). + # See gh-131001 and gh-139933. + # Also filters out lazy imports to avoid triggering module loading. + try: + d = obj.__dir__() + except TypeError: # when obj is a class + d = type(obj).__dir__(obj) + return sorted( + x for x in d if isinstance(x, str) and not _is_lazy_import(obj, x) + ) + + def _compute_suggestion_error(exc_value, tb, wrong_name): if wrong_name is None or not isinstance(wrong_name, str): return None @@ -1711,13 +1724,7 @@ def _compute_suggestion_error(exc_value, tb, wrong_name): if isinstance(exc_value, AttributeError): obj = exc_value.obj try: - try: - d = dir(obj) - except TypeError: # Attributes are unsortable, e.g. int and str - d = list(obj.__class__.__dict__.keys()) + list(obj.__dict__.keys()) - d = sorted([x for x in d if isinstance(x, str)]) - # Filter out lazy imports to avoid triggering module loading - d = [x for x in d if not _is_lazy_import(obj, x)] + d = _get_safe___dir__(obj) hide_underscored = (wrong_name[:1] != '_') if hide_underscored and tb is not None: while tb.tb_next is not None: @@ -1744,13 +1751,7 @@ def _compute_suggestion_error(exc_value, tb, wrong_name): elif isinstance(exc_value, ImportError): try: mod = __import__(exc_value.name) - try: - d = dir(mod) - except TypeError: # Attributes are unsortable, e.g. int and str - d = list(mod.__dict__.keys()) - d = sorted([x for x in d if isinstance(x, str)]) - # Filter out lazy imports to avoid triggering module loading - d = [x for x in d if not _is_lazy_import(mod, x)] + d = _get_safe___dir__(mod) if wrong_name[:1] != '_': d = [x for x in d if x[:1] != '_'] except Exception: diff --git a/Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst b/Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst new file mode 100644 index 00000000000..d76f0873d77 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst @@ -0,0 +1,3 @@ +Improve :exc:`AttributeError` suggestions for classes with a custom +:meth:`~object.__dir__` method returning a list of unsortable values. +Patch by Bénédikt Tran. From 706fd4ec08acbf1b1def3630017ebe55d224adfa Mon Sep 17 00:00:00 2001 From: "T. Wouters" Date: Wed, 11 Mar 2026 15:46:16 +0100 Subject: [PATCH 097/775] gh-142183: Cache one datachunk per tstate to prevent alloc/dealloc thrashing (#145789) Cache one datachunk per tstate to prevent alloc/dealloc thrashing when repeatedly hitting the same call depth at exactly the wrong boundary. --------- Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Include/cpython/pystate.h | 1 + ...-03-11-00-13-59.gh-issue-142183.2iVhJH.rst | 1 + Python/pystate.c | 30 ++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 22df26bd37a..1c56ad5af80 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -198,6 +198,7 @@ struct _ts { _PyStackChunk *datastack_chunk; PyObject **datastack_top; PyObject **datastack_limit; + _PyStackChunk *datastack_cached_chunk; /* XXX signal handlers should also be here */ /* The following fields are here to avoid allocation during init. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst new file mode 100644 index 00000000000..827224dc71e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst @@ -0,0 +1 @@ +Avoid a pathological case where repeated calls at a specific stack depth could be significantly slower. diff --git a/Python/pystate.c b/Python/pystate.c index a8f37bedc81..17b8430b19c 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1564,6 +1564,7 @@ init_threadstate(_PyThreadStateImpl *_tstate, tstate->datastack_chunk = NULL; tstate->datastack_top = NULL; tstate->datastack_limit = NULL; + tstate->datastack_cached_chunk = NULL; tstate->what_event = -1; tstate->current_executor = NULL; tstate->jit_exit = NULL; @@ -1714,6 +1715,11 @@ clear_datastack(PyThreadState *tstate) _PyObject_VirtualFree(chunk, chunk->size); chunk = prev; } + if (tstate->datastack_cached_chunk != NULL) { + _PyObject_VirtualFree(tstate->datastack_cached_chunk, + tstate->datastack_cached_chunk->size); + tstate->datastack_cached_chunk = NULL; + } } void @@ -3045,9 +3051,20 @@ push_chunk(PyThreadState *tstate, int size) while (allocate_size < (int)sizeof(PyObject*)*(size + MINIMUM_OVERHEAD)) { allocate_size *= 2; } - _PyStackChunk *new = allocate_chunk(allocate_size, tstate->datastack_chunk); - if (new == NULL) { - return NULL; + _PyStackChunk *new; + if (tstate->datastack_cached_chunk != NULL + && (size_t)allocate_size <= tstate->datastack_cached_chunk->size) + { + new = tstate->datastack_cached_chunk; + tstate->datastack_cached_chunk = NULL; + new->previous = tstate->datastack_chunk; + new->top = 0; + } + else { + new = allocate_chunk(allocate_size, tstate->datastack_chunk); + if (new == NULL) { + return NULL; + } } if (tstate->datastack_chunk) { tstate->datastack_chunk->top = tstate->datastack_top - @@ -3083,12 +3100,17 @@ _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame) if (base == &tstate->datastack_chunk->data[0]) { _PyStackChunk *chunk = tstate->datastack_chunk; _PyStackChunk *previous = chunk->previous; + _PyStackChunk *cached = tstate->datastack_cached_chunk; // push_chunk ensures that the root chunk is never popped: assert(previous); tstate->datastack_top = &previous->data[previous->top]; tstate->datastack_chunk = previous; - _PyObject_VirtualFree(chunk, chunk->size); tstate->datastack_limit = (PyObject **)(((char *)previous) + previous->size); + chunk->previous = NULL; + if (cached != NULL) { + _PyObject_VirtualFree(cached, cached->size); + } + tstate->datastack_cached_chunk = chunk; } else { assert(tstate->datastack_top); From 713be70175a2dad477a1cf5e7c00bab0edda04ad Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 11 Mar 2026 17:05:09 +0100 Subject: [PATCH 098/775] gh-141510: Raise TypeError in PyDict_SetItem() on frozendict (#145564) If the following functions get an unexpected frozendict, raise TypeError instead of SystemError: * PyDict_DelItem() * PyDict_DelItemString() * PyDict_Merge() * PyDict_MergeFromSeq2() * PyDict_Pop() * PyDict_PopString() * PyDict_SetDefault() * PyDict_SetDefaultRef() * PyDict_SetItem() * PyDict_SetItemString() * _PyDict_SetItem_KnownHash() * PyDict_Update() Co-authored-by: mohsinm-dev --- Lib/test/test_capi/test_dict.py | 62 +++++++++++++++++---- Objects/dictobject.c | 96 +++++++++++++++++++++++++-------- 2 files changed, 125 insertions(+), 33 deletions(-) diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py index cd46fea5476..4cf404e9f56 100644 --- a/Lib/test/test_capi/test_dict.py +++ b/Lib/test/test_capi/test_dict.py @@ -1,3 +1,4 @@ +import contextlib import unittest from collections import OrderedDict, UserDict from types import MappingProxyType @@ -258,6 +259,12 @@ def test_dict_contains_string(self): # CRASHES contains({}, NULL) # CRASHES contains(NULL, b'a') + @contextlib.contextmanager + def frozendict_does_not_support(self, what): + errmsg = f'frozendict object does not support item {what}' + with self.assertRaisesRegex(TypeError, errmsg): + yield + def test_dict_setitem(self): # Test PyDict_SetItem() setitem = _testlimitedcapi.dict_setitem @@ -269,7 +276,10 @@ def test_dict_setitem(self): self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) self.assertRaises(TypeError, setitem, {}, [], 5) # unhashable - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setitem(test_type(), 'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: self.assertRaises(SystemError, setitem, test_type(), 'a', 5) # CRASHES setitem({}, NULL, 5) # CRASHES setitem({}, 'a', NULL) @@ -286,7 +296,10 @@ def test_dict_setitemstring(self): self.assertEqual(dct, {'a': 5, '\U0001f40d': 8}) self.assertRaises(UnicodeDecodeError, setitemstring, {}, INVALID_UTF8, 5) - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setitemstring(test_type(), b'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: self.assertRaises(SystemError, setitemstring, test_type(), b'a', 5) # CRASHES setitemstring({}, NULL, 5) # CRASHES setitemstring({}, b'a', NULL) @@ -304,7 +317,10 @@ def test_dict_delitem(self): self.assertEqual(dct, {'c': 2}) self.assertRaises(TypeError, delitem, {}, []) # unhashable - for test_type in NOT_DICT_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + delitem(test_type({'a': 1}), 'a') + for test_type in MAPPING_TYPES: self.assertRaises(SystemError, delitem, test_type({'a': 1}), 'a') for test_type in OTHER_TYPES: self.assertRaises(SystemError, delitem, test_type(), 'a') @@ -323,7 +339,10 @@ def test_dict_delitemstring(self): self.assertEqual(dct, {'c': 2}) self.assertRaises(UnicodeDecodeError, delitemstring, {}, INVALID_UTF8) - for test_type in NOT_DICT_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + delitemstring(test_type({'a': 1}), b'a') + for test_type in MAPPING_TYPES: self.assertRaises(SystemError, delitemstring, test_type({'a': 1}), b'a') for test_type in OTHER_TYPES: self.assertRaises(SystemError, delitemstring, test_type(), b'a') @@ -341,7 +360,10 @@ def test_dict_setdefault(self): self.assertEqual(dct, {'a': 5}) self.assertRaises(TypeError, setdefault, {}, [], 5) # unhashable - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setdefault(test_type(), 'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: self.assertRaises(SystemError, setdefault, test_type(), 'a', 5) # CRASHES setdefault({}, NULL, 5) # CRASHES setdefault({}, 'a', NULL) @@ -358,7 +380,10 @@ def test_dict_setdefaultref(self): self.assertEqual(dct, {'a': 5}) self.assertRaises(TypeError, setdefault, {}, [], 5) # unhashable - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + setdefault(test_type(), 'a', 5) + for test_type in MAPPING_TYPES + OTHER_TYPES: self.assertRaises(SystemError, setdefault, test_type(), 'a', 5) # CRASHES setdefault({}, NULL, 5) # CRASHES setdefault({}, 'a', NULL) @@ -424,7 +449,10 @@ def test_dict_update(self): self.assertRaises(AttributeError, update, {}, []) self.assertRaises(AttributeError, update, {}, 42) - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + update(test_type(), {}) + for test_type in MAPPING_TYPES + OTHER_TYPES: self.assertRaises(SystemError, update, test_type(), {}) self.assertRaises(SystemError, update, {}, NULL) self.assertRaises(SystemError, update, NULL, {}) @@ -443,7 +471,10 @@ def test_dict_merge(self): self.assertRaises(AttributeError, merge, {}, [], 0) self.assertRaises(AttributeError, merge, {}, 42, 0) - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + merge(test_type(), {}, 0) + for test_type in MAPPING_TYPES + OTHER_TYPES: self.assertRaises(SystemError, merge, test_type(), {}, 0) self.assertRaises(SystemError, merge, {}, NULL, 0) self.assertRaises(SystemError, merge, NULL, {}, 0) @@ -464,7 +495,10 @@ def test_dict_mergefromseq2(self): self.assertRaises(ValueError, mergefromseq2, {}, [(1, 2, 3)], 0) self.assertRaises(TypeError, mergefromseq2, {}, [1], 0) self.assertRaises(TypeError, mergefromseq2, {}, 42, 0) - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('assignment'): + mergefromseq2(test_type(), [], 0) + for test_type in MAPPING_TYPES + OTHER_TYPES: self.assertRaises(SystemError, mergefromseq2, test_type(), [], 0) # CRASHES mergefromseq2({}, NULL, 0) # CRASHES mergefromseq2(NULL, {}, 0) @@ -511,7 +545,10 @@ def test_dict_pop(self): dict_pop(mydict, not_hashable_key) # wrong dict type - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + dict_pop(test_type(), "key") + for test_type in MAPPING_TYPES + OTHER_TYPES: not_dict = test_type() self.assertRaises(SystemError, dict_pop, not_dict, "key") self.assertRaises(SystemError, dict_pop_null, not_dict, "key") @@ -560,7 +597,10 @@ def test_dict_popstring(self): self.assertRaises(UnicodeDecodeError, dict_popstring_null, mydict, INVALID_UTF8) # wrong dict type - for test_type in NOT_DICT_TYPES + OTHER_TYPES: + for test_type in FROZENDICT_TYPES: + with self.frozendict_does_not_support('deletion'): + dict_popstring(test_type(), "key") + for test_type in MAPPING_TYPES + OTHER_TYPES: not_dict = test_type() self.assertRaises(SystemError, dict_popstring, not_dict, "key") self.assertRaises(SystemError, dict_popstring_null, not_dict, "key") diff --git a/Objects/dictobject.c b/Objects/dictobject.c index b5f2a682c54..842d9be73b8 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2719,6 +2719,10 @@ _PyDict_LoadBuiltinsFromGlobals(PyObject *globals) return builtins; } +#define frozendict_does_not_support(WHAT) \ + PyErr_SetString(PyExc_TypeError, "frozendict object does " \ + "not support item " WHAT) + /* Consumes references to key and value */ static int setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) @@ -2762,12 +2766,19 @@ _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) int PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) { - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } assert(key); assert(value); + + if (!PyDict_Check(op)) { + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } + return -1; + } + return _PyDict_SetItem_Take2((PyDictObject *)op, Py_NewRef(key), Py_NewRef(value)); } @@ -2807,14 +2818,20 @@ int _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value, Py_hash_t hash) { - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } assert(key); assert(value); assert(hash != -1); + if (!PyDict_Check(op)) { + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } + return -1; + } + int res; Py_BEGIN_CRITICAL_SECTION(op); res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)op, key, value, hash); @@ -2899,13 +2916,18 @@ PyDict_DelItem(PyObject *op, PyObject *key) int _PyDict_DelItem_KnownHash_LockHeld(PyObject *op, PyObject *key, Py_hash_t hash) { - Py_ssize_t ix; - PyObject *old_value; - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("deletion"); + } + else { + PyErr_BadInternalCall(); + } return -1; } + + Py_ssize_t ix; + PyObject *old_value; PyDictObject *mp = (PyDictObject *)op; assert(can_modify_dict(mp)); @@ -3206,7 +3228,12 @@ pop_lock_held(PyObject *op, PyObject *key, PyObject **result) if (result) { *result = NULL; } - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("deletion"); + } + else { + PyErr_BadInternalCall(); + } return -1; } PyDictObject *dict = (PyDictObject *)op; @@ -4017,7 +4044,12 @@ PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override) assert(d != NULL); assert(seq2 != NULL); if (!PyDict_Check(d)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(d)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } return -1; } @@ -4220,7 +4252,12 @@ dict_merge_api(PyObject *a, PyObject *b, int override) * PyMapping_Keys() and PyObject_GetItem() be supported. */ if (a == NULL || !PyDict_Check(a) || b == NULL) { - PyErr_BadInternalCall(); + if (a != NULL && PyFrozenDict_Check(a)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } return -1; } return dict_merge(a, b, override); @@ -4596,13 +4633,13 @@ static int dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_value, PyObject **result, int incref_result) { - PyDictObject *mp = (PyDictObject *)d; - PyObject *value; - Py_hash_t hash; - Py_ssize_t ix; - if (!PyDict_Check(d)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(d)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } if (result) { *result = NULL; } @@ -4610,6 +4647,11 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu } assert(can_modify_dict((PyDictObject*)d)); + PyDictObject *mp = (PyDictObject *)d; + PyObject *value; + Py_hash_t hash; + Py_ssize_t ix; + hash = _PyObject_HashFast(key); if (hash == -1) { dict_unhashable_type(d, key); @@ -7154,7 +7196,17 @@ int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value) { if (!PyDict_Check(dict)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(dict)) { + if (value == NULL) { + frozendict_does_not_support("deletion"); + } + else { + frozendict_does_not_support("assignment"); + } + } + else { + PyErr_BadInternalCall(); + } return -1; } From 77d6d5d8fcc8565034dac378b2184131af735512 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 11 Mar 2026 21:01:03 +0200 Subject: [PATCH 099/775] gh-145736: Fix Tkinter tests for Tk 8.7, 9.0 and 9.1 (GH-145738) --- Lib/test/test_tkinter/test_widgets.py | 230 +++++++++++--------------- Lib/test/test_tkinter/widget_tests.py | 90 ++++------ Lib/test/test_ttk/test_widgets.py | 4 +- 3 files changed, 129 insertions(+), 195 deletions(-) diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index f3579a23afc..1c400e970eb 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -26,12 +26,8 @@ def float_round(x): return float(round(x)) class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} - if tk_version < (9, 0): + _no_round = {'padx', 'pady'} + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: _clipped = {'borderwidth', 'height', 'highlightthickness', 'padx', @@ -122,11 +118,6 @@ class FrameTest(AbstractToplevelTest, unittest.TestCase): 'highlightbackground', 'highlightcolor', 'highlightthickness', 'padx', 'pady', 'relief', 'takefocus', 'tile', 'visual', 'width', ) - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} def create(self, **kwargs): return tkinter.Frame(self.root, **kwargs) @@ -142,11 +133,6 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase): 'labelanchor', 'labelwidget', 'padx', 'pady', 'relief', 'takefocus', 'text', 'visual', 'width', ) - if tk_version < (9, 0): - _no_round = {'padx', 'pady'} - else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'padx', - 'pady', 'width'} def create(self, **kwargs): return tkinter.LabelFrame(self.root, **kwargs) @@ -167,11 +153,19 @@ def test_configure_labelwidget(self): # Label, Button, Checkbutton, Radiobutton, MenuButton class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests): _rounds_pixels = False - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'height', 'highlightthickness', 'padx', 'pady', 'width'} else: - _clipped = {'borderwidth', 'insertborderwidth', 'highlightthickness', - 'padx', 'pady'} + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'padx', 'pady', 'width'} + + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 2): + self._clipped = self._clipped - {'height', 'width'} + @add_configure_tests(StandardOptionsTests) class LabelTest(AbstractLabelTest, unittest.TestCase): @@ -201,6 +195,11 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase): 'repeatdelay', 'repeatinterval', 'state', 'takefocus', 'text', 'textvariable', 'underline', 'width', 'wraplength') + if tk_version < (8, 7): + _clipped = {} + else: + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'padx', 'pady', 'width'} def create(self, **kwargs): return tkinter.Button(self.root, **kwargs) @@ -301,10 +300,17 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase): 'underline', 'width', 'wraplength', ) _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness', 'padx', 'pady'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} else: - _clipped ={ 'insertborderwidth', 'highlightthickness', 'padx', 'pady'} + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', 'padx', 'pady'} + + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._clipped = self._clipped - {'borderwidth'} def create(self, **kwargs): return tkinter.Menubutton(self.root, **kwargs) @@ -316,16 +322,17 @@ def test_configure_direction(self): def test_configure_height(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=str) + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): + conv = str else: - self.checkIntegerParam(widget, 'height', 0, -100, 0) + conv = False + self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=conv) def test_configure_image(self): widget = self.create() image = tkinter.PhotoImage(master=self.root, name='image1') self.checkParam(widget, 'image', image, conv=str) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -346,10 +353,11 @@ def test_configure_menu(self): def test_configure_width(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=str) + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): + conv = str else: - self.checkIntegerParam(widget, 'width', 402, 0, 0) + conv = False + self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=conv) class OptionMenuTest(MenubuttonTest, unittest.TestCase): @@ -368,12 +376,11 @@ def test_specify_name(self): @add_configure_tests(IntegerSizeTests, StandardOptionsTests) class EntryTest(AbstractWidgetTest, unittest.TestCase): - _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = {'highlightthickness', 'borderwidth', 'insertborderwidth', - 'selectborderwidth'} + _clipped = {'borderwidth', 'highlightthickness', 'insertborderwidth', + 'insertwidth', 'selectborderwidth'} OPTIONS = ( 'background', 'borderwidth', 'cursor', @@ -398,28 +405,21 @@ def test_configure_disabledbackground(self): def test_configure_insertborderwidth(self): widget = self.create(insertwidth=100) - if tk_version < (9, 0): - self.checkPixelsParam(widget, 'insertborderwidth', - 0, 1.3, 2.6, 6, '10p') - else: - self.checkPixelsParam(widget, 'insertborderwidth', - 0, 1.3, 3, 6, '10p') - self.checkParam(widget, 'insertborderwidth', -2) + self.checkPixelsParam(widget, 'insertborderwidth', + 0, 1.3, 2.6, 6, -2, '10p') # insertborderwidth is bounded above by a half of insertwidth. - expected = 100 // 2 if tk_version < (9, 0) else 60 + expected = 100 // 2 if tk_version < (8, 7) else 60 self.checkParam(widget, 'insertborderwidth', 60, expected=expected) def test_configure_insertwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p') - if tk_version < (9, 0): + self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, 0.9, '10p') + if tk_version < (8, 7): + self.checkParam(widget, 'insertwidth', 0, expected=2) self.checkParam(widget, 'insertwidth', 0.1, expected=2) self.checkParam(widget, 'insertwidth', -2, expected=2) - self.checkParam(widget, 'insertwidth', 0.9, expected=1) else: - self.checkParam(widget, 'insertwidth', 0.1) - self.checkParam(widget, 'insertwidth', -2, expected=0) - self.checkParam(widget, 'insertwidth', 0.9) + self.checkPixelsParam(widget, 'insertwidth', 0, 0.1, -2) def test_configure_invalidcommand(self): widget = self.create() @@ -562,7 +562,7 @@ def test_configure_values(self): # XXX widget = self.create() self.assertEqual(widget['values'], '') - if tk_version < (9, 0): + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): expected = 'mon tue wed thur' else: expected = ('mon', 'tue', 'wed', 'thur') @@ -571,7 +571,7 @@ def test_configure_values(self): self.checkParam(widget, 'values', ('mon', 'tue', 'wed', 'thur'), expected=expected) - if tk_version < (9, 0): + if tk_version < (8, 7) or (tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1)): expected = '42 3.14 {} {any string}' else: expected = (42, 3.14, '', 'any string') @@ -640,9 +640,20 @@ class TextTest(AbstractWidgetTest, unittest.TestCase): 'tabs', 'tabstyle', 'takefocus', 'undo', 'width', 'wrap', 'xscrollcommand', 'yscrollcommand', ) - _rounds_pixels = (tk_version < (9, 0)) _no_round = {'selectborderwidth'} - _clipped = {'highlightthickness'} + if tk_version < (9, 0): + _clipped = {'highlightthickness', 'spacing1', 'spacing2', 'spacing3'} + else: + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'insertwidth', 'padx', 'pady', + 'selectborderwidth', 'spacing1', 'spacing2', 'spacing3'} + + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 2): + self._clipped = self._clipped - {'borderwidth', 'height', 'padx', 'pady'} + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._clipped = self._clipped - {'insertborderwidth', 'insertwidth', 'selectborderwidth'} def create(self, **kwargs): return tkinter.Text(self.root, **kwargs) @@ -671,9 +682,11 @@ def test_configure_endline(self): def test_configure_height(self): widget = self.create() self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c') - expected = 1 if tk_version < (9, 0) else 0 - self.checkParam(widget, 'height', -100, expected=expected) - self.checkParam(widget, 'height', 0, expected=expected) + if tk_version < (9, 0): + self.checkParam(widget, 'height', 0, expected=1) + self.checkParam(widget, 'height', -100, expected=1) + else: + self.checkPixelsParam(widget, 'height', 0, -100) def test_configure_maxundo(self): widget = self.create() @@ -689,26 +702,17 @@ def test_configure_insertunfocussed(self): self.checkEnumParam(widget, 'insertunfocussed', 'hollow', 'none', 'solid') - def test_configure_selectborderwidth(self): - widget = self.create() - value = -2 if tk_version < (9, 0) else 0 - self.checkPixelsParam(widget, 'selectborderwidth', - 1.3, 2.6, value, '10p', conv=False) - def test_configure_spacing1(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, '0.5c') - self.checkParam(widget, 'spacing1', -5, expected=0) + self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, -5, '0.5c') def test_configure_spacing2(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, '0.1c') - self.checkParam(widget, 'spacing2', -1, expected=0) + self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, -1, '0.1c') def test_configure_spacing3(self): widget = self.create() - self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, '0.5c') - self.checkParam(widget, 'spacing3', -10, expected=0) + self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, -10, '0.5c') def test_configure_startline(self): widget = self.create() @@ -781,17 +785,22 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase): 'xscrollcommand', 'xscrollincrement', 'yscrollcommand', 'yscrollincrement', 'width', ) - _rounds_pixels = True - if tk_version < (9, 0): - _noround = {} + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _no_round = {'borderwidth', 'height', 'highlightthickness', 'width', - 'xscrollincrement', 'yscrollincrement'} - _clipped = {'borderwidth', 'height', 'highlightthickness', 'width', - 'xscrollincrement', 'yscrollincrement'} + _clipped = {'borderwidth', 'height', 'highlightthickness', + 'insertborderwidth', 'insertwidth', 'selectborderwidth', + 'width', 'xscrollincrement', 'yscrollincrement'} _stringify = True + def setUp(self): + super().setUp() + if tk_version[:2] == (9, 0) and get_tk_patchlevel(self.root) < (9, 0, 1): + self._rounds_pixels = True + self._no_round = {'borderwidth', 'height', 'highlightthickness', + 'width', 'xscrollincrement', 'yscrollincrement'} + self._clipped = self._clipped - {'insertborderwidth', 'insertwidth', 'selectborderwidth'} + def create(self, **kwargs): return tkinter.Canvas(self.root, **kwargs) @@ -938,7 +947,6 @@ def test_create_line(self): def test_create_polygon(self): c = self.create() - tk87 = tk_version >= (8, 7) # In Tk < 8.7 polygons are filled, but has no outline by default. # This affects its size, so always explicitly specify outline. i1 = c.create_polygon(20, 30, 40, 50, 60, 10, outline='red') @@ -1043,11 +1051,10 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase): 'selectmode', 'setgrid', 'state', 'takefocus', 'width', 'xscrollcommand', 'yscrollcommand', ) - _rounds_pixels = (tk_version < (9, 0)) - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = { 'borderwidth', 'highlightthickness', 'selectborderwidth'} + _clipped = {'borderwidth', 'highlightthickness', 'selectborderwidth'} def create(self, **kwargs): return tkinter.Listbox(self.root, **kwargs) @@ -1185,7 +1192,6 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase): 'resolution', 'showvalue', 'sliderlength', 'sliderrelief', 'state', 'takefocus', 'tickinterval', 'to', 'troughcolor', 'variable', 'width', ) - _rounds_pixels = (tk_version < (9, 0)) _clipped = {'highlightthickness'} default_orient = 'vertical' @@ -1255,14 +1261,13 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): 'repeatdelay', 'repeatinterval', 'takefocus', 'troughcolor', 'width', ) - _rounds_pixels = True - if tk_version >= (9, 0): - _no_round = {'borderwidth', 'elementborderwidth', 'highlightthickness', - 'width'} - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} + elif tk_version < (9, 0): + _clipped = {'borderwidth', 'elementborderwidth', 'highlightthickness'} else: - _clipped = {'borderwidth', 'highlightthickness', 'width'} + _clipped = {'borderwidth', 'elementborderwidth', 'highlightthickness', 'width'} + _clipped_to_default = {'elementborderwidth'} _stringify = True default_orient = 'vertical' @@ -1271,9 +1276,7 @@ def create(self, **kwargs): def test_configure_elementborderwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, '1m') - expected = self._default_pixels if tk_version >= (8, 7) else -2 - self.checkParam(widget, 'elementborderwidth', -2, expected=expected) + self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, -2, '1m') def test_configure_orient(self): widget = self.create() @@ -1300,7 +1303,7 @@ def test_set(self): self.assertRaises(TypeError, sb.set, 0.6, 0.7, 0.8) -@add_configure_tests(StandardOptionsTests) +@add_configure_tests(PixelSizeTests, StandardOptionsTests) class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): OPTIONS = ( 'background', 'borderwidth', 'cursor', @@ -1311,14 +1314,8 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): 'sashcursor', 'sashpad', 'sashrelief', 'sashwidth', 'showhandle', 'width', ) - _rounds_pixels = True - if tk_version < (9, 0): - _no_round = {'handlesize', 'height', 'proxyborderwidth', 'sashwidth', - 'selectborderwidth', 'width'} - else: - _no_round = {'borderwidth', 'handlepad', 'handlesize', 'height', - 'proxyborderwidth', 'sashpad', 'sashwidth', - 'selectborderwidth', 'width'} + _no_round = {'handlesize', 'height', 'proxyborderwidth', 'sashwidth', + 'selectborderwidth', 'width'} _clipped = {} default_orient = 'horizontal' @@ -1331,13 +1328,7 @@ def test_configure_handlepad(self): def test_configure_handlesize(self): widget = self.create() - self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m', - conv=False) - - def test_configure_height(self): - widget = self.create() - self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i', - conv=False) + self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m') def test_configure_opaqueresize(self): widget = self.create() @@ -1352,8 +1343,7 @@ def test_configure_proxybackground(self): def test_configure_proxyborderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'proxyborderwidth', - 0, 1.3, 2.9, 6, -2, '10p', - conv=False) + 0, 1.3, 2.9, 6, -2, '10p') @requires_tk(8, 6, 5) def test_configure_proxyrelief(self): @@ -1375,18 +1365,12 @@ def test_configure_sashrelief(self): def test_configure_sashwidth(self): widget = self.create() - self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m', - conv=False) + self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m') def test_configure_showhandle(self): widget = self.create() self.checkBooleanParam(widget, 'showhandle') - def test_configure_width(self): - widget = self.create() - self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i', - conv=False) - def create2(self): p = self.create() b = tkinter.Button(p) @@ -1568,12 +1552,12 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase): 'justify', 'padx', 'pady', 'relief', 'takefocus', 'text', 'textvariable', 'width', ) - _rounds_pixels = (tk_version < (9, 0)) _no_round = {'padx', 'pady'} - if tk_version < (9, 0): + if tk_version < (8, 7): _clipped = {'highlightthickness'} else: - _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady'} + _clipped = {'borderwidth', 'highlightthickness', 'padx', 'pady', 'width'} + _clipped_to_default = {'padx', 'pady'} def create(self, **kwargs): return tkinter.Message(self.root, **kwargs) @@ -1582,24 +1566,6 @@ def test_configure_aspect(self): widget = self.create() self.checkIntegerParam(widget, 'aspect', 250, 0, -300) - def test_configure_padx(self): - widget = self.create() - self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m') - expected = -2 if tk_version < (9, 0) else self._default_pixels - self.checkParam(widget, 'padx', -2, expected=expected) - - def test_configure_pady(self): - widget = self.create() - self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m') - expected = -2 if tk_version < (9, 0) else self._default_pixels - self.checkParam(widget, 'pady', -2, expected=expected) - - def test_configure_width(self): - widget = self.create() - self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, 0, '5i') - expected = 0 if tk_version >= (8, 7) else -402 - self.checkParam(widget, 'width', -402, expected=expected) - class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): diff --git a/Lib/test/test_tkinter/widget_tests.py b/Lib/test/test_tkinter/widget_tests.py index dd2d7c4da45..94244a8b3fe 100644 --- a/Lib/test/test_tkinter/widget_tests.py +++ b/Lib/test/test_tkinter/widget_tests.py @@ -12,11 +12,12 @@ # borderwidth = bd class AbstractWidgetTest(AbstractTkTest): - _default_pixels = '' # Value for unset pixel options. - _rounds_pixels = True # True if some pixel options are rounded. - _no_round = {} # Pixel options which are not rounded nonetheless + _default_pixels = '' if tk_version >= (9, 0) else -1 # Value for unset pixel options. + _rounds_pixels = (tk_version < (9, 0)) # True if some pixel options are rounded. + _no_round = set() # Pixel options which are not rounded nonetheless _stringify = False # Whether to convert tuples to strings _allow_empty_justify = False + _clipped_to_default = set() @property def scaling(self): @@ -43,9 +44,12 @@ def checkParam(self, widget, name, value, *, expected=_sentinel, widget[name] = value if expected is _sentinel: expected = value - if name in self._clipped: - if not isinstance(expected, str): - expected = max(expected, 0) + if name in self._clipped: + if not isinstance(expected, str) and expected < 0: + if tk_version >= (8, 7) and name in self._clipped_to_default: + expected = self._default_pixels + else: + expected = 0 if conv: expected = conv(expected) if self._stringify or not self.wantobjects: @@ -143,10 +147,10 @@ def checkEnumParam(self, widget, name, *values, self.checkInvalidParam(widget, name, 'spam', errmsg=errmsg) def checkPixelsParam(self, widget, name, *values, conv=None, **kwargs): - if not self._rounds_pixels or name in self._no_round: - conv = False - elif conv != str: - conv = round + if conv is None: + if self._rounds_pixels and name not in self._no_round: + conv = round + alow_neg = tk_version < (9, 1) for value in values: expected = _sentinel conv1 = conv @@ -156,6 +160,9 @@ def checkPixelsParam(self, widget, name, *values, conv=None, **kwargs): if conv1 and conv1 is not str: expected = pixels_conv(value) * self.scaling conv1 = round + elif not alow_neg and isinstance(value, (int, float)) and value < 0: + self.checkInvalidParam(widget, name, value) + continue self.checkParam(widget, name, value, expected=expected, conv=conv1, **kwargs) errmsg = '(bad|expected) screen distance ((or "" )?but got )?"{}"' @@ -177,7 +184,7 @@ def checkReliefParam(self, widget, name, *, allow_empty=False): def checkImageParam(self, widget, name): image = tkinter.PhotoImage(master=self.root, name='image1') self.checkParam(widget, name, image, conv=str) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -246,11 +253,7 @@ def test_configure_activeborderwidth(self): def test_configure_borderwidth(self): widget = self.create() self.checkPixelsParam(widget, 'borderwidth', - 0, 1.3, 2.6, 6, '10p') - if tk_version < (9, 0): - self.checkParam(widget, 'borderwidth', -2) - else: - self.checkParam(widget, 'borderwidth', 0) + 0, 1.3, 2.6, 6, -2, '10p') if 'bd' in self.OPTIONS: self.checkPixelsParam(widget, 'bd', 0, 1.3, 2.6, 6, '10p') @@ -259,50 +262,27 @@ def test_configure_borderwidth(self): def test_configure_highlightthickness(self): widget = self.create() self.checkPixelsParam(widget, 'highlightthickness', - 0, 1.3, 2.6, 6, '10p') - self.checkParam(widget, 'highlightthickness', -2) + 0, 1.3, 2.6, 6, -2, '10p') def test_configure_insertborderwidth(self): widget = self.create() - if tk_version < (9, 0): - values = (0, 1.3, 2.6, 6, -2, '10p') - value = -2 - else: - values = (0, 1, 3, 6, 13) - value = 0 - self.checkPixelsParam(widget, 'insertborderwidth', *values) - self.checkParam(widget, 'insertborderwidth', value) + self.checkPixelsParam(widget, 'insertborderwidth', 0, 1.3, 2.6, 6, -2, '10p') def test_configure_insertwidth(self): widget = self.create() - if tk_version < (9, 0): - self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p') - else: - self.checkPixelsParam(widget, 'insertwidth', 1, 3, 0, 13) + self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p') def test_configure_padx(self): widget = self.create() - self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m') - if tk_version < (9, 0): - self.checkParam(widget, 'padx', -2) - else: - self.checkParam(widget, 'padx', 0) + self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, -2, '12m') def test_configure_pady(self): widget = self.create() - self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m') - if tk_version < (9, 0): - self.checkParam(widget, 'pady', -2) - else: - self.checkParam(widget, 'pady', 0) + self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, -2, '12m') def test_configure_selectborderwidth(self): widget = self.create() - if tk_version < (9, 0): - values = (1.3, 2.6, -2, '10p') - else: - values = (1, 3, 0, 13) - self.checkPixelsParam(widget, 'selectborderwidth', *values) + self.checkPixelsParam(widget, 'selectborderwidth', 1.3, 2.6, -2, '10p') class StandardOptionsTests(PixelOptionsTests): @@ -569,34 +549,22 @@ class IntegerSizeTests: """ Tests widgets which only accept integral width and height.""" def test_configure_height(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'height', 100, -100, 0) - else: - self.checkIntegerParam(widget, 'height', 100, 0, 0) + self.checkIntegerParam(widget, 'height', 100, -100, 0) def test_configure_width(self): widget = self.create() - if tk_version < (9, 0): - self.checkIntegerParam(widget, 'width', 402, -402, 0) - else: - self.checkIntegerParam(widget, 'width', 402, 0, 0) + self.checkIntegerParam(widget, 'width', 402, -402, 0) class PixelSizeTests: """ Tests widgets which accept screen distances for width and height.""" def test_configure_height(self): widget = self.create() - value = -100 if tk_version < (9, 0) else 0 - self.checkPixelsParam( - widget, 'height', 100, 101.2, 102.6, value, 0, '3c' - ) + self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '3c') def test_configure_width(self): widget = self.create() - value = -402 if tk_version < (9, 0) else 0 - self.checkPixelsParam( - widget, 'width', 402, 403.4, 404.6, value, 0, '5i' - ) + self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i') def add_configure_tests(*source_classes): diff --git a/Lib/test/test_ttk/test_widgets.py b/Lib/test/test_ttk/test_widgets.py index e738fbff82e..8cce9aed9d5 100644 --- a/Lib/test/test_ttk/test_widgets.py +++ b/Lib/test/test_ttk/test_widgets.py @@ -183,7 +183,7 @@ def checkImageParam(self, widget, name): expected=('image1', 'active', 'image2')) self.checkParam(widget, name, 'image1 active image2', expected=('image1', 'active', 'image2')) - if tk_version < (9, 0): + if tk_version < (8, 7): errmsg = 'image "spam" doesn\'t exist' else: errmsg = 'image "spam" does not exist' @@ -1192,7 +1192,7 @@ def test_traversal(self): elif sys.platform == 'win32': focus_identify_as = 'focus' else: - focus_identify_as = 'focus' if tk_version < (9,0) else 'padding' + focus_identify_as = 'focus' if tk_version < (8, 7) else 'padding' self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) self.nb.focus_force() From f062014d3876f1f81c0e60bf861c3460429ac3b4 Mon Sep 17 00:00:00 2001 From: Hai Zhu Date: Thu, 12 Mar 2026 04:24:19 +0800 Subject: [PATCH 100/775] gh-144540: Add _MAKE_HEAP_SAFE uop to eliminate unnecessary refcount operations in RETURN_VALUE and YIELD_VALUE (GH-144414) --- Include/internal/pycore_opcode_metadata.h | 4 +- Include/internal/pycore_uop_ids.h | 1929 +++++++++++---------- Include/internal/pycore_uop_metadata.h | 21 + Lib/test/test_capi/test_opt.py | 44 + Modules/_testinternalcapi/test_cases.c.h | 122 +- Python/bytecodes.c | 26 +- Python/executor_cases.c.h | 63 +- Python/generated_cases.c.h | 122 +- Python/optimizer_bytecodes.c | 14 +- Python/optimizer_cases.c.h | 15 +- 10 files changed, 1288 insertions(+), 1072 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 126bc7d7102..09588e94282 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1495,7 +1495,7 @@ _PyOpcode_macro_expansion[256] = { [PUSH_NULL] = { .nuops = 1, .uops = { { _PUSH_NULL, OPARG_SIMPLE, 0 } } }, [RESUME_CHECK] = { .nuops = 1, .uops = { { _RESUME_CHECK, OPARG_SIMPLE, 0 } } }, [RETURN_GENERATOR] = { .nuops = 1, .uops = { { _RETURN_GENERATOR, OPARG_SIMPLE, 0 } } }, - [RETURN_VALUE] = { .nuops = 1, .uops = { { _RETURN_VALUE, OPARG_SIMPLE, 0 } } }, + [RETURN_VALUE] = { .nuops = 2, .uops = { { _MAKE_HEAP_SAFE, OPARG_SIMPLE, 0 }, { _RETURN_VALUE, OPARG_SIMPLE, 0 } } }, [SEND_GEN] = { .nuops = 4, .uops = { { _RECORD_NOS_GEN_FUNC, OPARG_SIMPLE, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _SEND_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, [SETUP_ANNOTATIONS] = { .nuops = 1, .uops = { { _SETUP_ANNOTATIONS, OPARG_SIMPLE, 0 } } }, [SET_ADD] = { .nuops = 1, .uops = { { _SET_ADD, OPARG_SIMPLE, 0 } } }, @@ -1532,7 +1532,7 @@ _PyOpcode_macro_expansion[256] = { [UNPACK_SEQUENCE_TUPLE] = { .nuops = 2, .uops = { { _GUARD_TOS_TUPLE, OPARG_SIMPLE, 0 }, { _UNPACK_SEQUENCE_TUPLE, OPARG_SIMPLE, 1 } } }, [UNPACK_SEQUENCE_TWO_TUPLE] = { .nuops = 2, .uops = { { _GUARD_TOS_TUPLE, OPARG_SIMPLE, 0 }, { _UNPACK_SEQUENCE_TWO_TUPLE, OPARG_SIMPLE, 1 } } }, [WITH_EXCEPT_START] = { .nuops = 1, .uops = { { _WITH_EXCEPT_START, OPARG_SIMPLE, 0 } } }, - [YIELD_VALUE] = { .nuops = 1, .uops = { { _YIELD_VALUE, OPARG_SIMPLE, 0 } } }, + [YIELD_VALUE] = { .nuops = 2, .uops = { { _MAKE_HEAP_SAFE, OPARG_SIMPLE, 0 }, { _YIELD_VALUE, OPARG_SIMPLE, 0 } } }, }; #endif // NEED_OPCODE_METADATA diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 38f290df2c7..216436604c6 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -289,994 +289,999 @@ extern "C" { #define _MAKE_CALLARGS_A_TUPLE 517 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 518 +#define _MAKE_HEAP_SAFE 518 +#define _MAKE_WARM 519 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 519 -#define _MAYBE_EXPAND_METHOD_KW 520 -#define _MONITOR_CALL 521 -#define _MONITOR_CALL_KW 522 -#define _MONITOR_JUMP_BACKWARD 523 -#define _MONITOR_RESUME 524 +#define _MAYBE_EXPAND_METHOD 520 +#define _MAYBE_EXPAND_METHOD_KW 521 +#define _MONITOR_CALL 522 +#define _MONITOR_CALL_KW 523 +#define _MONITOR_JUMP_BACKWARD 524 +#define _MONITOR_RESUME 525 #define _NOP NOP -#define _POP_CALL 525 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 526 -#define _POP_CALL_ONE 527 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 528 -#define _POP_CALL_TWO 529 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 530 +#define _POP_CALL 526 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 527 +#define _POP_CALL_ONE 528 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 529 +#define _POP_CALL_TWO 530 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 531 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 531 -#define _POP_JUMP_IF_TRUE 532 +#define _POP_JUMP_IF_FALSE 532 +#define _POP_JUMP_IF_TRUE 533 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 533 -#define _POP_TOP_INT 534 -#define _POP_TOP_LOAD_CONST_INLINE 535 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 536 -#define _POP_TOP_NOP 537 -#define _POP_TOP_UNICODE 538 -#define _POP_TWO 539 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 540 +#define _POP_TOP_FLOAT 534 +#define _POP_TOP_INT 535 +#define _POP_TOP_LOAD_CONST_INLINE 536 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 537 +#define _POP_TOP_NOP 538 +#define _POP_TOP_UNICODE 539 +#define _POP_TWO 540 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 541 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 541 +#define _PUSH_FRAME 542 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 542 -#define _PY_FRAME_EX 543 -#define _PY_FRAME_GENERAL 544 -#define _PY_FRAME_KW 545 -#define _QUICKEN_RESUME 546 -#define _RECORD_4OS 547 -#define _RECORD_BOUND_METHOD 548 -#define _RECORD_CALLABLE 549 -#define _RECORD_CODE 550 -#define _RECORD_NOS 551 -#define _RECORD_NOS_GEN_FUNC 552 -#define _RECORD_TOS 553 -#define _RECORD_TOS_TYPE 554 -#define _REPLACE_WITH_TRUE 555 +#define _PUSH_NULL_CONDITIONAL 543 +#define _PY_FRAME_EX 544 +#define _PY_FRAME_GENERAL 545 +#define _PY_FRAME_KW 546 +#define _QUICKEN_RESUME 547 +#define _RECORD_4OS 548 +#define _RECORD_BOUND_METHOD 549 +#define _RECORD_CALLABLE 550 +#define _RECORD_CODE 551 +#define _RECORD_NOS 552 +#define _RECORD_NOS_GEN_FUNC 553 +#define _RECORD_TOS 554 +#define _RECORD_TOS_TYPE 555 +#define _REPLACE_WITH_TRUE 556 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 556 -#define _SEND 557 -#define _SEND_GEN_FRAME 558 +#define _RETURN_VALUE 557 +#define _SAVE_RETURN_OFFSET 558 +#define _SEND 559 +#define _SEND_GEN_FRAME 560 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 559 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 560 -#define _SPILL_OR_RELOAD 561 -#define _START_EXECUTOR 562 -#define _STORE_ATTR 563 -#define _STORE_ATTR_INSTANCE_VALUE 564 -#define _STORE_ATTR_SLOT 565 -#define _STORE_ATTR_WITH_HINT 566 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 561 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 562 +#define _SPILL_OR_RELOAD 563 +#define _START_EXECUTOR 564 +#define _STORE_ATTR 565 +#define _STORE_ATTR_INSTANCE_VALUE 566 +#define _STORE_ATTR_SLOT 567 +#define _STORE_ATTR_WITH_HINT 568 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 567 -#define _STORE_SUBSCR 568 -#define _STORE_SUBSCR_DICT 569 -#define _STORE_SUBSCR_LIST_INT 570 -#define _SWAP 571 -#define _SWAP_2 572 -#define _SWAP_3 573 -#define _SWAP_FAST 574 -#define _SWAP_FAST_0 575 -#define _SWAP_FAST_1 576 -#define _SWAP_FAST_2 577 -#define _SWAP_FAST_3 578 -#define _SWAP_FAST_4 579 -#define _SWAP_FAST_5 580 -#define _SWAP_FAST_6 581 -#define _SWAP_FAST_7 582 -#define _TIER2_RESUME_CHECK 583 -#define _TO_BOOL 584 +#define _STORE_SLICE 569 +#define _STORE_SUBSCR 570 +#define _STORE_SUBSCR_DICT 571 +#define _STORE_SUBSCR_LIST_INT 572 +#define _SWAP 573 +#define _SWAP_2 574 +#define _SWAP_3 575 +#define _SWAP_FAST 576 +#define _SWAP_FAST_0 577 +#define _SWAP_FAST_1 578 +#define _SWAP_FAST_2 579 +#define _SWAP_FAST_3 580 +#define _SWAP_FAST_4 581 +#define _SWAP_FAST_5 582 +#define _SWAP_FAST_6 583 +#define _SWAP_FAST_7 584 +#define _TIER2_RESUME_CHECK 585 +#define _TO_BOOL 586 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 585 -#define _TO_BOOL_LIST 586 +#define _TO_BOOL_INT 587 +#define _TO_BOOL_LIST 588 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 587 +#define _TO_BOOL_STR 589 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 588 -#define _UNARY_NEGATIVE 589 +#define _UNARY_INVERT 590 +#define _UNARY_NEGATIVE 591 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 590 -#define _UNPACK_SEQUENCE_LIST 591 -#define _UNPACK_SEQUENCE_TUPLE 592 -#define _UNPACK_SEQUENCE_TWO_TUPLE 593 +#define _UNPACK_SEQUENCE 592 +#define _UNPACK_SEQUENCE_LIST 593 +#define _UNPACK_SEQUENCE_TUPLE 594 +#define _UNPACK_SEQUENCE_TWO_TUPLE 595 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 593 -#define _BINARY_OP_r23 594 -#define _BINARY_OP_ADD_FLOAT_r03 595 -#define _BINARY_OP_ADD_FLOAT_r13 596 -#define _BINARY_OP_ADD_FLOAT_r23 597 -#define _BINARY_OP_ADD_INT_r03 598 -#define _BINARY_OP_ADD_INT_r13 599 -#define _BINARY_OP_ADD_INT_r23 600 -#define _BINARY_OP_ADD_UNICODE_r03 601 -#define _BINARY_OP_ADD_UNICODE_r13 602 -#define _BINARY_OP_ADD_UNICODE_r23 603 -#define _BINARY_OP_EXTEND_r23 604 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 605 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 606 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 607 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 608 -#define _BINARY_OP_MULTIPLY_INT_r03 609 -#define _BINARY_OP_MULTIPLY_INT_r13 610 -#define _BINARY_OP_MULTIPLY_INT_r23 611 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 612 -#define _BINARY_OP_SUBSCR_DICT_r23 613 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 614 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 615 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 616 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 617 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 618 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 619 -#define _BINARY_OP_SUBSCR_STR_INT_r23 620 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 621 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 622 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 623 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 624 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 625 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 626 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 627 -#define _BINARY_OP_SUBTRACT_INT_r03 628 -#define _BINARY_OP_SUBTRACT_INT_r13 629 -#define _BINARY_OP_SUBTRACT_INT_r23 630 -#define _BINARY_SLICE_r31 631 -#define _BUILD_INTERPOLATION_r01 632 -#define _BUILD_LIST_r01 633 -#define _BUILD_MAP_r01 634 -#define _BUILD_SET_r01 635 -#define _BUILD_SLICE_r01 636 -#define _BUILD_STRING_r01 637 -#define _BUILD_TEMPLATE_r21 638 -#define _BUILD_TUPLE_r01 639 -#define _CALL_BUILTIN_CLASS_r01 640 -#define _CALL_BUILTIN_FAST_r01 641 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 642 -#define _CALL_BUILTIN_O_r03 643 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 644 -#define _CALL_INTRINSIC_1_r11 645 -#define _CALL_INTRINSIC_2_r21 646 -#define _CALL_ISINSTANCE_r31 647 -#define _CALL_KW_NON_PY_r11 648 -#define _CALL_LEN_r33 649 -#define _CALL_LIST_APPEND_r03 650 -#define _CALL_LIST_APPEND_r13 651 -#define _CALL_LIST_APPEND_r23 652 -#define _CALL_LIST_APPEND_r33 653 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 654 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 655 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 656 -#define _CALL_METHOD_DESCRIPTOR_O_r03 657 -#define _CALL_NON_PY_GENERAL_r01 658 -#define _CALL_STR_1_r32 659 -#define _CALL_TUPLE_1_r32 660 -#define _CALL_TYPE_1_r02 661 -#define _CALL_TYPE_1_r12 662 -#define _CALL_TYPE_1_r22 663 -#define _CALL_TYPE_1_r32 664 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 665 -#define _CHECK_ATTR_CLASS_r01 666 -#define _CHECK_ATTR_CLASS_r11 667 -#define _CHECK_ATTR_CLASS_r22 668 -#define _CHECK_ATTR_CLASS_r33 669 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 670 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 671 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 672 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 673 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 674 -#define _CHECK_EG_MATCH_r22 675 -#define _CHECK_EXC_MATCH_r22 676 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 677 -#define _CHECK_FUNCTION_VERSION_r00 678 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 679 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 680 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 681 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 682 -#define _CHECK_FUNCTION_VERSION_KW_r11 683 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 684 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 685 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 686 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 687 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 688 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 689 -#define _CHECK_IS_PY_CALLABLE_EX_r03 690 -#define _CHECK_IS_PY_CALLABLE_EX_r13 691 -#define _CHECK_IS_PY_CALLABLE_EX_r23 692 -#define _CHECK_IS_PY_CALLABLE_EX_r33 693 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 694 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 695 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 696 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 697 -#define _CHECK_METHOD_VERSION_r00 698 -#define _CHECK_METHOD_VERSION_KW_r11 699 -#define _CHECK_PEP_523_r00 700 -#define _CHECK_PEP_523_r11 701 -#define _CHECK_PEP_523_r22 702 -#define _CHECK_PEP_523_r33 703 -#define _CHECK_PERIODIC_r00 704 -#define _CHECK_PERIODIC_AT_END_r00 705 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 706 -#define _CHECK_RECURSION_REMAINING_r00 707 -#define _CHECK_RECURSION_REMAINING_r11 708 -#define _CHECK_RECURSION_REMAINING_r22 709 -#define _CHECK_RECURSION_REMAINING_r33 710 -#define _CHECK_STACK_SPACE_r00 711 -#define _CHECK_STACK_SPACE_OPERAND_r00 712 -#define _CHECK_STACK_SPACE_OPERAND_r11 713 -#define _CHECK_STACK_SPACE_OPERAND_r22 714 -#define _CHECK_STACK_SPACE_OPERAND_r33 715 -#define _CHECK_VALIDITY_r00 716 -#define _CHECK_VALIDITY_r11 717 -#define _CHECK_VALIDITY_r22 718 -#define _CHECK_VALIDITY_r33 719 -#define _COLD_DYNAMIC_EXIT_r00 720 -#define _COLD_EXIT_r00 721 -#define _COMPARE_OP_r21 722 -#define _COMPARE_OP_FLOAT_r03 723 -#define _COMPARE_OP_FLOAT_r13 724 -#define _COMPARE_OP_FLOAT_r23 725 -#define _COMPARE_OP_INT_r23 726 -#define _COMPARE_OP_STR_r23 727 -#define _CONTAINS_OP_r23 728 -#define _CONTAINS_OP_DICT_r23 729 -#define _CONTAINS_OP_SET_r23 730 -#define _CONVERT_VALUE_r11 731 -#define _COPY_r01 732 -#define _COPY_1_r02 733 -#define _COPY_1_r12 734 -#define _COPY_1_r23 735 -#define _COPY_2_r03 736 -#define _COPY_2_r13 737 -#define _COPY_2_r23 738 -#define _COPY_3_r03 739 -#define _COPY_3_r13 740 -#define _COPY_3_r23 741 -#define _COPY_3_r33 742 -#define _COPY_FREE_VARS_r00 743 -#define _COPY_FREE_VARS_r11 744 -#define _COPY_FREE_VARS_r22 745 -#define _COPY_FREE_VARS_r33 746 -#define _CREATE_INIT_FRAME_r01 747 -#define _DELETE_ATTR_r10 748 -#define _DELETE_DEREF_r00 749 -#define _DELETE_FAST_r00 750 -#define _DELETE_GLOBAL_r00 751 -#define _DELETE_NAME_r00 752 -#define _DELETE_SUBSCR_r20 753 -#define _DEOPT_r00 754 -#define _DEOPT_r10 755 -#define _DEOPT_r20 756 -#define _DEOPT_r30 757 -#define _DICT_MERGE_r10 758 -#define _DICT_UPDATE_r10 759 -#define _DO_CALL_r01 760 -#define _DO_CALL_FUNCTION_EX_r31 761 -#define _DO_CALL_KW_r11 762 -#define _DYNAMIC_EXIT_r00 763 -#define _DYNAMIC_EXIT_r10 764 -#define _DYNAMIC_EXIT_r20 765 -#define _DYNAMIC_EXIT_r30 766 -#define _END_FOR_r10 767 -#define _END_SEND_r21 768 -#define _ERROR_POP_N_r00 769 -#define _EXIT_INIT_CHECK_r10 770 -#define _EXIT_TRACE_r00 771 -#define _EXIT_TRACE_r10 772 -#define _EXIT_TRACE_r20 773 -#define _EXIT_TRACE_r30 774 -#define _EXPAND_METHOD_r00 775 -#define _EXPAND_METHOD_KW_r11 776 -#define _FATAL_ERROR_r00 777 -#define _FATAL_ERROR_r11 778 -#define _FATAL_ERROR_r22 779 -#define _FATAL_ERROR_r33 780 -#define _FORMAT_SIMPLE_r11 781 -#define _FORMAT_WITH_SPEC_r21 782 -#define _FOR_ITER_r23 783 -#define _FOR_ITER_GEN_FRAME_r03 784 -#define _FOR_ITER_GEN_FRAME_r13 785 -#define _FOR_ITER_GEN_FRAME_r23 786 -#define _FOR_ITER_TIER_TWO_r23 787 -#define _GET_AITER_r11 788 -#define _GET_ANEXT_r12 789 -#define _GET_AWAITABLE_r11 790 -#define _GET_ITER_r12 791 -#define _GET_LEN_r12 792 -#define _GET_YIELD_FROM_ITER_r11 793 -#define _GUARD_BINARY_OP_EXTEND_r22 794 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 795 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 796 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 797 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 798 -#define _GUARD_BIT_IS_SET_POP_r00 799 -#define _GUARD_BIT_IS_SET_POP_r10 800 -#define _GUARD_BIT_IS_SET_POP_r21 801 -#define _GUARD_BIT_IS_SET_POP_r32 802 -#define _GUARD_BIT_IS_SET_POP_4_r00 803 -#define _GUARD_BIT_IS_SET_POP_4_r10 804 -#define _GUARD_BIT_IS_SET_POP_4_r21 805 -#define _GUARD_BIT_IS_SET_POP_4_r32 806 -#define _GUARD_BIT_IS_SET_POP_5_r00 807 -#define _GUARD_BIT_IS_SET_POP_5_r10 808 -#define _GUARD_BIT_IS_SET_POP_5_r21 809 -#define _GUARD_BIT_IS_SET_POP_5_r32 810 -#define _GUARD_BIT_IS_SET_POP_6_r00 811 -#define _GUARD_BIT_IS_SET_POP_6_r10 812 -#define _GUARD_BIT_IS_SET_POP_6_r21 813 -#define _GUARD_BIT_IS_SET_POP_6_r32 814 -#define _GUARD_BIT_IS_SET_POP_7_r00 815 -#define _GUARD_BIT_IS_SET_POP_7_r10 816 -#define _GUARD_BIT_IS_SET_POP_7_r21 817 -#define _GUARD_BIT_IS_SET_POP_7_r32 818 -#define _GUARD_BIT_IS_UNSET_POP_r00 819 -#define _GUARD_BIT_IS_UNSET_POP_r10 820 -#define _GUARD_BIT_IS_UNSET_POP_r21 821 -#define _GUARD_BIT_IS_UNSET_POP_r32 822 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 823 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 824 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 825 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 826 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 827 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 828 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 829 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 830 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 831 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 832 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 833 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 834 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 835 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 836 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 837 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 838 -#define _GUARD_CALLABLE_ISINSTANCE_r03 839 -#define _GUARD_CALLABLE_ISINSTANCE_r13 840 -#define _GUARD_CALLABLE_ISINSTANCE_r23 841 -#define _GUARD_CALLABLE_ISINSTANCE_r33 842 -#define _GUARD_CALLABLE_LEN_r03 843 -#define _GUARD_CALLABLE_LEN_r13 844 -#define _GUARD_CALLABLE_LEN_r23 845 -#define _GUARD_CALLABLE_LEN_r33 846 -#define _GUARD_CALLABLE_LIST_APPEND_r03 847 -#define _GUARD_CALLABLE_LIST_APPEND_r13 848 -#define _GUARD_CALLABLE_LIST_APPEND_r23 849 -#define _GUARD_CALLABLE_LIST_APPEND_r33 850 -#define _GUARD_CALLABLE_STR_1_r03 851 -#define _GUARD_CALLABLE_STR_1_r13 852 -#define _GUARD_CALLABLE_STR_1_r23 853 -#define _GUARD_CALLABLE_STR_1_r33 854 -#define _GUARD_CALLABLE_TUPLE_1_r03 855 -#define _GUARD_CALLABLE_TUPLE_1_r13 856 -#define _GUARD_CALLABLE_TUPLE_1_r23 857 -#define _GUARD_CALLABLE_TUPLE_1_r33 858 -#define _GUARD_CALLABLE_TYPE_1_r03 859 -#define _GUARD_CALLABLE_TYPE_1_r13 860 -#define _GUARD_CALLABLE_TYPE_1_r23 861 -#define _GUARD_CALLABLE_TYPE_1_r33 862 -#define _GUARD_CODE_VERSION_r00 863 -#define _GUARD_CODE_VERSION_r11 864 -#define _GUARD_CODE_VERSION_r22 865 -#define _GUARD_CODE_VERSION_r33 866 -#define _GUARD_DORV_NO_DICT_r01 867 -#define _GUARD_DORV_NO_DICT_r11 868 -#define _GUARD_DORV_NO_DICT_r22 869 -#define _GUARD_DORV_NO_DICT_r33 870 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 871 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 872 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 873 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 874 -#define _GUARD_GLOBALS_VERSION_r00 875 -#define _GUARD_GLOBALS_VERSION_r11 876 -#define _GUARD_GLOBALS_VERSION_r22 877 -#define _GUARD_GLOBALS_VERSION_r33 878 -#define _GUARD_IP_RETURN_GENERATOR_r00 879 -#define _GUARD_IP_RETURN_GENERATOR_r11 880 -#define _GUARD_IP_RETURN_GENERATOR_r22 881 -#define _GUARD_IP_RETURN_GENERATOR_r33 882 -#define _GUARD_IP_RETURN_VALUE_r00 883 -#define _GUARD_IP_RETURN_VALUE_r11 884 -#define _GUARD_IP_RETURN_VALUE_r22 885 -#define _GUARD_IP_RETURN_VALUE_r33 886 -#define _GUARD_IP_YIELD_VALUE_r00 887 -#define _GUARD_IP_YIELD_VALUE_r11 888 -#define _GUARD_IP_YIELD_VALUE_r22 889 -#define _GUARD_IP_YIELD_VALUE_r33 890 -#define _GUARD_IP__PUSH_FRAME_r00 891 -#define _GUARD_IP__PUSH_FRAME_r11 892 -#define _GUARD_IP__PUSH_FRAME_r22 893 -#define _GUARD_IP__PUSH_FRAME_r33 894 -#define _GUARD_IS_FALSE_POP_r00 895 -#define _GUARD_IS_FALSE_POP_r10 896 -#define _GUARD_IS_FALSE_POP_r21 897 -#define _GUARD_IS_FALSE_POP_r32 898 -#define _GUARD_IS_NONE_POP_r00 899 -#define _GUARD_IS_NONE_POP_r10 900 -#define _GUARD_IS_NONE_POP_r21 901 -#define _GUARD_IS_NONE_POP_r32 902 -#define _GUARD_IS_NOT_NONE_POP_r10 903 -#define _GUARD_IS_TRUE_POP_r00 904 -#define _GUARD_IS_TRUE_POP_r10 905 -#define _GUARD_IS_TRUE_POP_r21 906 -#define _GUARD_IS_TRUE_POP_r32 907 -#define _GUARD_KEYS_VERSION_r01 908 -#define _GUARD_KEYS_VERSION_r11 909 -#define _GUARD_KEYS_VERSION_r22 910 -#define _GUARD_KEYS_VERSION_r33 911 -#define _GUARD_NOS_ANY_DICT_r02 912 -#define _GUARD_NOS_ANY_DICT_r12 913 -#define _GUARD_NOS_ANY_DICT_r22 914 -#define _GUARD_NOS_ANY_DICT_r33 915 -#define _GUARD_NOS_COMPACT_ASCII_r02 916 -#define _GUARD_NOS_COMPACT_ASCII_r12 917 -#define _GUARD_NOS_COMPACT_ASCII_r22 918 -#define _GUARD_NOS_COMPACT_ASCII_r33 919 -#define _GUARD_NOS_DICT_r02 920 -#define _GUARD_NOS_DICT_r12 921 -#define _GUARD_NOS_DICT_r22 922 -#define _GUARD_NOS_DICT_r33 923 -#define _GUARD_NOS_FLOAT_r02 924 -#define _GUARD_NOS_FLOAT_r12 925 -#define _GUARD_NOS_FLOAT_r22 926 -#define _GUARD_NOS_FLOAT_r33 927 -#define _GUARD_NOS_INT_r02 928 -#define _GUARD_NOS_INT_r12 929 -#define _GUARD_NOS_INT_r22 930 -#define _GUARD_NOS_INT_r33 931 -#define _GUARD_NOS_LIST_r02 932 -#define _GUARD_NOS_LIST_r12 933 -#define _GUARD_NOS_LIST_r22 934 -#define _GUARD_NOS_LIST_r33 935 -#define _GUARD_NOS_NOT_NULL_r02 936 -#define _GUARD_NOS_NOT_NULL_r12 937 -#define _GUARD_NOS_NOT_NULL_r22 938 -#define _GUARD_NOS_NOT_NULL_r33 939 -#define _GUARD_NOS_NULL_r02 940 -#define _GUARD_NOS_NULL_r12 941 -#define _GUARD_NOS_NULL_r22 942 -#define _GUARD_NOS_NULL_r33 943 -#define _GUARD_NOS_OVERFLOWED_r02 944 -#define _GUARD_NOS_OVERFLOWED_r12 945 -#define _GUARD_NOS_OVERFLOWED_r22 946 -#define _GUARD_NOS_OVERFLOWED_r33 947 -#define _GUARD_NOS_TUPLE_r02 948 -#define _GUARD_NOS_TUPLE_r12 949 -#define _GUARD_NOS_TUPLE_r22 950 -#define _GUARD_NOS_TUPLE_r33 951 -#define _GUARD_NOS_UNICODE_r02 952 -#define _GUARD_NOS_UNICODE_r12 953 -#define _GUARD_NOS_UNICODE_r22 954 -#define _GUARD_NOS_UNICODE_r33 955 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 956 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 957 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 958 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 959 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 960 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 961 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 962 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 963 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 964 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 965 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 966 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 967 -#define _GUARD_THIRD_NULL_r03 968 -#define _GUARD_THIRD_NULL_r13 969 -#define _GUARD_THIRD_NULL_r23 970 -#define _GUARD_THIRD_NULL_r33 971 -#define _GUARD_TOS_ANY_DICT_r01 972 -#define _GUARD_TOS_ANY_DICT_r11 973 -#define _GUARD_TOS_ANY_DICT_r22 974 -#define _GUARD_TOS_ANY_DICT_r33 975 -#define _GUARD_TOS_ANY_SET_r01 976 -#define _GUARD_TOS_ANY_SET_r11 977 -#define _GUARD_TOS_ANY_SET_r22 978 -#define _GUARD_TOS_ANY_SET_r33 979 -#define _GUARD_TOS_DICT_r01 980 -#define _GUARD_TOS_DICT_r11 981 -#define _GUARD_TOS_DICT_r22 982 -#define _GUARD_TOS_DICT_r33 983 -#define _GUARD_TOS_FLOAT_r01 984 -#define _GUARD_TOS_FLOAT_r11 985 -#define _GUARD_TOS_FLOAT_r22 986 -#define _GUARD_TOS_FLOAT_r33 987 -#define _GUARD_TOS_FROZENDICT_r01 988 -#define _GUARD_TOS_FROZENDICT_r11 989 -#define _GUARD_TOS_FROZENDICT_r22 990 -#define _GUARD_TOS_FROZENDICT_r33 991 -#define _GUARD_TOS_FROZENSET_r01 992 -#define _GUARD_TOS_FROZENSET_r11 993 -#define _GUARD_TOS_FROZENSET_r22 994 -#define _GUARD_TOS_FROZENSET_r33 995 -#define _GUARD_TOS_INT_r01 996 -#define _GUARD_TOS_INT_r11 997 -#define _GUARD_TOS_INT_r22 998 -#define _GUARD_TOS_INT_r33 999 -#define _GUARD_TOS_LIST_r01 1000 -#define _GUARD_TOS_LIST_r11 1001 -#define _GUARD_TOS_LIST_r22 1002 -#define _GUARD_TOS_LIST_r33 1003 -#define _GUARD_TOS_OVERFLOWED_r01 1004 -#define _GUARD_TOS_OVERFLOWED_r11 1005 -#define _GUARD_TOS_OVERFLOWED_r22 1006 -#define _GUARD_TOS_OVERFLOWED_r33 1007 -#define _GUARD_TOS_SET_r01 1008 -#define _GUARD_TOS_SET_r11 1009 -#define _GUARD_TOS_SET_r22 1010 -#define _GUARD_TOS_SET_r33 1011 -#define _GUARD_TOS_SLICE_r01 1012 -#define _GUARD_TOS_SLICE_r11 1013 -#define _GUARD_TOS_SLICE_r22 1014 -#define _GUARD_TOS_SLICE_r33 1015 -#define _GUARD_TOS_TUPLE_r01 1016 -#define _GUARD_TOS_TUPLE_r11 1017 -#define _GUARD_TOS_TUPLE_r22 1018 -#define _GUARD_TOS_TUPLE_r33 1019 -#define _GUARD_TOS_UNICODE_r01 1020 -#define _GUARD_TOS_UNICODE_r11 1021 -#define _GUARD_TOS_UNICODE_r22 1022 -#define _GUARD_TOS_UNICODE_r33 1023 -#define _GUARD_TYPE_VERSION_r01 1024 -#define _GUARD_TYPE_VERSION_r11 1025 -#define _GUARD_TYPE_VERSION_r22 1026 -#define _GUARD_TYPE_VERSION_r33 1027 -#define _GUARD_TYPE_VERSION_AND_LOCK_r01 1028 -#define _GUARD_TYPE_VERSION_AND_LOCK_r11 1029 -#define _GUARD_TYPE_VERSION_AND_LOCK_r22 1030 -#define _GUARD_TYPE_VERSION_AND_LOCK_r33 1031 -#define _HANDLE_PENDING_AND_DEOPT_r00 1032 -#define _HANDLE_PENDING_AND_DEOPT_r10 1033 -#define _HANDLE_PENDING_AND_DEOPT_r20 1034 -#define _HANDLE_PENDING_AND_DEOPT_r30 1035 -#define _IMPORT_FROM_r12 1036 -#define _IMPORT_NAME_r21 1037 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1038 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1039 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1040 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1041 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1042 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1043 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1044 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1045 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1046 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1047 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1048 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1049 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1050 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1051 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1052 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1053 -#define _INSERT_NULL_r10 1054 -#define _INSTRUMENTED_FOR_ITER_r23 1055 -#define _INSTRUMENTED_INSTRUCTION_r00 1056 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1057 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1058 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1059 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1060 -#define _INSTRUMENTED_LINE_r00 1061 -#define _INSTRUMENTED_NOT_TAKEN_r00 1062 -#define _INSTRUMENTED_NOT_TAKEN_r11 1063 -#define _INSTRUMENTED_NOT_TAKEN_r22 1064 -#define _INSTRUMENTED_NOT_TAKEN_r33 1065 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1066 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1067 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1068 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1069 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1070 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1071 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1072 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1073 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1074 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1075 -#define _IS_NONE_r11 1076 -#define _IS_OP_r03 1077 -#define _IS_OP_r13 1078 -#define _IS_OP_r23 1079 -#define _ITER_CHECK_LIST_r02 1080 -#define _ITER_CHECK_LIST_r12 1081 -#define _ITER_CHECK_LIST_r22 1082 -#define _ITER_CHECK_LIST_r33 1083 -#define _ITER_CHECK_RANGE_r02 1084 -#define _ITER_CHECK_RANGE_r12 1085 -#define _ITER_CHECK_RANGE_r22 1086 -#define _ITER_CHECK_RANGE_r33 1087 -#define _ITER_CHECK_TUPLE_r02 1088 -#define _ITER_CHECK_TUPLE_r12 1089 -#define _ITER_CHECK_TUPLE_r22 1090 -#define _ITER_CHECK_TUPLE_r33 1091 -#define _ITER_JUMP_LIST_r02 1092 -#define _ITER_JUMP_LIST_r12 1093 -#define _ITER_JUMP_LIST_r22 1094 -#define _ITER_JUMP_LIST_r33 1095 -#define _ITER_JUMP_RANGE_r02 1096 -#define _ITER_JUMP_RANGE_r12 1097 -#define _ITER_JUMP_RANGE_r22 1098 -#define _ITER_JUMP_RANGE_r33 1099 -#define _ITER_JUMP_TUPLE_r02 1100 -#define _ITER_JUMP_TUPLE_r12 1101 -#define _ITER_JUMP_TUPLE_r22 1102 -#define _ITER_JUMP_TUPLE_r33 1103 -#define _ITER_NEXT_LIST_r23 1104 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1105 -#define _ITER_NEXT_RANGE_r03 1106 -#define _ITER_NEXT_RANGE_r13 1107 -#define _ITER_NEXT_RANGE_r23 1108 -#define _ITER_NEXT_TUPLE_r03 1109 -#define _ITER_NEXT_TUPLE_r13 1110 -#define _ITER_NEXT_TUPLE_r23 1111 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1112 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1113 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1114 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1115 -#define _JUMP_TO_TOP_r00 1116 -#define _LIST_APPEND_r10 1117 -#define _LIST_EXTEND_r10 1118 -#define _LOAD_ATTR_r10 1119 -#define _LOAD_ATTR_CLASS_r11 1120 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1121 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1122 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1123 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1124 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1125 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1126 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1127 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1128 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1129 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1130 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1131 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1132 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1133 -#define _LOAD_ATTR_MODULE_r12 1134 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1135 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1136 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1137 -#define _LOAD_ATTR_SLOT_r02 1138 -#define _LOAD_ATTR_SLOT_r12 1139 -#define _LOAD_ATTR_SLOT_r23 1140 -#define _LOAD_ATTR_WITH_HINT_r12 1141 -#define _LOAD_BUILD_CLASS_r01 1142 -#define _LOAD_BYTECODE_r00 1143 -#define _LOAD_COMMON_CONSTANT_r01 1144 -#define _LOAD_COMMON_CONSTANT_r12 1145 -#define _LOAD_COMMON_CONSTANT_r23 1146 -#define _LOAD_CONST_r01 1147 -#define _LOAD_CONST_r12 1148 -#define _LOAD_CONST_r23 1149 -#define _LOAD_CONST_INLINE_r01 1150 -#define _LOAD_CONST_INLINE_r12 1151 -#define _LOAD_CONST_INLINE_r23 1152 -#define _LOAD_CONST_INLINE_BORROW_r01 1153 -#define _LOAD_CONST_INLINE_BORROW_r12 1154 -#define _LOAD_CONST_INLINE_BORROW_r23 1155 -#define _LOAD_CONST_UNDER_INLINE_r02 1156 -#define _LOAD_CONST_UNDER_INLINE_r12 1157 -#define _LOAD_CONST_UNDER_INLINE_r23 1158 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1159 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1160 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1161 -#define _LOAD_DEREF_r01 1162 -#define _LOAD_FAST_r01 1163 -#define _LOAD_FAST_r12 1164 -#define _LOAD_FAST_r23 1165 -#define _LOAD_FAST_0_r01 1166 -#define _LOAD_FAST_0_r12 1167 -#define _LOAD_FAST_0_r23 1168 -#define _LOAD_FAST_1_r01 1169 -#define _LOAD_FAST_1_r12 1170 -#define _LOAD_FAST_1_r23 1171 -#define _LOAD_FAST_2_r01 1172 -#define _LOAD_FAST_2_r12 1173 -#define _LOAD_FAST_2_r23 1174 -#define _LOAD_FAST_3_r01 1175 -#define _LOAD_FAST_3_r12 1176 -#define _LOAD_FAST_3_r23 1177 -#define _LOAD_FAST_4_r01 1178 -#define _LOAD_FAST_4_r12 1179 -#define _LOAD_FAST_4_r23 1180 -#define _LOAD_FAST_5_r01 1181 -#define _LOAD_FAST_5_r12 1182 -#define _LOAD_FAST_5_r23 1183 -#define _LOAD_FAST_6_r01 1184 -#define _LOAD_FAST_6_r12 1185 -#define _LOAD_FAST_6_r23 1186 -#define _LOAD_FAST_7_r01 1187 -#define _LOAD_FAST_7_r12 1188 -#define _LOAD_FAST_7_r23 1189 -#define _LOAD_FAST_AND_CLEAR_r01 1190 -#define _LOAD_FAST_AND_CLEAR_r12 1191 -#define _LOAD_FAST_AND_CLEAR_r23 1192 -#define _LOAD_FAST_BORROW_r01 1193 -#define _LOAD_FAST_BORROW_r12 1194 -#define _LOAD_FAST_BORROW_r23 1195 -#define _LOAD_FAST_BORROW_0_r01 1196 -#define _LOAD_FAST_BORROW_0_r12 1197 -#define _LOAD_FAST_BORROW_0_r23 1198 -#define _LOAD_FAST_BORROW_1_r01 1199 -#define _LOAD_FAST_BORROW_1_r12 1200 -#define _LOAD_FAST_BORROW_1_r23 1201 -#define _LOAD_FAST_BORROW_2_r01 1202 -#define _LOAD_FAST_BORROW_2_r12 1203 -#define _LOAD_FAST_BORROW_2_r23 1204 -#define _LOAD_FAST_BORROW_3_r01 1205 -#define _LOAD_FAST_BORROW_3_r12 1206 -#define _LOAD_FAST_BORROW_3_r23 1207 -#define _LOAD_FAST_BORROW_4_r01 1208 -#define _LOAD_FAST_BORROW_4_r12 1209 -#define _LOAD_FAST_BORROW_4_r23 1210 -#define _LOAD_FAST_BORROW_5_r01 1211 -#define _LOAD_FAST_BORROW_5_r12 1212 -#define _LOAD_FAST_BORROW_5_r23 1213 -#define _LOAD_FAST_BORROW_6_r01 1214 -#define _LOAD_FAST_BORROW_6_r12 1215 -#define _LOAD_FAST_BORROW_6_r23 1216 -#define _LOAD_FAST_BORROW_7_r01 1217 -#define _LOAD_FAST_BORROW_7_r12 1218 -#define _LOAD_FAST_BORROW_7_r23 1219 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1220 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1221 -#define _LOAD_FAST_CHECK_r01 1222 -#define _LOAD_FAST_CHECK_r12 1223 -#define _LOAD_FAST_CHECK_r23 1224 -#define _LOAD_FAST_LOAD_FAST_r02 1225 -#define _LOAD_FAST_LOAD_FAST_r13 1226 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1227 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1228 -#define _LOAD_GLOBAL_r00 1229 -#define _LOAD_GLOBAL_BUILTINS_r01 1230 -#define _LOAD_GLOBAL_MODULE_r01 1231 -#define _LOAD_LOCALS_r01 1232 -#define _LOAD_LOCALS_r12 1233 -#define _LOAD_LOCALS_r23 1234 -#define _LOAD_NAME_r01 1235 -#define _LOAD_SMALL_INT_r01 1236 -#define _LOAD_SMALL_INT_r12 1237 -#define _LOAD_SMALL_INT_r23 1238 -#define _LOAD_SMALL_INT_0_r01 1239 -#define _LOAD_SMALL_INT_0_r12 1240 -#define _LOAD_SMALL_INT_0_r23 1241 -#define _LOAD_SMALL_INT_1_r01 1242 -#define _LOAD_SMALL_INT_1_r12 1243 -#define _LOAD_SMALL_INT_1_r23 1244 -#define _LOAD_SMALL_INT_2_r01 1245 -#define _LOAD_SMALL_INT_2_r12 1246 -#define _LOAD_SMALL_INT_2_r23 1247 -#define _LOAD_SMALL_INT_3_r01 1248 -#define _LOAD_SMALL_INT_3_r12 1249 -#define _LOAD_SMALL_INT_3_r23 1250 -#define _LOAD_SPECIAL_r00 1251 -#define _LOAD_SUPER_ATTR_ATTR_r31 1252 -#define _LOAD_SUPER_ATTR_METHOD_r32 1253 -#define _MAKE_CALLARGS_A_TUPLE_r33 1254 -#define _MAKE_CELL_r00 1255 -#define _MAKE_FUNCTION_r11 1256 -#define _MAKE_WARM_r00 1257 -#define _MAKE_WARM_r11 1258 -#define _MAKE_WARM_r22 1259 -#define _MAKE_WARM_r33 1260 -#define _MAP_ADD_r20 1261 -#define _MATCH_CLASS_r31 1262 -#define _MATCH_KEYS_r23 1263 -#define _MATCH_MAPPING_r02 1264 -#define _MATCH_MAPPING_r12 1265 -#define _MATCH_MAPPING_r23 1266 -#define _MATCH_SEQUENCE_r02 1267 -#define _MATCH_SEQUENCE_r12 1268 -#define _MATCH_SEQUENCE_r23 1269 -#define _MAYBE_EXPAND_METHOD_r00 1270 -#define _MAYBE_EXPAND_METHOD_KW_r11 1271 -#define _MONITOR_CALL_r00 1272 -#define _MONITOR_CALL_KW_r11 1273 -#define _MONITOR_JUMP_BACKWARD_r00 1274 -#define _MONITOR_JUMP_BACKWARD_r11 1275 -#define _MONITOR_JUMP_BACKWARD_r22 1276 -#define _MONITOR_JUMP_BACKWARD_r33 1277 -#define _MONITOR_RESUME_r00 1278 -#define _NOP_r00 1279 -#define _NOP_r11 1280 -#define _NOP_r22 1281 -#define _NOP_r33 1282 -#define _POP_CALL_r20 1283 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1284 -#define _POP_CALL_ONE_r30 1285 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1286 -#define _POP_CALL_TWO_r30 1287 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1288 -#define _POP_EXCEPT_r10 1289 -#define _POP_ITER_r20 1290 -#define _POP_JUMP_IF_FALSE_r00 1291 -#define _POP_JUMP_IF_FALSE_r10 1292 -#define _POP_JUMP_IF_FALSE_r21 1293 -#define _POP_JUMP_IF_FALSE_r32 1294 -#define _POP_JUMP_IF_TRUE_r00 1295 -#define _POP_JUMP_IF_TRUE_r10 1296 -#define _POP_JUMP_IF_TRUE_r21 1297 -#define _POP_JUMP_IF_TRUE_r32 1298 -#define _POP_TOP_r10 1299 -#define _POP_TOP_FLOAT_r00 1300 -#define _POP_TOP_FLOAT_r10 1301 -#define _POP_TOP_FLOAT_r21 1302 -#define _POP_TOP_FLOAT_r32 1303 -#define _POP_TOP_INT_r00 1304 -#define _POP_TOP_INT_r10 1305 -#define _POP_TOP_INT_r21 1306 -#define _POP_TOP_INT_r32 1307 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1308 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1309 -#define _POP_TOP_NOP_r00 1310 -#define _POP_TOP_NOP_r10 1311 -#define _POP_TOP_NOP_r21 1312 -#define _POP_TOP_NOP_r32 1313 -#define _POP_TOP_UNICODE_r00 1314 -#define _POP_TOP_UNICODE_r10 1315 -#define _POP_TOP_UNICODE_r21 1316 -#define _POP_TOP_UNICODE_r32 1317 -#define _POP_TWO_r20 1318 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1319 -#define _PUSH_EXC_INFO_r02 1320 -#define _PUSH_EXC_INFO_r12 1321 -#define _PUSH_EXC_INFO_r23 1322 -#define _PUSH_FRAME_r10 1323 -#define _PUSH_NULL_r01 1324 -#define _PUSH_NULL_r12 1325 -#define _PUSH_NULL_r23 1326 -#define _PUSH_NULL_CONDITIONAL_r00 1327 -#define _PY_FRAME_EX_r31 1328 -#define _PY_FRAME_GENERAL_r01 1329 -#define _PY_FRAME_KW_r11 1330 -#define _QUICKEN_RESUME_r00 1331 -#define _QUICKEN_RESUME_r11 1332 -#define _QUICKEN_RESUME_r22 1333 -#define _QUICKEN_RESUME_r33 1334 -#define _REPLACE_WITH_TRUE_r02 1335 -#define _REPLACE_WITH_TRUE_r12 1336 -#define _REPLACE_WITH_TRUE_r23 1337 -#define _RESUME_CHECK_r00 1338 -#define _RESUME_CHECK_r11 1339 -#define _RESUME_CHECK_r22 1340 -#define _RESUME_CHECK_r33 1341 -#define _RETURN_GENERATOR_r01 1342 -#define _RETURN_VALUE_r11 1343 -#define _SAVE_RETURN_OFFSET_r00 1344 -#define _SAVE_RETURN_OFFSET_r11 1345 -#define _SAVE_RETURN_OFFSET_r22 1346 -#define _SAVE_RETURN_OFFSET_r33 1347 -#define _SEND_r22 1348 -#define _SEND_GEN_FRAME_r22 1349 -#define _SETUP_ANNOTATIONS_r00 1350 -#define _SET_ADD_r10 1351 -#define _SET_FUNCTION_ATTRIBUTE_r01 1352 -#define _SET_FUNCTION_ATTRIBUTE_r11 1353 -#define _SET_FUNCTION_ATTRIBUTE_r21 1354 -#define _SET_FUNCTION_ATTRIBUTE_r32 1355 -#define _SET_IP_r00 1356 -#define _SET_IP_r11 1357 -#define _SET_IP_r22 1358 -#define _SET_IP_r33 1359 -#define _SET_UPDATE_r10 1360 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1361 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1362 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1363 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1364 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1365 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1366 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1367 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1368 -#define _SPILL_OR_RELOAD_r01 1369 -#define _SPILL_OR_RELOAD_r02 1370 -#define _SPILL_OR_RELOAD_r03 1371 -#define _SPILL_OR_RELOAD_r10 1372 -#define _SPILL_OR_RELOAD_r12 1373 -#define _SPILL_OR_RELOAD_r13 1374 -#define _SPILL_OR_RELOAD_r20 1375 -#define _SPILL_OR_RELOAD_r21 1376 -#define _SPILL_OR_RELOAD_r23 1377 -#define _SPILL_OR_RELOAD_r30 1378 -#define _SPILL_OR_RELOAD_r31 1379 -#define _SPILL_OR_RELOAD_r32 1380 -#define _START_EXECUTOR_r00 1381 -#define _STORE_ATTR_r20 1382 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1383 -#define _STORE_ATTR_SLOT_r21 1384 -#define _STORE_ATTR_WITH_HINT_r21 1385 -#define _STORE_DEREF_r10 1386 -#define _STORE_FAST_LOAD_FAST_r11 1387 -#define _STORE_FAST_STORE_FAST_r20 1388 -#define _STORE_GLOBAL_r10 1389 -#define _STORE_NAME_r10 1390 -#define _STORE_SLICE_r30 1391 -#define _STORE_SUBSCR_r30 1392 -#define _STORE_SUBSCR_DICT_r31 1393 -#define _STORE_SUBSCR_LIST_INT_r32 1394 -#define _SWAP_r11 1395 -#define _SWAP_2_r02 1396 -#define _SWAP_2_r12 1397 -#define _SWAP_2_r22 1398 -#define _SWAP_2_r33 1399 -#define _SWAP_3_r03 1400 -#define _SWAP_3_r13 1401 -#define _SWAP_3_r23 1402 -#define _SWAP_3_r33 1403 -#define _SWAP_FAST_r01 1404 -#define _SWAP_FAST_r11 1405 -#define _SWAP_FAST_r22 1406 -#define _SWAP_FAST_r33 1407 -#define _SWAP_FAST_0_r01 1408 -#define _SWAP_FAST_0_r11 1409 -#define _SWAP_FAST_0_r22 1410 -#define _SWAP_FAST_0_r33 1411 -#define _SWAP_FAST_1_r01 1412 -#define _SWAP_FAST_1_r11 1413 -#define _SWAP_FAST_1_r22 1414 -#define _SWAP_FAST_1_r33 1415 -#define _SWAP_FAST_2_r01 1416 -#define _SWAP_FAST_2_r11 1417 -#define _SWAP_FAST_2_r22 1418 -#define _SWAP_FAST_2_r33 1419 -#define _SWAP_FAST_3_r01 1420 -#define _SWAP_FAST_3_r11 1421 -#define _SWAP_FAST_3_r22 1422 -#define _SWAP_FAST_3_r33 1423 -#define _SWAP_FAST_4_r01 1424 -#define _SWAP_FAST_4_r11 1425 -#define _SWAP_FAST_4_r22 1426 -#define _SWAP_FAST_4_r33 1427 -#define _SWAP_FAST_5_r01 1428 -#define _SWAP_FAST_5_r11 1429 -#define _SWAP_FAST_5_r22 1430 -#define _SWAP_FAST_5_r33 1431 -#define _SWAP_FAST_6_r01 1432 -#define _SWAP_FAST_6_r11 1433 -#define _SWAP_FAST_6_r22 1434 -#define _SWAP_FAST_6_r33 1435 -#define _SWAP_FAST_7_r01 1436 -#define _SWAP_FAST_7_r11 1437 -#define _SWAP_FAST_7_r22 1438 -#define _SWAP_FAST_7_r33 1439 -#define _TIER2_RESUME_CHECK_r00 1440 -#define _TIER2_RESUME_CHECK_r11 1441 -#define _TIER2_RESUME_CHECK_r22 1442 -#define _TIER2_RESUME_CHECK_r33 1443 -#define _TO_BOOL_r11 1444 -#define _TO_BOOL_BOOL_r01 1445 -#define _TO_BOOL_BOOL_r11 1446 -#define _TO_BOOL_BOOL_r22 1447 -#define _TO_BOOL_BOOL_r33 1448 -#define _TO_BOOL_INT_r02 1449 -#define _TO_BOOL_INT_r12 1450 -#define _TO_BOOL_INT_r23 1451 -#define _TO_BOOL_LIST_r02 1452 -#define _TO_BOOL_LIST_r12 1453 -#define _TO_BOOL_LIST_r23 1454 -#define _TO_BOOL_NONE_r01 1455 -#define _TO_BOOL_NONE_r11 1456 -#define _TO_BOOL_NONE_r22 1457 -#define _TO_BOOL_NONE_r33 1458 -#define _TO_BOOL_STR_r02 1459 -#define _TO_BOOL_STR_r12 1460 -#define _TO_BOOL_STR_r23 1461 -#define _TRACE_RECORD_r00 1462 -#define _UNARY_INVERT_r12 1463 -#define _UNARY_NEGATIVE_r12 1464 -#define _UNARY_NOT_r01 1465 -#define _UNARY_NOT_r11 1466 -#define _UNARY_NOT_r22 1467 -#define _UNARY_NOT_r33 1468 -#define _UNPACK_EX_r10 1469 -#define _UNPACK_SEQUENCE_r10 1470 -#define _UNPACK_SEQUENCE_LIST_r10 1471 -#define _UNPACK_SEQUENCE_TUPLE_r10 1472 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1473 -#define _WITH_EXCEPT_START_r33 1474 -#define _YIELD_VALUE_r11 1475 -#define MAX_UOP_REGS_ID 1475 +#define _YIELD_VALUE 596 +#define MAX_UOP_ID 596 +#define _BINARY_OP_r23 597 +#define _BINARY_OP_ADD_FLOAT_r03 598 +#define _BINARY_OP_ADD_FLOAT_r13 599 +#define _BINARY_OP_ADD_FLOAT_r23 600 +#define _BINARY_OP_ADD_INT_r03 601 +#define _BINARY_OP_ADD_INT_r13 602 +#define _BINARY_OP_ADD_INT_r23 603 +#define _BINARY_OP_ADD_UNICODE_r03 604 +#define _BINARY_OP_ADD_UNICODE_r13 605 +#define _BINARY_OP_ADD_UNICODE_r23 606 +#define _BINARY_OP_EXTEND_r23 607 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 608 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 609 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 610 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 611 +#define _BINARY_OP_MULTIPLY_INT_r03 612 +#define _BINARY_OP_MULTIPLY_INT_r13 613 +#define _BINARY_OP_MULTIPLY_INT_r23 614 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 615 +#define _BINARY_OP_SUBSCR_DICT_r23 616 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 617 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 618 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 619 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 620 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 621 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 622 +#define _BINARY_OP_SUBSCR_STR_INT_r23 623 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 624 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 625 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 626 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 627 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 628 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 629 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 630 +#define _BINARY_OP_SUBTRACT_INT_r03 631 +#define _BINARY_OP_SUBTRACT_INT_r13 632 +#define _BINARY_OP_SUBTRACT_INT_r23 633 +#define _BINARY_SLICE_r31 634 +#define _BUILD_INTERPOLATION_r01 635 +#define _BUILD_LIST_r01 636 +#define _BUILD_MAP_r01 637 +#define _BUILD_SET_r01 638 +#define _BUILD_SLICE_r01 639 +#define _BUILD_STRING_r01 640 +#define _BUILD_TEMPLATE_r21 641 +#define _BUILD_TUPLE_r01 642 +#define _CALL_BUILTIN_CLASS_r01 643 +#define _CALL_BUILTIN_FAST_r01 644 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 645 +#define _CALL_BUILTIN_O_r03 646 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 647 +#define _CALL_INTRINSIC_1_r11 648 +#define _CALL_INTRINSIC_2_r21 649 +#define _CALL_ISINSTANCE_r31 650 +#define _CALL_KW_NON_PY_r11 651 +#define _CALL_LEN_r33 652 +#define _CALL_LIST_APPEND_r03 653 +#define _CALL_LIST_APPEND_r13 654 +#define _CALL_LIST_APPEND_r23 655 +#define _CALL_LIST_APPEND_r33 656 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 657 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 658 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 659 +#define _CALL_METHOD_DESCRIPTOR_O_r03 660 +#define _CALL_NON_PY_GENERAL_r01 661 +#define _CALL_STR_1_r32 662 +#define _CALL_TUPLE_1_r32 663 +#define _CALL_TYPE_1_r02 664 +#define _CALL_TYPE_1_r12 665 +#define _CALL_TYPE_1_r22 666 +#define _CALL_TYPE_1_r32 667 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 668 +#define _CHECK_ATTR_CLASS_r01 669 +#define _CHECK_ATTR_CLASS_r11 670 +#define _CHECK_ATTR_CLASS_r22 671 +#define _CHECK_ATTR_CLASS_r33 672 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 673 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 674 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 675 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 676 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 677 +#define _CHECK_EG_MATCH_r22 678 +#define _CHECK_EXC_MATCH_r22 679 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 680 +#define _CHECK_FUNCTION_VERSION_r00 681 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 682 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 683 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 684 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 685 +#define _CHECK_FUNCTION_VERSION_KW_r11 686 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 687 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 688 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 689 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 690 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 691 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 692 +#define _CHECK_IS_PY_CALLABLE_EX_r03 693 +#define _CHECK_IS_PY_CALLABLE_EX_r13 694 +#define _CHECK_IS_PY_CALLABLE_EX_r23 695 +#define _CHECK_IS_PY_CALLABLE_EX_r33 696 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 697 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 698 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 699 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 700 +#define _CHECK_METHOD_VERSION_r00 701 +#define _CHECK_METHOD_VERSION_KW_r11 702 +#define _CHECK_PEP_523_r00 703 +#define _CHECK_PEP_523_r11 704 +#define _CHECK_PEP_523_r22 705 +#define _CHECK_PEP_523_r33 706 +#define _CHECK_PERIODIC_r00 707 +#define _CHECK_PERIODIC_AT_END_r00 708 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 709 +#define _CHECK_RECURSION_REMAINING_r00 710 +#define _CHECK_RECURSION_REMAINING_r11 711 +#define _CHECK_RECURSION_REMAINING_r22 712 +#define _CHECK_RECURSION_REMAINING_r33 713 +#define _CHECK_STACK_SPACE_r00 714 +#define _CHECK_STACK_SPACE_OPERAND_r00 715 +#define _CHECK_STACK_SPACE_OPERAND_r11 716 +#define _CHECK_STACK_SPACE_OPERAND_r22 717 +#define _CHECK_STACK_SPACE_OPERAND_r33 718 +#define _CHECK_VALIDITY_r00 719 +#define _CHECK_VALIDITY_r11 720 +#define _CHECK_VALIDITY_r22 721 +#define _CHECK_VALIDITY_r33 722 +#define _COLD_DYNAMIC_EXIT_r00 723 +#define _COLD_EXIT_r00 724 +#define _COMPARE_OP_r21 725 +#define _COMPARE_OP_FLOAT_r03 726 +#define _COMPARE_OP_FLOAT_r13 727 +#define _COMPARE_OP_FLOAT_r23 728 +#define _COMPARE_OP_INT_r23 729 +#define _COMPARE_OP_STR_r23 730 +#define _CONTAINS_OP_r23 731 +#define _CONTAINS_OP_DICT_r23 732 +#define _CONTAINS_OP_SET_r23 733 +#define _CONVERT_VALUE_r11 734 +#define _COPY_r01 735 +#define _COPY_1_r02 736 +#define _COPY_1_r12 737 +#define _COPY_1_r23 738 +#define _COPY_2_r03 739 +#define _COPY_2_r13 740 +#define _COPY_2_r23 741 +#define _COPY_3_r03 742 +#define _COPY_3_r13 743 +#define _COPY_3_r23 744 +#define _COPY_3_r33 745 +#define _COPY_FREE_VARS_r00 746 +#define _COPY_FREE_VARS_r11 747 +#define _COPY_FREE_VARS_r22 748 +#define _COPY_FREE_VARS_r33 749 +#define _CREATE_INIT_FRAME_r01 750 +#define _DELETE_ATTR_r10 751 +#define _DELETE_DEREF_r00 752 +#define _DELETE_FAST_r00 753 +#define _DELETE_GLOBAL_r00 754 +#define _DELETE_NAME_r00 755 +#define _DELETE_SUBSCR_r20 756 +#define _DEOPT_r00 757 +#define _DEOPT_r10 758 +#define _DEOPT_r20 759 +#define _DEOPT_r30 760 +#define _DICT_MERGE_r10 761 +#define _DICT_UPDATE_r10 762 +#define _DO_CALL_r01 763 +#define _DO_CALL_FUNCTION_EX_r31 764 +#define _DO_CALL_KW_r11 765 +#define _DYNAMIC_EXIT_r00 766 +#define _DYNAMIC_EXIT_r10 767 +#define _DYNAMIC_EXIT_r20 768 +#define _DYNAMIC_EXIT_r30 769 +#define _END_FOR_r10 770 +#define _END_SEND_r21 771 +#define _ERROR_POP_N_r00 772 +#define _EXIT_INIT_CHECK_r10 773 +#define _EXIT_TRACE_r00 774 +#define _EXIT_TRACE_r10 775 +#define _EXIT_TRACE_r20 776 +#define _EXIT_TRACE_r30 777 +#define _EXPAND_METHOD_r00 778 +#define _EXPAND_METHOD_KW_r11 779 +#define _FATAL_ERROR_r00 780 +#define _FATAL_ERROR_r11 781 +#define _FATAL_ERROR_r22 782 +#define _FATAL_ERROR_r33 783 +#define _FORMAT_SIMPLE_r11 784 +#define _FORMAT_WITH_SPEC_r21 785 +#define _FOR_ITER_r23 786 +#define _FOR_ITER_GEN_FRAME_r03 787 +#define _FOR_ITER_GEN_FRAME_r13 788 +#define _FOR_ITER_GEN_FRAME_r23 789 +#define _FOR_ITER_TIER_TWO_r23 790 +#define _GET_AITER_r11 791 +#define _GET_ANEXT_r12 792 +#define _GET_AWAITABLE_r11 793 +#define _GET_ITER_r12 794 +#define _GET_LEN_r12 795 +#define _GET_YIELD_FROM_ITER_r11 796 +#define _GUARD_BINARY_OP_EXTEND_r22 797 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 798 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 799 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 800 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 801 +#define _GUARD_BIT_IS_SET_POP_r00 802 +#define _GUARD_BIT_IS_SET_POP_r10 803 +#define _GUARD_BIT_IS_SET_POP_r21 804 +#define _GUARD_BIT_IS_SET_POP_r32 805 +#define _GUARD_BIT_IS_SET_POP_4_r00 806 +#define _GUARD_BIT_IS_SET_POP_4_r10 807 +#define _GUARD_BIT_IS_SET_POP_4_r21 808 +#define _GUARD_BIT_IS_SET_POP_4_r32 809 +#define _GUARD_BIT_IS_SET_POP_5_r00 810 +#define _GUARD_BIT_IS_SET_POP_5_r10 811 +#define _GUARD_BIT_IS_SET_POP_5_r21 812 +#define _GUARD_BIT_IS_SET_POP_5_r32 813 +#define _GUARD_BIT_IS_SET_POP_6_r00 814 +#define _GUARD_BIT_IS_SET_POP_6_r10 815 +#define _GUARD_BIT_IS_SET_POP_6_r21 816 +#define _GUARD_BIT_IS_SET_POP_6_r32 817 +#define _GUARD_BIT_IS_SET_POP_7_r00 818 +#define _GUARD_BIT_IS_SET_POP_7_r10 819 +#define _GUARD_BIT_IS_SET_POP_7_r21 820 +#define _GUARD_BIT_IS_SET_POP_7_r32 821 +#define _GUARD_BIT_IS_UNSET_POP_r00 822 +#define _GUARD_BIT_IS_UNSET_POP_r10 823 +#define _GUARD_BIT_IS_UNSET_POP_r21 824 +#define _GUARD_BIT_IS_UNSET_POP_r32 825 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 826 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 827 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 828 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 829 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 830 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 831 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 832 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 833 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 834 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 835 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 836 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 837 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 838 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 839 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 840 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 841 +#define _GUARD_CALLABLE_ISINSTANCE_r03 842 +#define _GUARD_CALLABLE_ISINSTANCE_r13 843 +#define _GUARD_CALLABLE_ISINSTANCE_r23 844 +#define _GUARD_CALLABLE_ISINSTANCE_r33 845 +#define _GUARD_CALLABLE_LEN_r03 846 +#define _GUARD_CALLABLE_LEN_r13 847 +#define _GUARD_CALLABLE_LEN_r23 848 +#define _GUARD_CALLABLE_LEN_r33 849 +#define _GUARD_CALLABLE_LIST_APPEND_r03 850 +#define _GUARD_CALLABLE_LIST_APPEND_r13 851 +#define _GUARD_CALLABLE_LIST_APPEND_r23 852 +#define _GUARD_CALLABLE_LIST_APPEND_r33 853 +#define _GUARD_CALLABLE_STR_1_r03 854 +#define _GUARD_CALLABLE_STR_1_r13 855 +#define _GUARD_CALLABLE_STR_1_r23 856 +#define _GUARD_CALLABLE_STR_1_r33 857 +#define _GUARD_CALLABLE_TUPLE_1_r03 858 +#define _GUARD_CALLABLE_TUPLE_1_r13 859 +#define _GUARD_CALLABLE_TUPLE_1_r23 860 +#define _GUARD_CALLABLE_TUPLE_1_r33 861 +#define _GUARD_CALLABLE_TYPE_1_r03 862 +#define _GUARD_CALLABLE_TYPE_1_r13 863 +#define _GUARD_CALLABLE_TYPE_1_r23 864 +#define _GUARD_CALLABLE_TYPE_1_r33 865 +#define _GUARD_CODE_VERSION_r00 866 +#define _GUARD_CODE_VERSION_r11 867 +#define _GUARD_CODE_VERSION_r22 868 +#define _GUARD_CODE_VERSION_r33 869 +#define _GUARD_DORV_NO_DICT_r01 870 +#define _GUARD_DORV_NO_DICT_r11 871 +#define _GUARD_DORV_NO_DICT_r22 872 +#define _GUARD_DORV_NO_DICT_r33 873 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 874 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 875 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 876 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 877 +#define _GUARD_GLOBALS_VERSION_r00 878 +#define _GUARD_GLOBALS_VERSION_r11 879 +#define _GUARD_GLOBALS_VERSION_r22 880 +#define _GUARD_GLOBALS_VERSION_r33 881 +#define _GUARD_IP_RETURN_GENERATOR_r00 882 +#define _GUARD_IP_RETURN_GENERATOR_r11 883 +#define _GUARD_IP_RETURN_GENERATOR_r22 884 +#define _GUARD_IP_RETURN_GENERATOR_r33 885 +#define _GUARD_IP_RETURN_VALUE_r00 886 +#define _GUARD_IP_RETURN_VALUE_r11 887 +#define _GUARD_IP_RETURN_VALUE_r22 888 +#define _GUARD_IP_RETURN_VALUE_r33 889 +#define _GUARD_IP_YIELD_VALUE_r00 890 +#define _GUARD_IP_YIELD_VALUE_r11 891 +#define _GUARD_IP_YIELD_VALUE_r22 892 +#define _GUARD_IP_YIELD_VALUE_r33 893 +#define _GUARD_IP__PUSH_FRAME_r00 894 +#define _GUARD_IP__PUSH_FRAME_r11 895 +#define _GUARD_IP__PUSH_FRAME_r22 896 +#define _GUARD_IP__PUSH_FRAME_r33 897 +#define _GUARD_IS_FALSE_POP_r00 898 +#define _GUARD_IS_FALSE_POP_r10 899 +#define _GUARD_IS_FALSE_POP_r21 900 +#define _GUARD_IS_FALSE_POP_r32 901 +#define _GUARD_IS_NONE_POP_r00 902 +#define _GUARD_IS_NONE_POP_r10 903 +#define _GUARD_IS_NONE_POP_r21 904 +#define _GUARD_IS_NONE_POP_r32 905 +#define _GUARD_IS_NOT_NONE_POP_r10 906 +#define _GUARD_IS_TRUE_POP_r00 907 +#define _GUARD_IS_TRUE_POP_r10 908 +#define _GUARD_IS_TRUE_POP_r21 909 +#define _GUARD_IS_TRUE_POP_r32 910 +#define _GUARD_KEYS_VERSION_r01 911 +#define _GUARD_KEYS_VERSION_r11 912 +#define _GUARD_KEYS_VERSION_r22 913 +#define _GUARD_KEYS_VERSION_r33 914 +#define _GUARD_NOS_ANY_DICT_r02 915 +#define _GUARD_NOS_ANY_DICT_r12 916 +#define _GUARD_NOS_ANY_DICT_r22 917 +#define _GUARD_NOS_ANY_DICT_r33 918 +#define _GUARD_NOS_COMPACT_ASCII_r02 919 +#define _GUARD_NOS_COMPACT_ASCII_r12 920 +#define _GUARD_NOS_COMPACT_ASCII_r22 921 +#define _GUARD_NOS_COMPACT_ASCII_r33 922 +#define _GUARD_NOS_DICT_r02 923 +#define _GUARD_NOS_DICT_r12 924 +#define _GUARD_NOS_DICT_r22 925 +#define _GUARD_NOS_DICT_r33 926 +#define _GUARD_NOS_FLOAT_r02 927 +#define _GUARD_NOS_FLOAT_r12 928 +#define _GUARD_NOS_FLOAT_r22 929 +#define _GUARD_NOS_FLOAT_r33 930 +#define _GUARD_NOS_INT_r02 931 +#define _GUARD_NOS_INT_r12 932 +#define _GUARD_NOS_INT_r22 933 +#define _GUARD_NOS_INT_r33 934 +#define _GUARD_NOS_LIST_r02 935 +#define _GUARD_NOS_LIST_r12 936 +#define _GUARD_NOS_LIST_r22 937 +#define _GUARD_NOS_LIST_r33 938 +#define _GUARD_NOS_NOT_NULL_r02 939 +#define _GUARD_NOS_NOT_NULL_r12 940 +#define _GUARD_NOS_NOT_NULL_r22 941 +#define _GUARD_NOS_NOT_NULL_r33 942 +#define _GUARD_NOS_NULL_r02 943 +#define _GUARD_NOS_NULL_r12 944 +#define _GUARD_NOS_NULL_r22 945 +#define _GUARD_NOS_NULL_r33 946 +#define _GUARD_NOS_OVERFLOWED_r02 947 +#define _GUARD_NOS_OVERFLOWED_r12 948 +#define _GUARD_NOS_OVERFLOWED_r22 949 +#define _GUARD_NOS_OVERFLOWED_r33 950 +#define _GUARD_NOS_TUPLE_r02 951 +#define _GUARD_NOS_TUPLE_r12 952 +#define _GUARD_NOS_TUPLE_r22 953 +#define _GUARD_NOS_TUPLE_r33 954 +#define _GUARD_NOS_UNICODE_r02 955 +#define _GUARD_NOS_UNICODE_r12 956 +#define _GUARD_NOS_UNICODE_r22 957 +#define _GUARD_NOS_UNICODE_r33 958 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 959 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 960 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 961 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 962 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 963 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 964 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 965 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 966 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 967 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 968 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 969 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 970 +#define _GUARD_THIRD_NULL_r03 971 +#define _GUARD_THIRD_NULL_r13 972 +#define _GUARD_THIRD_NULL_r23 973 +#define _GUARD_THIRD_NULL_r33 974 +#define _GUARD_TOS_ANY_DICT_r01 975 +#define _GUARD_TOS_ANY_DICT_r11 976 +#define _GUARD_TOS_ANY_DICT_r22 977 +#define _GUARD_TOS_ANY_DICT_r33 978 +#define _GUARD_TOS_ANY_SET_r01 979 +#define _GUARD_TOS_ANY_SET_r11 980 +#define _GUARD_TOS_ANY_SET_r22 981 +#define _GUARD_TOS_ANY_SET_r33 982 +#define _GUARD_TOS_DICT_r01 983 +#define _GUARD_TOS_DICT_r11 984 +#define _GUARD_TOS_DICT_r22 985 +#define _GUARD_TOS_DICT_r33 986 +#define _GUARD_TOS_FLOAT_r01 987 +#define _GUARD_TOS_FLOAT_r11 988 +#define _GUARD_TOS_FLOAT_r22 989 +#define _GUARD_TOS_FLOAT_r33 990 +#define _GUARD_TOS_FROZENDICT_r01 991 +#define _GUARD_TOS_FROZENDICT_r11 992 +#define _GUARD_TOS_FROZENDICT_r22 993 +#define _GUARD_TOS_FROZENDICT_r33 994 +#define _GUARD_TOS_FROZENSET_r01 995 +#define _GUARD_TOS_FROZENSET_r11 996 +#define _GUARD_TOS_FROZENSET_r22 997 +#define _GUARD_TOS_FROZENSET_r33 998 +#define _GUARD_TOS_INT_r01 999 +#define _GUARD_TOS_INT_r11 1000 +#define _GUARD_TOS_INT_r22 1001 +#define _GUARD_TOS_INT_r33 1002 +#define _GUARD_TOS_LIST_r01 1003 +#define _GUARD_TOS_LIST_r11 1004 +#define _GUARD_TOS_LIST_r22 1005 +#define _GUARD_TOS_LIST_r33 1006 +#define _GUARD_TOS_OVERFLOWED_r01 1007 +#define _GUARD_TOS_OVERFLOWED_r11 1008 +#define _GUARD_TOS_OVERFLOWED_r22 1009 +#define _GUARD_TOS_OVERFLOWED_r33 1010 +#define _GUARD_TOS_SET_r01 1011 +#define _GUARD_TOS_SET_r11 1012 +#define _GUARD_TOS_SET_r22 1013 +#define _GUARD_TOS_SET_r33 1014 +#define _GUARD_TOS_SLICE_r01 1015 +#define _GUARD_TOS_SLICE_r11 1016 +#define _GUARD_TOS_SLICE_r22 1017 +#define _GUARD_TOS_SLICE_r33 1018 +#define _GUARD_TOS_TUPLE_r01 1019 +#define _GUARD_TOS_TUPLE_r11 1020 +#define _GUARD_TOS_TUPLE_r22 1021 +#define _GUARD_TOS_TUPLE_r33 1022 +#define _GUARD_TOS_UNICODE_r01 1023 +#define _GUARD_TOS_UNICODE_r11 1024 +#define _GUARD_TOS_UNICODE_r22 1025 +#define _GUARD_TOS_UNICODE_r33 1026 +#define _GUARD_TYPE_VERSION_r01 1027 +#define _GUARD_TYPE_VERSION_r11 1028 +#define _GUARD_TYPE_VERSION_r22 1029 +#define _GUARD_TYPE_VERSION_r33 1030 +#define _GUARD_TYPE_VERSION_AND_LOCK_r01 1031 +#define _GUARD_TYPE_VERSION_AND_LOCK_r11 1032 +#define _GUARD_TYPE_VERSION_AND_LOCK_r22 1033 +#define _GUARD_TYPE_VERSION_AND_LOCK_r33 1034 +#define _HANDLE_PENDING_AND_DEOPT_r00 1035 +#define _HANDLE_PENDING_AND_DEOPT_r10 1036 +#define _HANDLE_PENDING_AND_DEOPT_r20 1037 +#define _HANDLE_PENDING_AND_DEOPT_r30 1038 +#define _IMPORT_FROM_r12 1039 +#define _IMPORT_NAME_r21 1040 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1041 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1042 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1043 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1044 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1045 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1046 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1047 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1048 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1049 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1050 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1051 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1052 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1053 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1054 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1055 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1056 +#define _INSERT_NULL_r10 1057 +#define _INSTRUMENTED_FOR_ITER_r23 1058 +#define _INSTRUMENTED_INSTRUCTION_r00 1059 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1060 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1061 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1062 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1063 +#define _INSTRUMENTED_LINE_r00 1064 +#define _INSTRUMENTED_NOT_TAKEN_r00 1065 +#define _INSTRUMENTED_NOT_TAKEN_r11 1066 +#define _INSTRUMENTED_NOT_TAKEN_r22 1067 +#define _INSTRUMENTED_NOT_TAKEN_r33 1068 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1069 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1070 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1071 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1072 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1073 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1074 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1075 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1076 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1077 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1078 +#define _IS_NONE_r11 1079 +#define _IS_OP_r03 1080 +#define _IS_OP_r13 1081 +#define _IS_OP_r23 1082 +#define _ITER_CHECK_LIST_r02 1083 +#define _ITER_CHECK_LIST_r12 1084 +#define _ITER_CHECK_LIST_r22 1085 +#define _ITER_CHECK_LIST_r33 1086 +#define _ITER_CHECK_RANGE_r02 1087 +#define _ITER_CHECK_RANGE_r12 1088 +#define _ITER_CHECK_RANGE_r22 1089 +#define _ITER_CHECK_RANGE_r33 1090 +#define _ITER_CHECK_TUPLE_r02 1091 +#define _ITER_CHECK_TUPLE_r12 1092 +#define _ITER_CHECK_TUPLE_r22 1093 +#define _ITER_CHECK_TUPLE_r33 1094 +#define _ITER_JUMP_LIST_r02 1095 +#define _ITER_JUMP_LIST_r12 1096 +#define _ITER_JUMP_LIST_r22 1097 +#define _ITER_JUMP_LIST_r33 1098 +#define _ITER_JUMP_RANGE_r02 1099 +#define _ITER_JUMP_RANGE_r12 1100 +#define _ITER_JUMP_RANGE_r22 1101 +#define _ITER_JUMP_RANGE_r33 1102 +#define _ITER_JUMP_TUPLE_r02 1103 +#define _ITER_JUMP_TUPLE_r12 1104 +#define _ITER_JUMP_TUPLE_r22 1105 +#define _ITER_JUMP_TUPLE_r33 1106 +#define _ITER_NEXT_LIST_r23 1107 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1108 +#define _ITER_NEXT_RANGE_r03 1109 +#define _ITER_NEXT_RANGE_r13 1110 +#define _ITER_NEXT_RANGE_r23 1111 +#define _ITER_NEXT_TUPLE_r03 1112 +#define _ITER_NEXT_TUPLE_r13 1113 +#define _ITER_NEXT_TUPLE_r23 1114 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1115 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1116 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1117 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1118 +#define _JUMP_TO_TOP_r00 1119 +#define _LIST_APPEND_r10 1120 +#define _LIST_EXTEND_r10 1121 +#define _LOAD_ATTR_r10 1122 +#define _LOAD_ATTR_CLASS_r11 1123 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1124 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1125 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1126 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1127 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1128 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1129 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1130 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1131 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1132 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1133 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1134 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1135 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1136 +#define _LOAD_ATTR_MODULE_r12 1137 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1138 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1139 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1140 +#define _LOAD_ATTR_SLOT_r02 1141 +#define _LOAD_ATTR_SLOT_r12 1142 +#define _LOAD_ATTR_SLOT_r23 1143 +#define _LOAD_ATTR_WITH_HINT_r12 1144 +#define _LOAD_BUILD_CLASS_r01 1145 +#define _LOAD_BYTECODE_r00 1146 +#define _LOAD_COMMON_CONSTANT_r01 1147 +#define _LOAD_COMMON_CONSTANT_r12 1148 +#define _LOAD_COMMON_CONSTANT_r23 1149 +#define _LOAD_CONST_r01 1150 +#define _LOAD_CONST_r12 1151 +#define _LOAD_CONST_r23 1152 +#define _LOAD_CONST_INLINE_r01 1153 +#define _LOAD_CONST_INLINE_r12 1154 +#define _LOAD_CONST_INLINE_r23 1155 +#define _LOAD_CONST_INLINE_BORROW_r01 1156 +#define _LOAD_CONST_INLINE_BORROW_r12 1157 +#define _LOAD_CONST_INLINE_BORROW_r23 1158 +#define _LOAD_CONST_UNDER_INLINE_r02 1159 +#define _LOAD_CONST_UNDER_INLINE_r12 1160 +#define _LOAD_CONST_UNDER_INLINE_r23 1161 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1162 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1163 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1164 +#define _LOAD_DEREF_r01 1165 +#define _LOAD_FAST_r01 1166 +#define _LOAD_FAST_r12 1167 +#define _LOAD_FAST_r23 1168 +#define _LOAD_FAST_0_r01 1169 +#define _LOAD_FAST_0_r12 1170 +#define _LOAD_FAST_0_r23 1171 +#define _LOAD_FAST_1_r01 1172 +#define _LOAD_FAST_1_r12 1173 +#define _LOAD_FAST_1_r23 1174 +#define _LOAD_FAST_2_r01 1175 +#define _LOAD_FAST_2_r12 1176 +#define _LOAD_FAST_2_r23 1177 +#define _LOAD_FAST_3_r01 1178 +#define _LOAD_FAST_3_r12 1179 +#define _LOAD_FAST_3_r23 1180 +#define _LOAD_FAST_4_r01 1181 +#define _LOAD_FAST_4_r12 1182 +#define _LOAD_FAST_4_r23 1183 +#define _LOAD_FAST_5_r01 1184 +#define _LOAD_FAST_5_r12 1185 +#define _LOAD_FAST_5_r23 1186 +#define _LOAD_FAST_6_r01 1187 +#define _LOAD_FAST_6_r12 1188 +#define _LOAD_FAST_6_r23 1189 +#define _LOAD_FAST_7_r01 1190 +#define _LOAD_FAST_7_r12 1191 +#define _LOAD_FAST_7_r23 1192 +#define _LOAD_FAST_AND_CLEAR_r01 1193 +#define _LOAD_FAST_AND_CLEAR_r12 1194 +#define _LOAD_FAST_AND_CLEAR_r23 1195 +#define _LOAD_FAST_BORROW_r01 1196 +#define _LOAD_FAST_BORROW_r12 1197 +#define _LOAD_FAST_BORROW_r23 1198 +#define _LOAD_FAST_BORROW_0_r01 1199 +#define _LOAD_FAST_BORROW_0_r12 1200 +#define _LOAD_FAST_BORROW_0_r23 1201 +#define _LOAD_FAST_BORROW_1_r01 1202 +#define _LOAD_FAST_BORROW_1_r12 1203 +#define _LOAD_FAST_BORROW_1_r23 1204 +#define _LOAD_FAST_BORROW_2_r01 1205 +#define _LOAD_FAST_BORROW_2_r12 1206 +#define _LOAD_FAST_BORROW_2_r23 1207 +#define _LOAD_FAST_BORROW_3_r01 1208 +#define _LOAD_FAST_BORROW_3_r12 1209 +#define _LOAD_FAST_BORROW_3_r23 1210 +#define _LOAD_FAST_BORROW_4_r01 1211 +#define _LOAD_FAST_BORROW_4_r12 1212 +#define _LOAD_FAST_BORROW_4_r23 1213 +#define _LOAD_FAST_BORROW_5_r01 1214 +#define _LOAD_FAST_BORROW_5_r12 1215 +#define _LOAD_FAST_BORROW_5_r23 1216 +#define _LOAD_FAST_BORROW_6_r01 1217 +#define _LOAD_FAST_BORROW_6_r12 1218 +#define _LOAD_FAST_BORROW_6_r23 1219 +#define _LOAD_FAST_BORROW_7_r01 1220 +#define _LOAD_FAST_BORROW_7_r12 1221 +#define _LOAD_FAST_BORROW_7_r23 1222 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1223 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1224 +#define _LOAD_FAST_CHECK_r01 1225 +#define _LOAD_FAST_CHECK_r12 1226 +#define _LOAD_FAST_CHECK_r23 1227 +#define _LOAD_FAST_LOAD_FAST_r02 1228 +#define _LOAD_FAST_LOAD_FAST_r13 1229 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1230 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1231 +#define _LOAD_GLOBAL_r00 1232 +#define _LOAD_GLOBAL_BUILTINS_r01 1233 +#define _LOAD_GLOBAL_MODULE_r01 1234 +#define _LOAD_LOCALS_r01 1235 +#define _LOAD_LOCALS_r12 1236 +#define _LOAD_LOCALS_r23 1237 +#define _LOAD_NAME_r01 1238 +#define _LOAD_SMALL_INT_r01 1239 +#define _LOAD_SMALL_INT_r12 1240 +#define _LOAD_SMALL_INT_r23 1241 +#define _LOAD_SMALL_INT_0_r01 1242 +#define _LOAD_SMALL_INT_0_r12 1243 +#define _LOAD_SMALL_INT_0_r23 1244 +#define _LOAD_SMALL_INT_1_r01 1245 +#define _LOAD_SMALL_INT_1_r12 1246 +#define _LOAD_SMALL_INT_1_r23 1247 +#define _LOAD_SMALL_INT_2_r01 1248 +#define _LOAD_SMALL_INT_2_r12 1249 +#define _LOAD_SMALL_INT_2_r23 1250 +#define _LOAD_SMALL_INT_3_r01 1251 +#define _LOAD_SMALL_INT_3_r12 1252 +#define _LOAD_SMALL_INT_3_r23 1253 +#define _LOAD_SPECIAL_r00 1254 +#define _LOAD_SUPER_ATTR_ATTR_r31 1255 +#define _LOAD_SUPER_ATTR_METHOD_r32 1256 +#define _MAKE_CALLARGS_A_TUPLE_r33 1257 +#define _MAKE_CELL_r00 1258 +#define _MAKE_FUNCTION_r11 1259 +#define _MAKE_HEAP_SAFE_r01 1260 +#define _MAKE_HEAP_SAFE_r11 1261 +#define _MAKE_HEAP_SAFE_r22 1262 +#define _MAKE_HEAP_SAFE_r33 1263 +#define _MAKE_WARM_r00 1264 +#define _MAKE_WARM_r11 1265 +#define _MAKE_WARM_r22 1266 +#define _MAKE_WARM_r33 1267 +#define _MAP_ADD_r20 1268 +#define _MATCH_CLASS_r31 1269 +#define _MATCH_KEYS_r23 1270 +#define _MATCH_MAPPING_r02 1271 +#define _MATCH_MAPPING_r12 1272 +#define _MATCH_MAPPING_r23 1273 +#define _MATCH_SEQUENCE_r02 1274 +#define _MATCH_SEQUENCE_r12 1275 +#define _MATCH_SEQUENCE_r23 1276 +#define _MAYBE_EXPAND_METHOD_r00 1277 +#define _MAYBE_EXPAND_METHOD_KW_r11 1278 +#define _MONITOR_CALL_r00 1279 +#define _MONITOR_CALL_KW_r11 1280 +#define _MONITOR_JUMP_BACKWARD_r00 1281 +#define _MONITOR_JUMP_BACKWARD_r11 1282 +#define _MONITOR_JUMP_BACKWARD_r22 1283 +#define _MONITOR_JUMP_BACKWARD_r33 1284 +#define _MONITOR_RESUME_r00 1285 +#define _NOP_r00 1286 +#define _NOP_r11 1287 +#define _NOP_r22 1288 +#define _NOP_r33 1289 +#define _POP_CALL_r20 1290 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1291 +#define _POP_CALL_ONE_r30 1292 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1293 +#define _POP_CALL_TWO_r30 1294 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1295 +#define _POP_EXCEPT_r10 1296 +#define _POP_ITER_r20 1297 +#define _POP_JUMP_IF_FALSE_r00 1298 +#define _POP_JUMP_IF_FALSE_r10 1299 +#define _POP_JUMP_IF_FALSE_r21 1300 +#define _POP_JUMP_IF_FALSE_r32 1301 +#define _POP_JUMP_IF_TRUE_r00 1302 +#define _POP_JUMP_IF_TRUE_r10 1303 +#define _POP_JUMP_IF_TRUE_r21 1304 +#define _POP_JUMP_IF_TRUE_r32 1305 +#define _POP_TOP_r10 1306 +#define _POP_TOP_FLOAT_r00 1307 +#define _POP_TOP_FLOAT_r10 1308 +#define _POP_TOP_FLOAT_r21 1309 +#define _POP_TOP_FLOAT_r32 1310 +#define _POP_TOP_INT_r00 1311 +#define _POP_TOP_INT_r10 1312 +#define _POP_TOP_INT_r21 1313 +#define _POP_TOP_INT_r32 1314 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1315 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1316 +#define _POP_TOP_NOP_r00 1317 +#define _POP_TOP_NOP_r10 1318 +#define _POP_TOP_NOP_r21 1319 +#define _POP_TOP_NOP_r32 1320 +#define _POP_TOP_UNICODE_r00 1321 +#define _POP_TOP_UNICODE_r10 1322 +#define _POP_TOP_UNICODE_r21 1323 +#define _POP_TOP_UNICODE_r32 1324 +#define _POP_TWO_r20 1325 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1326 +#define _PUSH_EXC_INFO_r02 1327 +#define _PUSH_EXC_INFO_r12 1328 +#define _PUSH_EXC_INFO_r23 1329 +#define _PUSH_FRAME_r10 1330 +#define _PUSH_NULL_r01 1331 +#define _PUSH_NULL_r12 1332 +#define _PUSH_NULL_r23 1333 +#define _PUSH_NULL_CONDITIONAL_r00 1334 +#define _PY_FRAME_EX_r31 1335 +#define _PY_FRAME_GENERAL_r01 1336 +#define _PY_FRAME_KW_r11 1337 +#define _QUICKEN_RESUME_r00 1338 +#define _QUICKEN_RESUME_r11 1339 +#define _QUICKEN_RESUME_r22 1340 +#define _QUICKEN_RESUME_r33 1341 +#define _REPLACE_WITH_TRUE_r02 1342 +#define _REPLACE_WITH_TRUE_r12 1343 +#define _REPLACE_WITH_TRUE_r23 1344 +#define _RESUME_CHECK_r00 1345 +#define _RESUME_CHECK_r11 1346 +#define _RESUME_CHECK_r22 1347 +#define _RESUME_CHECK_r33 1348 +#define _RETURN_GENERATOR_r01 1349 +#define _RETURN_VALUE_r11 1350 +#define _SAVE_RETURN_OFFSET_r00 1351 +#define _SAVE_RETURN_OFFSET_r11 1352 +#define _SAVE_RETURN_OFFSET_r22 1353 +#define _SAVE_RETURN_OFFSET_r33 1354 +#define _SEND_r22 1355 +#define _SEND_GEN_FRAME_r22 1356 +#define _SETUP_ANNOTATIONS_r00 1357 +#define _SET_ADD_r10 1358 +#define _SET_FUNCTION_ATTRIBUTE_r01 1359 +#define _SET_FUNCTION_ATTRIBUTE_r11 1360 +#define _SET_FUNCTION_ATTRIBUTE_r21 1361 +#define _SET_FUNCTION_ATTRIBUTE_r32 1362 +#define _SET_IP_r00 1363 +#define _SET_IP_r11 1364 +#define _SET_IP_r22 1365 +#define _SET_IP_r33 1366 +#define _SET_UPDATE_r10 1367 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1368 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1369 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1370 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1371 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1372 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1373 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1374 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1375 +#define _SPILL_OR_RELOAD_r01 1376 +#define _SPILL_OR_RELOAD_r02 1377 +#define _SPILL_OR_RELOAD_r03 1378 +#define _SPILL_OR_RELOAD_r10 1379 +#define _SPILL_OR_RELOAD_r12 1380 +#define _SPILL_OR_RELOAD_r13 1381 +#define _SPILL_OR_RELOAD_r20 1382 +#define _SPILL_OR_RELOAD_r21 1383 +#define _SPILL_OR_RELOAD_r23 1384 +#define _SPILL_OR_RELOAD_r30 1385 +#define _SPILL_OR_RELOAD_r31 1386 +#define _SPILL_OR_RELOAD_r32 1387 +#define _START_EXECUTOR_r00 1388 +#define _STORE_ATTR_r20 1389 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1390 +#define _STORE_ATTR_SLOT_r21 1391 +#define _STORE_ATTR_WITH_HINT_r21 1392 +#define _STORE_DEREF_r10 1393 +#define _STORE_FAST_LOAD_FAST_r11 1394 +#define _STORE_FAST_STORE_FAST_r20 1395 +#define _STORE_GLOBAL_r10 1396 +#define _STORE_NAME_r10 1397 +#define _STORE_SLICE_r30 1398 +#define _STORE_SUBSCR_r30 1399 +#define _STORE_SUBSCR_DICT_r31 1400 +#define _STORE_SUBSCR_LIST_INT_r32 1401 +#define _SWAP_r11 1402 +#define _SWAP_2_r02 1403 +#define _SWAP_2_r12 1404 +#define _SWAP_2_r22 1405 +#define _SWAP_2_r33 1406 +#define _SWAP_3_r03 1407 +#define _SWAP_3_r13 1408 +#define _SWAP_3_r23 1409 +#define _SWAP_3_r33 1410 +#define _SWAP_FAST_r01 1411 +#define _SWAP_FAST_r11 1412 +#define _SWAP_FAST_r22 1413 +#define _SWAP_FAST_r33 1414 +#define _SWAP_FAST_0_r01 1415 +#define _SWAP_FAST_0_r11 1416 +#define _SWAP_FAST_0_r22 1417 +#define _SWAP_FAST_0_r33 1418 +#define _SWAP_FAST_1_r01 1419 +#define _SWAP_FAST_1_r11 1420 +#define _SWAP_FAST_1_r22 1421 +#define _SWAP_FAST_1_r33 1422 +#define _SWAP_FAST_2_r01 1423 +#define _SWAP_FAST_2_r11 1424 +#define _SWAP_FAST_2_r22 1425 +#define _SWAP_FAST_2_r33 1426 +#define _SWAP_FAST_3_r01 1427 +#define _SWAP_FAST_3_r11 1428 +#define _SWAP_FAST_3_r22 1429 +#define _SWAP_FAST_3_r33 1430 +#define _SWAP_FAST_4_r01 1431 +#define _SWAP_FAST_4_r11 1432 +#define _SWAP_FAST_4_r22 1433 +#define _SWAP_FAST_4_r33 1434 +#define _SWAP_FAST_5_r01 1435 +#define _SWAP_FAST_5_r11 1436 +#define _SWAP_FAST_5_r22 1437 +#define _SWAP_FAST_5_r33 1438 +#define _SWAP_FAST_6_r01 1439 +#define _SWAP_FAST_6_r11 1440 +#define _SWAP_FAST_6_r22 1441 +#define _SWAP_FAST_6_r33 1442 +#define _SWAP_FAST_7_r01 1443 +#define _SWAP_FAST_7_r11 1444 +#define _SWAP_FAST_7_r22 1445 +#define _SWAP_FAST_7_r33 1446 +#define _TIER2_RESUME_CHECK_r00 1447 +#define _TIER2_RESUME_CHECK_r11 1448 +#define _TIER2_RESUME_CHECK_r22 1449 +#define _TIER2_RESUME_CHECK_r33 1450 +#define _TO_BOOL_r11 1451 +#define _TO_BOOL_BOOL_r01 1452 +#define _TO_BOOL_BOOL_r11 1453 +#define _TO_BOOL_BOOL_r22 1454 +#define _TO_BOOL_BOOL_r33 1455 +#define _TO_BOOL_INT_r02 1456 +#define _TO_BOOL_INT_r12 1457 +#define _TO_BOOL_INT_r23 1458 +#define _TO_BOOL_LIST_r02 1459 +#define _TO_BOOL_LIST_r12 1460 +#define _TO_BOOL_LIST_r23 1461 +#define _TO_BOOL_NONE_r01 1462 +#define _TO_BOOL_NONE_r11 1463 +#define _TO_BOOL_NONE_r22 1464 +#define _TO_BOOL_NONE_r33 1465 +#define _TO_BOOL_STR_r02 1466 +#define _TO_BOOL_STR_r12 1467 +#define _TO_BOOL_STR_r23 1468 +#define _TRACE_RECORD_r00 1469 +#define _UNARY_INVERT_r12 1470 +#define _UNARY_NEGATIVE_r12 1471 +#define _UNARY_NOT_r01 1472 +#define _UNARY_NOT_r11 1473 +#define _UNARY_NOT_r22 1474 +#define _UNARY_NOT_r33 1475 +#define _UNPACK_EX_r10 1476 +#define _UNPACK_SEQUENCE_r10 1477 +#define _UNPACK_SEQUENCE_LIST_r10 1478 +#define _UNPACK_SEQUENCE_TUPLE_r10 1479 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1480 +#define _WITH_EXCEPT_START_r33 1481 +#define _YIELD_VALUE_r11 1482 +#define MAX_UOP_REGS_ID 1482 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index c08f1e24fd1..4a8245365f8 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -142,6 +142,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_DELETE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MAKE_HEAP_SAFE] = 0, [_RETURN_VALUE] = HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG, [_GET_AITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GET_ANEXT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, @@ -1366,6 +1367,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_MAKE_HEAP_SAFE] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _MAKE_HEAP_SAFE_r01 }, + { 1, 1, _MAKE_HEAP_SAFE_r11 }, + { 2, 2, _MAKE_HEAP_SAFE_r22 }, + { 3, 3, _MAKE_HEAP_SAFE_r33 }, + }, + }, [_RETURN_VALUE] = { .best = { 1, 1, 1, 1 }, .entries = { @@ -3804,6 +3814,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_DELETE_SUBSCR_r20] = _DELETE_SUBSCR, [_CALL_INTRINSIC_1_r11] = _CALL_INTRINSIC_1, [_CALL_INTRINSIC_2_r21] = _CALL_INTRINSIC_2, + [_MAKE_HEAP_SAFE_r01] = _MAKE_HEAP_SAFE, + [_MAKE_HEAP_SAFE_r11] = _MAKE_HEAP_SAFE, + [_MAKE_HEAP_SAFE_r22] = _MAKE_HEAP_SAFE, + [_MAKE_HEAP_SAFE_r33] = _MAKE_HEAP_SAFE, [_RETURN_VALUE_r11] = _RETURN_VALUE, [_GET_AITER_r11] = _GET_AITER, [_GET_ANEXT_r12] = _GET_ANEXT, @@ -5199,6 +5213,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_MAKE_CELL_r00] = "_MAKE_CELL_r00", [_MAKE_FUNCTION] = "_MAKE_FUNCTION", [_MAKE_FUNCTION_r11] = "_MAKE_FUNCTION_r11", + [_MAKE_HEAP_SAFE] = "_MAKE_HEAP_SAFE", + [_MAKE_HEAP_SAFE_r01] = "_MAKE_HEAP_SAFE_r01", + [_MAKE_HEAP_SAFE_r11] = "_MAKE_HEAP_SAFE_r11", + [_MAKE_HEAP_SAFE_r22] = "_MAKE_HEAP_SAFE_r22", + [_MAKE_HEAP_SAFE_r33] = "_MAKE_HEAP_SAFE_r33", [_MAKE_WARM] = "_MAKE_WARM", [_MAKE_WARM_r00] = "_MAKE_WARM_r00", [_MAKE_WARM_r11] = "_MAKE_WARM_r11", @@ -5709,6 +5728,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _CALL_INTRINSIC_2: return 2; + case _MAKE_HEAP_SAFE: + return 0; case _RETURN_VALUE: return 1; case _GET_AITER: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 8fa4f02afb5..4dd1140f7d8 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -1304,6 +1304,50 @@ def testfunc(n): self.assertIsNotNone(ex) self.assertIn("_RETURN_GENERATOR", get_opnames(ex)) + def test_make_heap_safe_optimized_immortal(self): + def returns_immortal(): + return None + def testfunc(n): + a = 0 + for _ in range(n): + a = returns_immortal() + return a + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNone(res) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_MAKE_HEAP_SAFE", uops) + self.assertIn("_RETURN_VALUE", uops) + + def test_make_heap_safe_optimized_yield(self): + def gen(n): + for _ in range(n): + yield 1 + def testfunc(n): + for _ in gen(n): + pass + testfunc(TIER2_THRESHOLD * 2) + gen_ex = get_first_executor(gen) + self.assertIsNotNone(gen_ex) + uops = get_opnames(gen_ex) + self.assertNotIn("_MAKE_HEAP_SAFE", uops) + self.assertIn("_YIELD_VALUE", uops) + + def test_make_heap_safe_not_optimized_for_owned(self): + def returns_owned(x): + return x + 1 + def testfunc(n): + a = 0 + for _ in range(n): + a = returns_owned(a) + return a + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_MAKE_HEAP_SAFE", uops) + self.assertIn("_RETURN_VALUE", uops) + def test_for_iter(self): def testfunc(n): t = 0 diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 79320a4bff1..2615b1d4dd2 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -7519,6 +7519,7 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_RETURN_VALUE); _PyStackRef val; + _PyStackRef value; _PyStackRef retval; _PyStackRef res; // _RETURN_VALUE_EVENT @@ -7533,11 +7534,16 @@ JUMP_TO_LABEL(error); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _RETURN_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7568,8 +7574,8 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_YIELD_VALUE); _PyStackRef val; - _PyStackRef retval; _PyStackRef value; + _PyStackRef retval; // _YIELD_VALUE_EVENT { val = stack_pointer[-1]; @@ -7586,9 +7592,14 @@ DISPATCH(); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _YIELD_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -7617,7 +7628,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = value; @@ -10571,23 +10582,32 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(RETURN_VALUE); + _PyStackRef value; _PyStackRef retval; _PyStackRef res; - retval = stack_pointer[-1]; - assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - assert(STACK_LEVEL() == 0); - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *dying = frame; - frame = tstate->current_frame = dying->previous; - _PyEval_FrameClearAndPop(tstate, dying); - stack_pointer = _PyFrame_GetStackPointer(frame); - LOAD_IP(frame->return_offset); - res = temp; - LLTRACE_RESUME_FRAME(); + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } + // _RETURN_VALUE + { + retval = value; + assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); + _PyStackRef temp = retval; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(STACK_LEVEL() == 0); + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + stack_pointer = _PyFrame_GetStackPointer(frame); + LOAD_IP(frame->return_offset); + res = temp; + LLTRACE_RESUME_FRAME(); + } stack_pointer[0] = res; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -12402,39 +12422,47 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(YIELD_VALUE); - _PyStackRef retval; _PyStackRef value; - retval = stack_pointer[-1]; - assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - frame->instr_ptr++; - PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); - assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); - assert(oparg == 0 || oparg == 1); - _PyStackRef temp = retval; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *gen_frame = frame; - frame = tstate->current_frame = frame->previous; - gen_frame->previous = NULL; - ((_PyThreadStateImpl *)tstate)->generator_return_kind = GENERATOR_YIELD; - FT_ATOMIC_STORE_INT8_RELEASE(gen->gi_frame_state, FRAME_SUSPENDED + oparg); - assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); - #if TIER_ONE - assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || + _PyStackRef retval; + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } + // _YIELD_VALUE + { + retval = value; + assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); + frame->instr_ptr++; + PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); + assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); + assert(oparg == 0 || oparg == 1); + _PyStackRef temp = retval; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *gen_frame = frame; + frame = tstate->current_frame = frame->previous; + gen_frame->previous = NULL; + ((_PyThreadStateImpl *)tstate)->generator_return_kind = GENERATOR_YIELD; + FT_ATOMIC_STORE_INT8_RELEASE(gen->gi_frame_state, FRAME_SUSPENDED + oparg); + assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); + #if TIER_ONE + assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); - #endif - stack_pointer = _PyFrame_GetStackPointer(frame); - LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); - LLTRACE_RESUME_FRAME(); + #endif + stack_pointer = _PyFrame_GetStackPointer(frame); + LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); + value = temp; + LLTRACE_RESUME_FRAME(); + } stack_pointer[0] = value; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 8a748fec9e4..ac3e519398d 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1299,12 +1299,16 @@ dummy_func( return result; } + op(_MAKE_HEAP_SAFE, (value -- value)) { + value = PyStackRef_MakeHeapSafe(value); + } + // The stack effect here is a bit misleading. // retval is popped from the stack, but res // is pushed to a different frame, the callers' frame. - inst(RETURN_VALUE, (retval -- res)) { + op(_RETURN_VALUE, (retval -- res)) { assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; DEAD(retval); SAVE_STACK(); assert(STACK_LEVEL() == 0); @@ -1319,6 +1323,10 @@ dummy_func( LLTRACE_RESUME_FRAME(); } + macro(RETURN_VALUE) = + _MAKE_HEAP_SAFE + + _RETURN_VALUE; + tier1 op(_RETURN_VALUE_EVENT, (val -- val)) { int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, @@ -1328,7 +1336,8 @@ dummy_func( macro(INSTRUMENTED_RETURN_VALUE) = _RETURN_VALUE_EVENT + - RETURN_VALUE; + _MAKE_HEAP_SAFE + + _RETURN_VALUE; inst(GET_AITER, (obj -- iter)) { unaryfunc getter = NULL; @@ -1470,7 +1479,7 @@ dummy_func( _SEND_GEN_FRAME + _PUSH_FRAME; - inst(YIELD_VALUE, (retval -- value)) { + op(_YIELD_VALUE, (retval -- value)) { // NOTE: It's important that YIELD_VALUE never raises an exception! // The compiler treats any exception raised here as a failed close() // or throw() call. @@ -1502,10 +1511,14 @@ dummy_func( #endif RELOAD_STACK(); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } + macro(YIELD_VALUE) = + _MAKE_HEAP_SAFE + + _YIELD_VALUE; + tier1 op(_YIELD_VALUE_EVENT, (val -- val)) { int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_YIELD, @@ -1521,7 +1534,8 @@ dummy_func( macro(INSTRUMENTED_YIELD_VALUE) = _YIELD_VALUE_EVENT + - YIELD_VALUE; + _MAKE_HEAP_SAFE + + _YIELD_VALUE; inst(POP_EXCEPT, (exc_value -- )) { _PyErr_StackItem *exc_info = tstate->exc_info; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 09004545267..6271778bed4 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -6920,6 +6920,65 @@ break; } + case _MAKE_HEAP_SAFE_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _MAKE_HEAP_SAFE_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + value = _stack_item_0; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _MAKE_HEAP_SAFE_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + value = _stack_item_1; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache1 = value; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _MAKE_HEAP_SAFE_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + value = _stack_item_2; + value = PyStackRef_MakeHeapSafe(value); + _tos_cache2 = value; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _RETURN_VALUE_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -6928,7 +6987,7 @@ _PyStackRef _stack_item_0 = _tos_cache0; retval = _stack_item_0; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; _PyFrame_SetStackPointer(frame, stack_pointer); assert(STACK_LEVEL() == 0); _Py_LeaveRecursiveCallPy(tstate); @@ -7154,7 +7213,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); _tos_cache0 = value; _tos_cache1 = PyStackRef_ZERO_BITS; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 42098c59040..5d853998bf6 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -7518,6 +7518,7 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_RETURN_VALUE); _PyStackRef val; + _PyStackRef value; _PyStackRef retval; _PyStackRef res; // _RETURN_VALUE_EVENT @@ -7532,11 +7533,16 @@ JUMP_TO_LABEL(error); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _RETURN_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); + _PyStackRef temp = retval; stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7567,8 +7573,8 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_YIELD_VALUE); _PyStackRef val; - _PyStackRef retval; _PyStackRef value; + _PyStackRef retval; // _YIELD_VALUE_EVENT { val = stack_pointer[-1]; @@ -7585,9 +7591,14 @@ DISPATCH(); } } + // _MAKE_HEAP_SAFE + { + value = val; + value = PyStackRef_MakeHeapSafe(value); + } // _YIELD_VALUE { - retval = val; + retval = value; assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -7616,7 +7627,7 @@ #endif stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); + value = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = value; @@ -10568,23 +10579,32 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(RETURN_VALUE); + _PyStackRef value; _PyStackRef retval; _PyStackRef res; - retval = stack_pointer[-1]; - assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - _PyStackRef temp = PyStackRef_MakeHeapSafe(retval); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - assert(STACK_LEVEL() == 0); - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *dying = frame; - frame = tstate->current_frame = dying->previous; - _PyEval_FrameClearAndPop(tstate, dying); - stack_pointer = _PyFrame_GetStackPointer(frame); - LOAD_IP(frame->return_offset); - res = temp; - LLTRACE_RESUME_FRAME(); + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } + // _RETURN_VALUE + { + retval = value; + assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); + _PyStackRef temp = retval; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + assert(STACK_LEVEL() == 0); + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *dying = frame; + frame = tstate->current_frame = dying->previous; + _PyEval_FrameClearAndPop(tstate, dying); + stack_pointer = _PyFrame_GetStackPointer(frame); + LOAD_IP(frame->return_offset); + res = temp; + LLTRACE_RESUME_FRAME(); + } stack_pointer[0] = res; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -12399,39 +12419,47 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(YIELD_VALUE); - _PyStackRef retval; _PyStackRef value; - retval = stack_pointer[-1]; - assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - frame->instr_ptr++; - PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); - assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); - assert(oparg == 0 || oparg == 1); - _PyStackRef temp = retval; - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - tstate->exc_info = gen->gi_exc_state.previous_item; - gen->gi_exc_state.previous_item = NULL; - _Py_LeaveRecursiveCallPy(tstate); - _PyInterpreterFrame *gen_frame = frame; - frame = tstate->current_frame = frame->previous; - gen_frame->previous = NULL; - ((_PyThreadStateImpl *)tstate)->generator_return_kind = GENERATOR_YIELD; - FT_ATOMIC_STORE_INT8_RELEASE(gen->gi_frame_state, FRAME_SUSPENDED + oparg); - assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); - #if TIER_ONE - assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || + _PyStackRef retval; + // _MAKE_HEAP_SAFE + { + value = stack_pointer[-1]; + value = PyStackRef_MakeHeapSafe(value); + } + // _YIELD_VALUE + { + retval = value; + assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); + frame->instr_ptr++; + PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); + assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); + assert(oparg == 0 || oparg == 1); + _PyStackRef temp = retval; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + _Py_LeaveRecursiveCallPy(tstate); + _PyInterpreterFrame *gen_frame = frame; + frame = tstate->current_frame = frame->previous; + gen_frame->previous = NULL; + ((_PyThreadStateImpl *)tstate)->generator_return_kind = GENERATOR_YIELD; + FT_ATOMIC_STORE_INT8_RELEASE(gen->gi_frame_state, FRAME_SUSPENDED + oparg); + assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); + #if TIER_ONE + assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); - #endif - stack_pointer = _PyFrame_GetStackPointer(frame); - LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - value = PyStackRef_MakeHeapSafe(temp); - LLTRACE_RESUME_FRAME(); + #endif + stack_pointer = _PyFrame_GetStackPointer(frame); + LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); + value = temp; + LLTRACE_RESUME_FRAME(); + } stack_pointer[0] = value; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 2f52837f058..2b68ba4d2cd 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -88,6 +88,14 @@ dummy_func(void) { // BEGIN BYTECODES // + op(_MAKE_HEAP_SAFE, (value -- value)) { + // eliminate _MAKE_HEAP_SAFE when we *know* the value is immortal + if (sym_is_immortal(PyJitRef_Unwrap(value))) { + ADD_OP(_NOP, 0, 0); + } + value = PyJitRef_StripReferenceInfo(value); + } + op(_LOAD_FAST_CHECK, (-- value)) { value = GETLOCAL(oparg); // We guarantee this will error - just bail and don't optimize it. @@ -944,8 +952,7 @@ dummy_func(void) { } op(_RETURN_VALUE, (retval -- res)) { - // Mimics PyStackRef_MakeHeapSafe in the interpreter. - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; DEAD(retval); SAVE_STACK(); ctx->frame->stack_pointer = stack_pointer; @@ -983,8 +990,7 @@ dummy_func(void) { } op(_YIELD_VALUE, (retval -- value)) { - // Mimics PyStackRef_MakeHeapSafe in the interpreter. - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; DEAD(retval); SAVE_STACK(); ctx->frame->stack_pointer = stack_pointer; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index c35c77ed442..f996c1f6cc7 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1309,11 +1309,22 @@ break; } + case _MAKE_HEAP_SAFE: { + JitOptRef value; + value = stack_pointer[-1]; + if (sym_is_immortal(PyJitRef_Unwrap(value))) { + ADD_OP(_NOP, 0, 0); + } + value = PyJitRef_StripReferenceInfo(value); + stack_pointer[-1] = value; + break; + } + case _RETURN_VALUE: { JitOptRef retval; JitOptRef res; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; CHECK_STACK_BOUNDS(-1); stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -1385,7 +1396,7 @@ JitOptRef retval; JitOptRef value; retval = stack_pointer[-1]; - JitOptRef temp = PyJitRef_StripReferenceInfo(retval); + JitOptRef temp = retval; CHECK_STACK_BOUNDS(-1); stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); From d19de375a204c74ab5f3a28ec42335bae139033d Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Thu, 12 Mar 2026 02:08:18 +0500 Subject: [PATCH 101/775] GH-145247: Use _PyTuple_FromPair in Parser and Python (#145842) Use _PyTuple_FromPair in Parser and Python --- Parser/pegen_errors.c | 5 +++-- Python/Python-tokenize.c | 3 ++- Python/_warnings.c | 3 ++- Python/bltinmodule.c | 2 +- Python/compile.c | 3 ++- Python/hamt.c | 3 ++- Python/marshal.c | 5 ++--- Python/pylifecycle.c | 3 ++- 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 1c61524d60a..312699415ef 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -3,6 +3,7 @@ #include "pycore_pyerrors.h" // _PyErr_ProgramDecodedTextObject() #include "pycore_runtime.h" // _Py_ID() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "lexer/state.h" #include "lexer/lexer.h" #include "pegen.h" @@ -41,7 +42,7 @@ _PyPegen_raise_tokenizer_init_error(PyObject *filename) goto error; } - tuple = PyTuple_Pack(2, errstr, tmp); + tuple = _PyTuple_FromPair(errstr, tmp); Py_DECREF(tmp); if (!tuple) { goto error; @@ -393,7 +394,7 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, if (!tmp) { goto error; } - value = PyTuple_Pack(2, errstr, tmp); + value = _PyTuple_FromPair(errstr, tmp); Py_DECREF(tmp); if (!value) { goto error; diff --git a/Python/Python-tokenize.c b/Python/Python-tokenize.c index 152d61c6867..c50ff119068 100644 --- a/Python/Python-tokenize.c +++ b/Python/Python-tokenize.c @@ -1,6 +1,7 @@ #include "Python.h" #include "errcode.h" #include "internal/pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION +#include "internal/pycore_tuple.h" // _PyTuple_FromPair #include "../Parser/lexer/state.h" #include "../Parser/lexer/lexer.h" #include "../Parser/tokenizer/tokenizer.h" @@ -164,7 +165,7 @@ _tokenizer_error(tokenizeriterobject *it) goto exit; } - value = PyTuple_Pack(2, errstr, tmp); + value = _PyTuple_FromPair(errstr, tmp); if (!value) { result = -1; goto exit; diff --git a/Python/_warnings.c b/Python/_warnings.c index 0ea785772f0..6b6ac238935 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -7,6 +7,7 @@ #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_traceback.h" // _Py_DisplaySourceLine() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include @@ -634,7 +635,7 @@ update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text, if (add_zero) altkey = PyTuple_Pack(3, text, category, _PyLong_GetZero()); else - altkey = PyTuple_Pack(2, text, category); + altkey = _PyTuple_FromPair(text, category); rc = already_warned(interp, registry, altkey, 1); Py_XDECREF(altkey); diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index fc69f637202..5680e897157 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -3341,7 +3341,7 @@ zip_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) if (lz->strict) { return PyTuple_Pack(3, Py_TYPE(lz), lz->ittuple, Py_True); } - return PyTuple_Pack(2, Py_TYPE(lz), lz->ittuple); + return _PyTuple_FromPair((PyObject *)Py_TYPE(lz), lz->ittuple); } static PyObject * diff --git a/Python/compile.c b/Python/compile.c index 96779a0a219..4cf178b06ae 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -23,6 +23,7 @@ #include "pycore_runtime.h" // _Py_ID() #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_stats.h" +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include "cpython/code.h" @@ -1697,7 +1698,7 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, return NULL; } /* Allocate a copy of the instruction sequence on the heap */ - res = PyTuple_Pack(2, _PyCompile_InstrSequence(c), metadata); + res = _PyTuple_FromPair((PyObject *)_PyCompile_InstrSequence(c), metadata); finally: Py_XDECREF(metadata); diff --git a/Python/hamt.c b/Python/hamt.c index 881290a0e60..e4719e71a52 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -4,6 +4,7 @@ #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_long.h" // _PyLong_Format() #include "pycore_object.h" // _PyObject_GC_TRACK() +#include "pycore_tuple.h" // _PyTuple_FromPair #include // offsetof() @@ -2542,7 +2543,7 @@ PyTypeObject _PyHamtItems_Type = { static PyObject * hamt_iter_yield_items(PyObject *key, PyObject *val) { - return PyTuple_Pack(2, key, val); + return _PyTuple_FromPair(key, val); } PyObject * diff --git a/Python/marshal.c b/Python/marshal.c index 59db6456552..cc6a787ba75 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -14,6 +14,7 @@ #include "pycore_object.h" // _PyObject_IsUniquelyReferenced #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_setobject.h" // _PySet_NextEntryRef() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal() #include "marshal.h" // Py_MARSHAL_VERSION @@ -629,9 +630,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p) Py_DECREF(value); break; } - PyObject *pair = PyTuple_Pack(2, dump, value); - Py_DECREF(dump); - Py_DECREF(value); + PyObject *pair = _PyTuple_FromPairSteal(dump, value); if (pair == NULL) { p->error = WFERR_NOMEMORY; break; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 21d1e036d31..2b8e9a02cb6 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -30,6 +30,7 @@ #include "pycore_stats.h" // _PyStats_InterpInit() #include "pycore_sysmodule.h" // _PySys_ClearAttrString() #include "pycore_traceback.h" // _Py_DumpTracebackThreads() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_typeobject.h" // _PyTypes_InitTypes() #include "pycore_typevarobject.h" // _Py_clear_generic_types() #include "pycore_unicodeobject.h" // _PyUnicode_InitTypes() @@ -1613,7 +1614,7 @@ finalize_remove_modules(PyObject *modules, int verbose) if (weaklist != NULL) { \ PyObject *wr = PyWeakref_NewRef(mod, NULL); \ if (wr) { \ - PyObject *tup = PyTuple_Pack(2, name, wr); \ + PyObject *tup = _PyTuple_FromPair(name, wr); \ if (!tup || PyList_Append(weaklist, tup) < 0) { \ PyErr_FormatUnraisable("Exception ignored while removing modules"); \ } \ From 0dce4c6eab9dcfcb44bb2739dc60c8ac5fa1ebad Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Thu, 12 Mar 2026 07:48:43 +0100 Subject: [PATCH 102/775] gh-145254: Add thread safety annotation in docs (#145255) --- Doc/conf.py | 1 + Doc/data/threadsafety.dat | 19 ++++++ Doc/library/threadsafety.rst | 82 +++++++++++++++++++++++ Doc/tools/extensions/c_annotations.py | 93 +++++++++++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 Doc/data/threadsafety.dat diff --git a/Doc/conf.py b/Doc/conf.py index 6f66ed68c52..4ac6f6192a0 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -569,6 +569,7 @@ # Relative filename of the data files refcount_file = 'data/refcounts.dat' stable_abi_file = 'data/stable_abi.dat' +threadsafety_file = 'data/threadsafety.dat' # Options for sphinxext-opengraph # ------------------------------- diff --git a/Doc/data/threadsafety.dat b/Doc/data/threadsafety.dat new file mode 100644 index 00000000000..f063ca1360d --- /dev/null +++ b/Doc/data/threadsafety.dat @@ -0,0 +1,19 @@ +# Thread safety annotations for C API functions. +# +# Each line has the form: +# function_name : level +# +# Where level is one of: +# incompatible -- not safe even with external locking +# compatible -- safe if the caller serializes all access with external locks +# distinct -- safe on distinct objects without external synchronization +# shared -- safe for concurrent use on the same object +# atomic -- atomic +# +# Lines beginning with '#' are ignored. +# The function name must match the C domain identifier used in the documentation. + +# Synchronization primitives (Doc/c-api/synchronization.rst) +PyMutex_Lock:shared: +PyMutex_Unlock:shared: +PyMutex_IsLocked:atomic: diff --git a/Doc/library/threadsafety.rst b/Doc/library/threadsafety.rst index 5b5949d4eff..7ab5921c7ec 100644 --- a/Doc/library/threadsafety.rst +++ b/Doc/library/threadsafety.rst @@ -13,6 +13,88 @@ For general guidance on writing thread-safe code in free-threaded Python, see :ref:`freethreading-python-howto`. +.. _threadsafety-levels: + +Thread safety levels +==================== + +The C API documentation uses the following levels to describe the thread +safety guarantees of each function. The levels are listed from least to +most safe. + +.. _threadsafety-level-incompatible: + +Incompatible +------------ + +A function or operation that cannot be made safe for concurrent use even +with external synchronization. Incompatible code typically accesses +global state in an unsynchronized way and must only be called from a single +thread throughout the program's lifetime. + +Example: a function that modifies process-wide state such as signal handlers +or environment variables, where concurrent calls from any threads, even with +external locking, can conflict with the runtime or other libraries. + +.. _threadsafety-level-compatible: + +Compatible +---------- + +A function or operation that is safe to call from multiple threads +*provided* the caller supplies appropriate external synchronization, for +example by holding a :term:`lock` for the duration of each call. Without +such synchronization, concurrent calls may produce :term:`race conditions +` or :term:`data races `. + +Example: a function that reads from or writes to an object whose internal +state is not protected by a lock. Callers must ensure that no two threads +access the same object at the same time. + +.. _threadsafety-level-distinct: + +Safe on distinct objects +------------------------ + +A function or operation that is safe to call from multiple threads without +external synchronization, as long as each thread operates on a **different** +object. Two threads may call the function at the same time, but they must +not pass the same object (or objects that share underlying state) as +arguments. + +Example: a function that modifies fields of a struct using non-atomic +writes. Two threads can each call the function on their own struct +instance safely, but concurrent calls on the *same* instance require +external synchronization. + +.. _threadsafety-level-shared: + +Safe on shared objects +---------------------- + +A function or operation that is safe for concurrent use on the **same** +object. The implementation uses internal synchronization (such as +:term:`per-object locks ` or +:ref:`critical sections `) to protect shared +mutable state, so callers do not need to supply their own locking. + +Example: :c:func:`PyList_GetItemRef` can be called from multiple threads on the +same :c:type:`PyListObject` - it uses internal synchronization to serialize +access. + +.. _threadsafety-level-atomic: + +Atomic +------ + +A function or operation that appears :term:`atomic ` with +respect to other threads - it executes instantaneously from the perspective +of other threads. This is the strongest form of thread safety. + +Example: :c:func:`PyMutex_IsLocked` performs an atomic read of the mutex +state and can be called from any thread at any time. + + .. _thread-safety-list: Thread safety for list objects diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py index e04a5f144c4..58f597c2eb2 100644 --- a/Doc/tools/extensions/c_annotations.py +++ b/Doc/tools/extensions/c_annotations.py @@ -3,10 +3,12 @@ * Reference count annotations for C API functions. * Stable ABI annotations * Limited API annotations +* Thread safety annotations for C API functions. Configuration: * Set ``refcount_file`` to the path to the reference count data file. * Set ``stable_abi_file`` to the path to stable ABI list. +* Set ``threadsafety_file`` to the path to the thread safety data file. """ from __future__ import annotations @@ -48,6 +50,15 @@ class RefCountEntry: result_refs: int | None = None +@dataclasses.dataclass(frozen=True, slots=True) +class ThreadSafetyEntry: + # Name of the function. + name: str + # Thread safety level. + # One of: 'incompatible', 'compatible', 'safe'. + level: str + + @dataclasses.dataclass(frozen=True, slots=True) class StableABIEntry: # Role of the object. @@ -113,10 +124,42 @@ def read_stable_abi_data(stable_abi_file: Path) -> dict[str, StableABIEntry]: return stable_abi_data +_VALID_THREADSAFETY_LEVELS = frozenset({ + "incompatible", + "compatible", + "distinct", + "shared", + "atomic", +}) + + +def read_threadsafety_data( + threadsafety_filename: Path, +) -> dict[str, ThreadSafetyEntry]: + threadsafety_data = {} + for line in threadsafety_filename.read_text(encoding="utf8").splitlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + # Each line is of the form: function_name : level : [comment] + parts = line.split(":", 2) + if len(parts) < 2: + raise ValueError(f"Wrong field count in {line!r}") + name, level = parts[0].strip(), parts[1].strip() + if level not in _VALID_THREADSAFETY_LEVELS: + raise ValueError( + f"Unknown thread safety level {level!r} for {name!r}. " + f"Valid levels: {sorted(_VALID_THREADSAFETY_LEVELS)}" + ) + threadsafety_data[name] = ThreadSafetyEntry(name=name, level=level) + return threadsafety_data + + def add_annotations(app: Sphinx, doctree: nodes.document) -> None: state = app.env.domaindata["c_annotations"] refcount_data = state["refcount_data"] stable_abi_data = state["stable_abi_data"] + threadsafety_data = state["threadsafety_data"] for node in doctree.findall(addnodes.desc_content): par = node.parent if par["domain"] != "c": @@ -126,6 +169,12 @@ def add_annotations(app: Sphinx, doctree: nodes.document) -> None: name = par[0]["ids"][0].removeprefix("c.") objtype = par["objtype"] + # Thread safety annotation — inserted first so it appears last (bottom-most) + # among all annotations. + if entry := threadsafety_data.get(name): + annotation = _threadsafety_annotation(entry.level) + node.insert(0, annotation) + # Stable ABI annotation. if record := stable_abi_data.get(name): if ROLE_TO_OBJECT_TYPE[record.role] != objtype: @@ -256,6 +305,46 @@ def _unstable_api_annotation() -> nodes.admonition: ) +def _threadsafety_annotation(level: str) -> nodes.emphasis: + match level: + case "incompatible": + display = sphinx_gettext("Not safe to call from multiple threads.") + reftarget = "threadsafety-level-incompatible" + case "compatible": + display = sphinx_gettext( + "Safe to call from multiple threads" + " with external synchronization only." + ) + reftarget = "threadsafety-level-compatible" + case "distinct": + display = sphinx_gettext( + "Safe to call without external synchronization" + " on distinct objects." + ) + reftarget = "threadsafety-level-distinct" + case "shared": + display = sphinx_gettext( + "Safe for concurrent use on the same object." + ) + reftarget = "threadsafety-level-shared" + case "atomic": + display = sphinx_gettext("Atomic.") + reftarget = "threadsafety-level-atomic" + case _: + raise AssertionError(f"Unknown thread safety level {level!r}") + ref_node = addnodes.pending_xref( + display, + nodes.Text(display), + refdomain="std", + reftarget=reftarget, + reftype="ref", + refexplicit="True", + ) + prefix = sphinx_gettext("Thread safety:") + " " + classes = ["threadsafety", f"threadsafety-{level}"] + return nodes.emphasis("", prefix, ref_node, classes=classes) + + def _return_value_annotation(result_refs: int | None) -> nodes.emphasis: classes = ["refcount"] if result_refs is None: @@ -342,11 +431,15 @@ def init_annotations(app: Sphinx) -> None: state["stable_abi_data"] = read_stable_abi_data( Path(app.srcdir, app.config.stable_abi_file) ) + state["threadsafety_data"] = read_threadsafety_data( + Path(app.srcdir, app.config.threadsafety_file) + ) def setup(app: Sphinx) -> ExtensionMetadata: app.add_config_value("refcount_file", "", "env", types={str}) app.add_config_value("stable_abi_file", "", "env", types={str}) + app.add_config_value("threadsafety_file", "", "env", types={str}) app.add_directive("limited-api-list", LimitedAPIList) app.add_directive("corresponding-type-slot", CorrespondingTypeSlot) app.connect("builder-inited", init_annotations) From 72456309e9673019622d9d20d93c707f96d2f8e9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 12 Mar 2026 09:44:11 +0200 Subject: [PATCH 103/775] gh-143715: Deprecate incomplete initialization of struct.Struct() (GH-145580) * Struct.__new__() will require a mandatory argument (format) * Calls of __init__() method with a different format argument on initialized Struct are deprecated Co-authored-by: Sergey B Kirpichev --- Doc/deprecations/pending-removal-in-3.20.rst | 7 + Doc/whatsnew/3.15.rst | 9 + Lib/test/test_struct.py | 165 +++++++++++++- ...-01-10-16-23-21.gh-issue-143715.HZrfSA.rst | 3 + Modules/_struct.c | 211 +++++++++++++++--- Modules/clinic/_struct.c.h | 62 ++++- 6 files changed, 412 insertions(+), 45 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst diff --git a/Doc/deprecations/pending-removal-in-3.20.rst b/Doc/deprecations/pending-removal-in-3.20.rst index 8372432a34d..176e8f3f9f6 100644 --- a/Doc/deprecations/pending-removal-in-3.20.rst +++ b/Doc/deprecations/pending-removal-in-3.20.rst @@ -1,6 +1,13 @@ Pending removal in Python 3.20 ------------------------------ +* Calling the ``__new__()`` method of :class:`struct.Struct` without the + *format* argument is deprecated and will be removed in Python 3.20. Calling + :meth:`~object.__init__` method on initialized :class:`~struct.Struct` + objects is deprecated and will be removed in Python 3.20. + + (Contributed by Sergey B Kirpichev and Serhiy Storchaka in :gh:`143715`.) + * The ``__version__``, ``version`` and ``VERSION`` attributes have been deprecated in these standard library modules and will be removed in Python 3.20. Use :py:data:`sys.version_info` instead. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index e749ef2a455..c979118abd0 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1560,6 +1560,15 @@ New deprecations (Contributed by Bénédikt Tran in :gh:`134978`.) +* :mod:`struct`: + + * Calling the ``Struct.__new__()`` without required argument now is + deprecated and will be removed in Python 3.20. Calling + :meth:`~object.__init__` method on initialized :class:`~struct.Struct` + objects is deprecated and will be removed in Python 3.20. + + (Contributed by Sergey B Kirpichev and Serhiy Storchaka in :gh:`143715`.) + * ``__version__`` * The ``__version__``, ``version`` and ``VERSION`` attributes have been diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 55e2ce590a2..e3e02097b1f 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -591,27 +591,36 @@ def test_Struct_reinitialization(self): # Struct instance. This test can be used to detect the leak # when running with regrtest -L. s = struct.Struct('>h') - s.__init__('>hh') + msg = 'Re-initialization .* will not work' + with self.assertWarnsRegex(FutureWarning, msg): + s.__init__('>hh') self.assertEqual(s.format, '>hh') packed = b'\x00\x01\x00\x02' self.assertEqual(s.pack(1, 2), packed) self.assertEqual(s.unpack(packed), (1, 2)) - with self.assertRaises(UnicodeEncodeError): - s.__init__('\udc00') + s.__init__('>hh') # same format self.assertEqual(s.format, '>hh') self.assertEqual(s.pack(1, 2), packed) self.assertEqual(s.unpack(packed), (1, 2)) - with self.assertRaises(struct.error): - s.__init__('$') + with self.assertWarnsRegex(FutureWarning, msg): + with self.assertRaises(UnicodeEncodeError): + s.__init__('\udc00') + self.assertEqual(s.format, '>hh') + self.assertEqual(s.pack(1, 2), packed) + self.assertEqual(s.unpack(packed), (1, 2)) + + with self.assertWarnsRegex(FutureWarning, msg): + with self.assertRaises(struct.error): + s.__init__('$') self.assertEqual(s.format, '>hh') self.assertEqual(s.pack(1, 2), packed) self.assertEqual(s.unpack(packed), (1, 2)) def check_sizeof(self, format_str, number_of_codes): # The size of 'PyStructObject' - totalsize = support.calcobjsize('2n3P') + totalsize = support.calcobjsize('2n3P?0P') # The size taken up by the 'formatcode' dynamic array totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1) support.check_sizeof(self, struct.Struct(format_str), totalsize) @@ -809,14 +818,152 @@ def test_error_propagation(fmt_str): test_error_propagation('N') test_error_propagation('n') - def test_struct_subclass_instantiation(self): + def test_custom_struct_init(self): # Regression test for https://github.com/python/cpython/issues/112358 class MyStruct(struct.Struct): - def __init__(self): + def __init__(self, *args, **kwargs): super().__init__('>h') - my_struct = MyStruct() + my_struct = MyStruct('>h') self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct(format='>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + warnmsg = r"Different format arguments for __new__\(\) and __init__\(\) methods of Struct" + with self.assertWarnsRegex(FutureWarning, warnmsg): + my_struct = MyStruct('h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + warnmsg = r"Struct\(\) takes at most 1 argument \(2 given\)" + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct('>h', 42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct('>h', arg=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct('>h', format=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg): + my_struct = MyStruct(format='>h', arg=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + warnmsg = r"Invalid 'format' argument for Struct\.__new__\(\): " + with self.assertWarnsRegex(DeprecationWarning, warnmsg + '.*must be'): + my_struct = MyStruct(42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + '.*must be'): + my_struct = MyStruct(format=42) + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + 'bad char'): + my_struct = MyStruct('$') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + 'bad char'): + my_struct = MyStruct(format='$') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + ".*can't encode"): + my_struct = MyStruct('\udc00') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertWarnsRegex(DeprecationWarning, warnmsg + ".*can't encode"): + my_struct = MyStruct(format='\udc00') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + def test_custom_struct_new(self): + # New way, no warnings: + class MyStruct(struct.Struct): + def __new__(cls, *args, **kwargs): + return super().__new__(cls, '>h') + + for format in '>h', 'h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct(format='h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct() + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct('h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + + def test_custom_struct_new_and_init(self): + # New way, no warnings: + class MyStruct(struct.Struct): + def __new__(cls, newargs, initargs): + return super().__new__(cls, *newargs) + def __init__(self, newargs, initargs): + if initargs is not None: + super().__init__(*initargs) + + my_struct = MyStruct(('>h',), ('>h',)) + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertRaises(TypeError): + MyStruct((), ()) + with self.assertRaises(TypeError): + MyStruct(('>h',), ()) + with self.assertRaises(TypeError): + MyStruct((), ('>h',)) + with self.assertRaises(TypeError): + MyStruct((42,), ('>h',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(TypeError): + MyStruct(('>h',), (42,)) + with self.assertRaises(struct.error): + MyStruct(('$',), ('>h',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(struct.error): + MyStruct(('>h',), ('$',)) + with self.assertRaises(UnicodeEncodeError): + MyStruct(('\udc00',), ('>h',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(UnicodeEncodeError): + MyStruct(('>h',), ('\udc00',)) + with self.assertWarns(FutureWarning): + my_struct = MyStruct(('>h',), ('h') + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + my_struct = MyStruct(format='>h') + self.assertEqual(my_struct.format, '>h') + self.assertEqual(my_struct.pack(12345), b'\x30\x39') + with self.assertRaises(TypeError): + MyStruct() + with self.assertRaises(TypeError): + MyStruct(42) + with self.assertRaises(struct.error): + MyStruct('$') + with self.assertRaises(UnicodeEncodeError): + MyStruct('\udc00') + with self.assertRaises(TypeError): + MyStruct('>h', 42) + with self.assertRaises(TypeError): + MyStruct('>h', arg=42) + with self.assertRaises(TypeError): + MyStruct(arg=42) + with self.assertRaises(TypeError): + MyStruct('>h', format='>h') def test_repr(self): s = struct.Struct('=i2H') diff --git a/Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst b/Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst new file mode 100644 index 00000000000..90aae6bee83 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst @@ -0,0 +1,3 @@ +Calling the ``Struct.__new__()`` without required argument now is deprecated. +Calling :meth:`~object.__init__` method on initialized :class:`~struct.Struct` +objects is deprecated. diff --git a/Modules/_struct.c b/Modules/_struct.c index f8574322b40..7eddc9bdc38 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -70,6 +70,7 @@ typedef struct { formatcode *s_codes; PyObject *s_format; PyObject *weakreflist; /* List of weak references */ + bool init_called; } PyStructObject; #define PyStructObject_CAST(op) ((PyStructObject *)(op)) @@ -1773,24 +1774,153 @@ prepare_s(PyStructObject *self, PyObject *format) return -1; } +/* This should be moved to Struct_impl() when Struct___init__() and + * s_new() will be removed (see gh-143715 and gh-94532). */ +static int +set_format(PyStructObject *self, PyObject *format) +{ + if (PyUnicode_Check(format)) { + format = PyUnicode_AsASCIIString(format); + if (format == NULL) + return -1; + } + else if (PyBytes_Check(format)) { + Py_INCREF(format); + } + else { + PyErr_Format(PyExc_TypeError, + "Struct() argument 1 must be a str or bytes object, " + "not %T", format); + return -1; + } + if (prepare_s(self, format)) { + Py_DECREF(format); + return -1; + } + Py_DECREF(format); + return 0; +} + +/*[clinic input] +@classmethod +Struct.__new__ + + format: object + +Create a compiled struct object. + +Return a new Struct object which writes and reads binary data according +to the format string. See help(struct) for more on format strings. +[clinic start generated code]*/ + +static PyObject * +Struct_impl(PyTypeObject *type, PyObject *format) +/*[clinic end generated code: output=49468b044e334308 input=8381a9796f20f24e]*/ +{ + PyStructObject *self = (PyStructObject *)type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + self->s_format = Py_NewRef(Py_None); + self->s_codes = NULL; + self->s_size = -1; + self->s_len = -1; + self->init_called = false; + if (set_format(self, format) < 0) { + Py_DECREF(self); + return NULL; + } + return (PyObject *)self; +} + + +static int +s_init(PyObject *self, PyObject *args, PyObject *kwargs); + static PyObject * s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *self; - - assert(type != NULL); - allocfunc alloc_func = PyType_GetSlot(type, Py_tp_alloc); - assert(alloc_func != NULL); - - self = alloc_func(type, 0); - if (self != NULL) { - PyStructObject *s = (PyStructObject*)self; - s->s_format = Py_NewRef(Py_None); - s->s_codes = NULL; - s->s_size = -1; - s->s_len = -1; + if (type->tp_new != s_new) { + /* Struct.__new__() was called explicitly in a subclass' __new__(). */ + return Struct(type, args, kwds); } - return self; + + PyObject *format = NULL; + if (PyTuple_GET_SIZE(args) == 1 && (kwds == NULL || PyDict_GET_SIZE(kwds) == 0)) { + format = Py_NewRef(PyTuple_GET_ITEM(args, 0)); + } + else if (PyTuple_GET_SIZE(args) == 0 && kwds != NULL && PyDict_GET_SIZE(kwds) == 1) { + if (PyDict_GetItemStringRef(kwds, "format", &format) < 0) { + return NULL; + } + } + if (format == NULL && type->tp_init != s_init) { + Py_ssize_t nargs = PyTuple_GET_SIZE(args) + (kwds ? PyDict_GET_SIZE(kwds) : 0); + if (nargs > 1) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "Struct() takes at most 1 argument (%zd given)", nargs)) + { + Py_XDECREF(format); + return NULL; + } + } + else { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Struct() missing required argument 'format' (pos 1)", 1)) + { + Py_XDECREF(format); + return NULL; + } + } + } + + PyStructObject *self = (PyStructObject *)type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + self->s_format = Py_NewRef(Py_None); + self->s_codes = NULL; + self->s_size = -1; + self->s_len = -1; + self->init_called = false; + if (format && set_format(self, format) < 0) { + if (type->tp_init == s_init) { + /* No custom __init__() method, so __new__() should do + * all the work. */ + Py_DECREF(format); + Py_DECREF(self); + return NULL; + } + PyObject *exc = PyErr_GetRaisedException(); + Py_SETREF(self->s_format, Py_NewRef(Py_None)); + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "Invalid 'format' argument for Struct.__new__(): %S", exc)) + { + Py_DECREF(exc); + Py_DECREF(format); + Py_DECREF(self); + return NULL; + } + Py_DECREF(exc); + } + Py_XDECREF(format); + return (PyObject *)self; +} + +static bool +same_format(PyStructObject *s, PyObject *format) +{ + Py_ssize_t size = PyBytes_GET_SIZE(s->s_format); + const void *data = PyBytes_AS_STRING(s->s_format); + if (PyUnicode_Check(format) && PyUnicode_IS_ASCII(format)) { + return PyUnicode_GET_LENGTH(format) == size + && memcmp(PyUnicode_1BYTE_DATA(format), data, size) == 0; + } + if (PyBytes_Check(format)) { + return PyBytes_GET_SIZE(format) == size + && memcmp(PyBytes_AS_STRING(format), data, size) == 0; + } + return false; } /*[clinic input] @@ -1808,29 +1938,42 @@ static int Struct___init___impl(PyStructObject *self, PyObject *format) /*[clinic end generated code: output=b8e80862444e92d0 input=1af78a5f57d82cec]*/ { - int ret = 0; - - if (PyUnicode_Check(format)) { - format = PyUnicode_AsASCIIString(format); - if (format == NULL) + if (self->s_format == Py_None) { + if (set_format(self, format) < 0) { return -1; + } } - else { - Py_INCREF(format); + else if (!same_format(self, format)) { + const char *msg = self->init_called + ? "Re-initialization of Struct by calling the __init__() method " + "will not work in future Python versions" + : "Different format arguments for __new__() and __init__() " + "methods of Struct"; + if (PyErr_WarnEx(PyExc_FutureWarning, msg, 1)) { + return -1; + } + if (set_format(self, format) < 0) { + return -1; + } } + self->init_called = true; + return 0; +} - if (!PyBytes_Check(format)) { - Py_DECREF(format); - PyErr_Format(PyExc_TypeError, - "Struct() argument 1 must be a str or bytes object, " - "not %.200s", - _PyType_Name(Py_TYPE(format))); - return -1; +static int +s_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + if (!((PyStructObject *)self)->init_called + && Py_TYPE(self)->tp_init == s_init + && ((PyStructObject *)self)->s_format != Py_None) + { + /* Struct.__init__() was called implicitly. + * __new__() already did all the work. */ + ((PyStructObject *)self)->init_called = true; + return 0; } - - ret = prepare_s(self, format); - Py_DECREF(format); - return ret; + /* Struct.__init__() was called explicitly. */ + return Struct___init__(self, args, kwargs); } static int @@ -2446,10 +2589,8 @@ static PyType_Slot PyStructType_slots[] = { {Py_tp_methods, s_methods}, {Py_tp_members, s_members}, {Py_tp_getset, s_getsetlist}, - {Py_tp_init, Struct___init__}, - {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_init, s_init}, {Py_tp_new, s_new}, - {Py_tp_free, PyObject_GC_Del}, {0, 0}, }; diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index 9c9d29748fc..e75698e3ed0 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -9,6 +9,66 @@ preserve #include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +PyDoc_STRVAR(Struct__doc__, +"Struct(format)\n" +"--\n" +"\n" +"Create a compiled struct object.\n" +"\n" +"Return a new Struct object which writes and reads binary data according\n" +"to the format string. See help(struct) for more on format strings."); + +static PyObject * +Struct_impl(PyTypeObject *type, PyObject *format); + +static PyObject * +Struct(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(format), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"format", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "Struct", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *format; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!fastargs) { + goto exit; + } + format = fastargs[0]; + return_value = Struct_impl(type, format); + +exit: + return return_value; +} + PyDoc_STRVAR(Struct___init____doc__, "Struct(format)\n" "--\n" @@ -664,4 +724,4 @@ exit: return return_value; } -/*[clinic end generated code: output=09ee4ac45b7e709b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0f417d43a2a387c8 input=a9049054013a1b77]*/ From 86a0756234df7ce42fa4731c91067cb7f2e244d5 Mon Sep 17 00:00:00 2001 From: Shamil Date: Thu, 12 Mar 2026 13:46:36 +0300 Subject: [PATCH 104/775] gh-140594: Fix an out of bounds read when feeding NUL byte to PyOS_StdioReadline() (#140910) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Victor Stinner --- Lib/test/test_cmd_line.py | 8 ++++++++ .../2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst | 2 ++ Parser/myreadline.c | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 55e5f06c807..e106ac20809 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -200,6 +200,14 @@ def test_run_module_bug1764407(self): self.assertTrue(data.find(b'1 loop') != -1) self.assertTrue(data.find(b'__main__.Timer') != -1) + @support.cpython_only + def test_null_byte_in_interactive_mode(self): + # gh-140594: Fix an out of bounds read when a single NUL character + # is read from the standard input in interactive mode. + proc = spawn_python('-i') + proc.communicate(b'\x00', timeout=support.SHORT_TIMEOUT) + self.assertEqual(proc.returncode, 0) + def test_relativedir_bug46421(self): # Test `python -m unittest` with a relative directory beginning with ./ # Note: We have to switch to the project's top module's directory, as per diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst new file mode 100644 index 00000000000..aa126e7e25b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst @@ -0,0 +1,2 @@ +Fix an out of bounds read when a single NUL character is read from the standard input. +Patch by Shamil Abdulaev. diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 64e8f5383f0..ee77479ba7b 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -344,7 +344,7 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) break; } n += strlen(p + n); - } while (p[n-1] != '\n'); + } while (n == 0 || p[n-1] != '\n'); pr = (char *)PyMem_RawRealloc(p, n+1); if (pr == NULL) { From 453562a467a1f78a851ee12e7a556d1fe34f5a44 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 12 Mar 2026 10:57:59 +0000 Subject: [PATCH 105/775] GH-145692: Convert DEOPT_IFs to EXIT_IFs (GH-145751) * Convert DEOPT_IFs to EXIT_IFs for guards. Keep DEOPT_IF for intentional drops to the interpreter. * Modify BINARY_OP_SUBSCR_LIST_INT and STORE_SUBSCR_LIST_INT to handle negative indices, to keep EXIT_IFs and DEOPT_IFs in different uops --- Include/internal/pycore_opcode_metadata.h | 62 +- Include/internal/pycore_uop_ids.h | 1943 +++++++++++---------- Include/internal/pycore_uop_metadata.h | 125 +- Modules/_testinternalcapi/test_cases.c.h | 43 +- Python/bytecodes.c | 163 +- Python/executor_cases.c.h | 145 +- Python/generated_cases.c.h | 43 +- Python/optimizer_cases.c.h | 6 +- 8 files changed, 1304 insertions(+), 1226 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 09588e94282..2586ed3a529 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1096,17 +1096,17 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, - [BINARY_OP_EXTEND] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_EXTEND] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_OP_SUBSCR_DICT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [BINARY_OP_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [BINARY_OP_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_SUBSCR_LIST_SLICE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, - [BINARY_OP_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_SUBSCR_USTR_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, + [BINARY_OP_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, + [BINARY_OP_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_SUBSCR_USTR_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG }, [BINARY_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1120,24 +1120,24 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [BUILD_TUPLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [CACHE] = { true, INSTR_FMT_IX, 0 }, [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BOUND_METHOD_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_EX_NON_PY_GENERAL] = { true, INSTR_FMT_IXC, HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_EX_PY] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_FUNCTION_EX] = { true, INSTR_FMT_IXC, HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CALL_ISINSTANCE] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_ISINSTANCE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [CALL_KW_BOUND_METHOD] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [CALL_KW_NON_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_KW_PY] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [CALL_LEN] = { true, INSTR_FMT_IXC00, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_LEN] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_LIST_APPEND] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, @@ -1146,9 +1146,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [CALL_NON_PY_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_PY_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [CALL_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [CALL_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [CALL_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [CALL_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CALL_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [CHECK_EG_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CLEANUP_THROW] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, @@ -1158,7 +1158,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG }, [CONTAINS_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CONTAINS_OP_DICT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [CONTAINS_OP_SET] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [CONTAINS_OP_SET] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_PURE_FLAG }, [COPY_FREE_VARS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, @@ -1179,7 +1179,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [FORMAT_SIMPLE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [FORMAT_WITH_SPEC] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, - [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, @@ -1226,15 +1226,15 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, - [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, + [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_COMMON_CONSTANT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, @@ -1255,8 +1255,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [LOAD_SMALL_INT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [MAKE_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1283,13 +1283,13 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [SET_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [STORE_ATTR] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG }, [STORE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG }, @@ -1317,8 +1317,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [UNPACK_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [UNPACK_SEQUENCE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [UNPACK_SEQUENCE_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [WITH_EXCEPT_START] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [ANNOTATIONS_PLACEHOLDER] = { true, -1, HAS_PURE_FLAG }, @@ -1502,7 +1502,7 @@ _PyOpcode_macro_expansion[256] = { [SET_FUNCTION_ATTRIBUTE] = { .nuops = 1, .uops = { { _SET_FUNCTION_ATTRIBUTE, OPARG_SIMPLE, 0 } } }, [SET_UPDATE] = { .nuops = 1, .uops = { { _SET_UPDATE, OPARG_SIMPLE, 0 } } }, [STORE_ATTR] = { .nuops = 1, .uops = { { _STORE_ATTR, OPARG_SIMPLE, 3 } } }, - [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION_AND_LOCK, 2, 1 }, { _GUARD_DORV_NO_DICT, OPARG_SIMPLE, 3 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, + [STORE_ATTR_INSTANCE_VALUE] = { .nuops = 5, .uops = { { _LOCK_OBJECT, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION_LOCKED, 2, 1 }, { _GUARD_DORV_NO_DICT, OPARG_SIMPLE, 3 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_ATTR_SLOT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_ATTR_WITH_HINT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_WITH_HINT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 } } }, [STORE_DEREF] = { .nuops = 1, .uops = { { _STORE_DEREF, OPARG_SIMPLE, 0 } } }, diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 216436604c6..79e62edfeed 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -189,7 +189,7 @@ extern "C" { #define _GUARD_TOS_TUPLE 444 #define _GUARD_TOS_UNICODE 445 #define _GUARD_TYPE_VERSION 446 -#define _GUARD_TYPE_VERSION_AND_LOCK 447 +#define _GUARD_TYPE_VERSION_LOCKED 447 #define _HANDLE_PENDING_AND_DEOPT 448 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME @@ -286,1002 +286,1007 @@ extern "C" { #define _LOAD_SPECIAL 516 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 517 +#define _LOCK_OBJECT 517 +#define _MAKE_CALLARGS_A_TUPLE 518 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_HEAP_SAFE 518 -#define _MAKE_WARM 519 +#define _MAKE_HEAP_SAFE 519 +#define _MAKE_WARM 520 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 520 -#define _MAYBE_EXPAND_METHOD_KW 521 -#define _MONITOR_CALL 522 -#define _MONITOR_CALL_KW 523 -#define _MONITOR_JUMP_BACKWARD 524 -#define _MONITOR_RESUME 525 +#define _MAYBE_EXPAND_METHOD 521 +#define _MAYBE_EXPAND_METHOD_KW 522 +#define _MONITOR_CALL 523 +#define _MONITOR_CALL_KW 524 +#define _MONITOR_JUMP_BACKWARD 525 +#define _MONITOR_RESUME 526 #define _NOP NOP -#define _POP_CALL 526 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 527 -#define _POP_CALL_ONE 528 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 529 -#define _POP_CALL_TWO 530 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 531 +#define _POP_CALL 527 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 528 +#define _POP_CALL_ONE 529 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 530 +#define _POP_CALL_TWO 531 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 532 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 532 -#define _POP_JUMP_IF_TRUE 533 +#define _POP_JUMP_IF_FALSE 533 +#define _POP_JUMP_IF_TRUE 534 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 534 -#define _POP_TOP_INT 535 -#define _POP_TOP_LOAD_CONST_INLINE 536 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 537 -#define _POP_TOP_NOP 538 -#define _POP_TOP_UNICODE 539 -#define _POP_TWO 540 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 541 +#define _POP_TOP_FLOAT 535 +#define _POP_TOP_INT 536 +#define _POP_TOP_LOAD_CONST_INLINE 537 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 538 +#define _POP_TOP_NOP 539 +#define _POP_TOP_UNICODE 540 +#define _POP_TWO 541 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 542 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 542 +#define _PUSH_FRAME 543 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 543 -#define _PY_FRAME_EX 544 -#define _PY_FRAME_GENERAL 545 -#define _PY_FRAME_KW 546 -#define _QUICKEN_RESUME 547 -#define _RECORD_4OS 548 -#define _RECORD_BOUND_METHOD 549 -#define _RECORD_CALLABLE 550 -#define _RECORD_CODE 551 -#define _RECORD_NOS 552 -#define _RECORD_NOS_GEN_FUNC 553 -#define _RECORD_TOS 554 -#define _RECORD_TOS_TYPE 555 -#define _REPLACE_WITH_TRUE 556 +#define _PUSH_NULL_CONDITIONAL 544 +#define _PY_FRAME_EX 545 +#define _PY_FRAME_GENERAL 546 +#define _PY_FRAME_KW 547 +#define _QUICKEN_RESUME 548 +#define _RECORD_4OS 549 +#define _RECORD_BOUND_METHOD 550 +#define _RECORD_CALLABLE 551 +#define _RECORD_CODE 552 +#define _RECORD_NOS 553 +#define _RECORD_NOS_GEN_FUNC 554 +#define _RECORD_TOS 555 +#define _RECORD_TOS_TYPE 556 +#define _REPLACE_WITH_TRUE 557 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 557 -#define _SAVE_RETURN_OFFSET 558 -#define _SEND 559 -#define _SEND_GEN_FRAME 560 +#define _RETURN_VALUE 558 +#define _SAVE_RETURN_OFFSET 559 +#define _SEND 560 +#define _SEND_GEN_FRAME 561 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 561 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 562 -#define _SPILL_OR_RELOAD 563 -#define _START_EXECUTOR 564 -#define _STORE_ATTR 565 -#define _STORE_ATTR_INSTANCE_VALUE 566 -#define _STORE_ATTR_SLOT 567 -#define _STORE_ATTR_WITH_HINT 568 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 562 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 563 +#define _SPILL_OR_RELOAD 564 +#define _START_EXECUTOR 565 +#define _STORE_ATTR 566 +#define _STORE_ATTR_INSTANCE_VALUE 567 +#define _STORE_ATTR_SLOT 568 +#define _STORE_ATTR_WITH_HINT 569 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 569 -#define _STORE_SUBSCR 570 -#define _STORE_SUBSCR_DICT 571 -#define _STORE_SUBSCR_LIST_INT 572 -#define _SWAP 573 -#define _SWAP_2 574 -#define _SWAP_3 575 -#define _SWAP_FAST 576 -#define _SWAP_FAST_0 577 -#define _SWAP_FAST_1 578 -#define _SWAP_FAST_2 579 -#define _SWAP_FAST_3 580 -#define _SWAP_FAST_4 581 -#define _SWAP_FAST_5 582 -#define _SWAP_FAST_6 583 -#define _SWAP_FAST_7 584 -#define _TIER2_RESUME_CHECK 585 -#define _TO_BOOL 586 +#define _STORE_SLICE 570 +#define _STORE_SUBSCR 571 +#define _STORE_SUBSCR_DICT 572 +#define _STORE_SUBSCR_LIST_INT 573 +#define _SWAP 574 +#define _SWAP_2 575 +#define _SWAP_3 576 +#define _SWAP_FAST 577 +#define _SWAP_FAST_0 578 +#define _SWAP_FAST_1 579 +#define _SWAP_FAST_2 580 +#define _SWAP_FAST_3 581 +#define _SWAP_FAST_4 582 +#define _SWAP_FAST_5 583 +#define _SWAP_FAST_6 584 +#define _SWAP_FAST_7 585 +#define _TIER2_RESUME_CHECK 586 +#define _TO_BOOL 587 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 587 -#define _TO_BOOL_LIST 588 +#define _TO_BOOL_INT 588 +#define _TO_BOOL_LIST 589 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 589 +#define _TO_BOOL_STR 590 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 590 -#define _UNARY_NEGATIVE 591 +#define _UNARY_INVERT 591 +#define _UNARY_NEGATIVE 592 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 592 -#define _UNPACK_SEQUENCE_LIST 593 -#define _UNPACK_SEQUENCE_TUPLE 594 -#define _UNPACK_SEQUENCE_TWO_TUPLE 595 +#define _UNPACK_SEQUENCE 593 +#define _UNPACK_SEQUENCE_LIST 594 +#define _UNPACK_SEQUENCE_TUPLE 595 +#define _UNPACK_SEQUENCE_TWO_TUPLE 596 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 596 -#define MAX_UOP_ID 596 -#define _BINARY_OP_r23 597 -#define _BINARY_OP_ADD_FLOAT_r03 598 -#define _BINARY_OP_ADD_FLOAT_r13 599 -#define _BINARY_OP_ADD_FLOAT_r23 600 -#define _BINARY_OP_ADD_INT_r03 601 -#define _BINARY_OP_ADD_INT_r13 602 -#define _BINARY_OP_ADD_INT_r23 603 -#define _BINARY_OP_ADD_UNICODE_r03 604 -#define _BINARY_OP_ADD_UNICODE_r13 605 -#define _BINARY_OP_ADD_UNICODE_r23 606 -#define _BINARY_OP_EXTEND_r23 607 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 608 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 609 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 610 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 611 -#define _BINARY_OP_MULTIPLY_INT_r03 612 -#define _BINARY_OP_MULTIPLY_INT_r13 613 -#define _BINARY_OP_MULTIPLY_INT_r23 614 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 615 -#define _BINARY_OP_SUBSCR_DICT_r23 616 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 617 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 618 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 619 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 620 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 621 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 622 -#define _BINARY_OP_SUBSCR_STR_INT_r23 623 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 624 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 625 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 626 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 627 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 628 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 629 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 630 -#define _BINARY_OP_SUBTRACT_INT_r03 631 -#define _BINARY_OP_SUBTRACT_INT_r13 632 -#define _BINARY_OP_SUBTRACT_INT_r23 633 -#define _BINARY_SLICE_r31 634 -#define _BUILD_INTERPOLATION_r01 635 -#define _BUILD_LIST_r01 636 -#define _BUILD_MAP_r01 637 -#define _BUILD_SET_r01 638 -#define _BUILD_SLICE_r01 639 -#define _BUILD_STRING_r01 640 -#define _BUILD_TEMPLATE_r21 641 -#define _BUILD_TUPLE_r01 642 -#define _CALL_BUILTIN_CLASS_r01 643 -#define _CALL_BUILTIN_FAST_r01 644 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 645 -#define _CALL_BUILTIN_O_r03 646 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 647 -#define _CALL_INTRINSIC_1_r11 648 -#define _CALL_INTRINSIC_2_r21 649 -#define _CALL_ISINSTANCE_r31 650 -#define _CALL_KW_NON_PY_r11 651 -#define _CALL_LEN_r33 652 -#define _CALL_LIST_APPEND_r03 653 -#define _CALL_LIST_APPEND_r13 654 -#define _CALL_LIST_APPEND_r23 655 -#define _CALL_LIST_APPEND_r33 656 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 657 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 658 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 659 -#define _CALL_METHOD_DESCRIPTOR_O_r03 660 -#define _CALL_NON_PY_GENERAL_r01 661 -#define _CALL_STR_1_r32 662 -#define _CALL_TUPLE_1_r32 663 -#define _CALL_TYPE_1_r02 664 -#define _CALL_TYPE_1_r12 665 -#define _CALL_TYPE_1_r22 666 -#define _CALL_TYPE_1_r32 667 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 668 -#define _CHECK_ATTR_CLASS_r01 669 -#define _CHECK_ATTR_CLASS_r11 670 -#define _CHECK_ATTR_CLASS_r22 671 -#define _CHECK_ATTR_CLASS_r33 672 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 673 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 674 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 675 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 676 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 677 -#define _CHECK_EG_MATCH_r22 678 -#define _CHECK_EXC_MATCH_r22 679 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 680 -#define _CHECK_FUNCTION_VERSION_r00 681 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 682 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 683 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 684 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 685 -#define _CHECK_FUNCTION_VERSION_KW_r11 686 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 687 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 688 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 689 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 690 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 691 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 692 -#define _CHECK_IS_PY_CALLABLE_EX_r03 693 -#define _CHECK_IS_PY_CALLABLE_EX_r13 694 -#define _CHECK_IS_PY_CALLABLE_EX_r23 695 -#define _CHECK_IS_PY_CALLABLE_EX_r33 696 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 697 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 698 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 699 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 700 -#define _CHECK_METHOD_VERSION_r00 701 -#define _CHECK_METHOD_VERSION_KW_r11 702 -#define _CHECK_PEP_523_r00 703 -#define _CHECK_PEP_523_r11 704 -#define _CHECK_PEP_523_r22 705 -#define _CHECK_PEP_523_r33 706 -#define _CHECK_PERIODIC_r00 707 -#define _CHECK_PERIODIC_AT_END_r00 708 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 709 -#define _CHECK_RECURSION_REMAINING_r00 710 -#define _CHECK_RECURSION_REMAINING_r11 711 -#define _CHECK_RECURSION_REMAINING_r22 712 -#define _CHECK_RECURSION_REMAINING_r33 713 -#define _CHECK_STACK_SPACE_r00 714 -#define _CHECK_STACK_SPACE_OPERAND_r00 715 -#define _CHECK_STACK_SPACE_OPERAND_r11 716 -#define _CHECK_STACK_SPACE_OPERAND_r22 717 -#define _CHECK_STACK_SPACE_OPERAND_r33 718 -#define _CHECK_VALIDITY_r00 719 -#define _CHECK_VALIDITY_r11 720 -#define _CHECK_VALIDITY_r22 721 -#define _CHECK_VALIDITY_r33 722 -#define _COLD_DYNAMIC_EXIT_r00 723 -#define _COLD_EXIT_r00 724 -#define _COMPARE_OP_r21 725 -#define _COMPARE_OP_FLOAT_r03 726 -#define _COMPARE_OP_FLOAT_r13 727 -#define _COMPARE_OP_FLOAT_r23 728 -#define _COMPARE_OP_INT_r23 729 -#define _COMPARE_OP_STR_r23 730 -#define _CONTAINS_OP_r23 731 -#define _CONTAINS_OP_DICT_r23 732 -#define _CONTAINS_OP_SET_r23 733 -#define _CONVERT_VALUE_r11 734 -#define _COPY_r01 735 -#define _COPY_1_r02 736 -#define _COPY_1_r12 737 -#define _COPY_1_r23 738 -#define _COPY_2_r03 739 -#define _COPY_2_r13 740 -#define _COPY_2_r23 741 -#define _COPY_3_r03 742 -#define _COPY_3_r13 743 -#define _COPY_3_r23 744 -#define _COPY_3_r33 745 -#define _COPY_FREE_VARS_r00 746 -#define _COPY_FREE_VARS_r11 747 -#define _COPY_FREE_VARS_r22 748 -#define _COPY_FREE_VARS_r33 749 -#define _CREATE_INIT_FRAME_r01 750 -#define _DELETE_ATTR_r10 751 -#define _DELETE_DEREF_r00 752 -#define _DELETE_FAST_r00 753 -#define _DELETE_GLOBAL_r00 754 -#define _DELETE_NAME_r00 755 -#define _DELETE_SUBSCR_r20 756 -#define _DEOPT_r00 757 -#define _DEOPT_r10 758 -#define _DEOPT_r20 759 -#define _DEOPT_r30 760 -#define _DICT_MERGE_r10 761 -#define _DICT_UPDATE_r10 762 -#define _DO_CALL_r01 763 -#define _DO_CALL_FUNCTION_EX_r31 764 -#define _DO_CALL_KW_r11 765 -#define _DYNAMIC_EXIT_r00 766 -#define _DYNAMIC_EXIT_r10 767 -#define _DYNAMIC_EXIT_r20 768 -#define _DYNAMIC_EXIT_r30 769 -#define _END_FOR_r10 770 -#define _END_SEND_r21 771 -#define _ERROR_POP_N_r00 772 -#define _EXIT_INIT_CHECK_r10 773 -#define _EXIT_TRACE_r00 774 -#define _EXIT_TRACE_r10 775 -#define _EXIT_TRACE_r20 776 -#define _EXIT_TRACE_r30 777 -#define _EXPAND_METHOD_r00 778 -#define _EXPAND_METHOD_KW_r11 779 -#define _FATAL_ERROR_r00 780 -#define _FATAL_ERROR_r11 781 -#define _FATAL_ERROR_r22 782 -#define _FATAL_ERROR_r33 783 -#define _FORMAT_SIMPLE_r11 784 -#define _FORMAT_WITH_SPEC_r21 785 -#define _FOR_ITER_r23 786 -#define _FOR_ITER_GEN_FRAME_r03 787 -#define _FOR_ITER_GEN_FRAME_r13 788 -#define _FOR_ITER_GEN_FRAME_r23 789 -#define _FOR_ITER_TIER_TWO_r23 790 -#define _GET_AITER_r11 791 -#define _GET_ANEXT_r12 792 -#define _GET_AWAITABLE_r11 793 -#define _GET_ITER_r12 794 -#define _GET_LEN_r12 795 -#define _GET_YIELD_FROM_ITER_r11 796 -#define _GUARD_BINARY_OP_EXTEND_r22 797 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 798 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 799 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 800 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 801 -#define _GUARD_BIT_IS_SET_POP_r00 802 -#define _GUARD_BIT_IS_SET_POP_r10 803 -#define _GUARD_BIT_IS_SET_POP_r21 804 -#define _GUARD_BIT_IS_SET_POP_r32 805 -#define _GUARD_BIT_IS_SET_POP_4_r00 806 -#define _GUARD_BIT_IS_SET_POP_4_r10 807 -#define _GUARD_BIT_IS_SET_POP_4_r21 808 -#define _GUARD_BIT_IS_SET_POP_4_r32 809 -#define _GUARD_BIT_IS_SET_POP_5_r00 810 -#define _GUARD_BIT_IS_SET_POP_5_r10 811 -#define _GUARD_BIT_IS_SET_POP_5_r21 812 -#define _GUARD_BIT_IS_SET_POP_5_r32 813 -#define _GUARD_BIT_IS_SET_POP_6_r00 814 -#define _GUARD_BIT_IS_SET_POP_6_r10 815 -#define _GUARD_BIT_IS_SET_POP_6_r21 816 -#define _GUARD_BIT_IS_SET_POP_6_r32 817 -#define _GUARD_BIT_IS_SET_POP_7_r00 818 -#define _GUARD_BIT_IS_SET_POP_7_r10 819 -#define _GUARD_BIT_IS_SET_POP_7_r21 820 -#define _GUARD_BIT_IS_SET_POP_7_r32 821 -#define _GUARD_BIT_IS_UNSET_POP_r00 822 -#define _GUARD_BIT_IS_UNSET_POP_r10 823 -#define _GUARD_BIT_IS_UNSET_POP_r21 824 -#define _GUARD_BIT_IS_UNSET_POP_r32 825 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 826 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 827 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 828 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 829 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 830 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 831 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 832 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 833 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 834 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 835 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 836 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 837 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 838 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 839 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 840 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 841 -#define _GUARD_CALLABLE_ISINSTANCE_r03 842 -#define _GUARD_CALLABLE_ISINSTANCE_r13 843 -#define _GUARD_CALLABLE_ISINSTANCE_r23 844 -#define _GUARD_CALLABLE_ISINSTANCE_r33 845 -#define _GUARD_CALLABLE_LEN_r03 846 -#define _GUARD_CALLABLE_LEN_r13 847 -#define _GUARD_CALLABLE_LEN_r23 848 -#define _GUARD_CALLABLE_LEN_r33 849 -#define _GUARD_CALLABLE_LIST_APPEND_r03 850 -#define _GUARD_CALLABLE_LIST_APPEND_r13 851 -#define _GUARD_CALLABLE_LIST_APPEND_r23 852 -#define _GUARD_CALLABLE_LIST_APPEND_r33 853 -#define _GUARD_CALLABLE_STR_1_r03 854 -#define _GUARD_CALLABLE_STR_1_r13 855 -#define _GUARD_CALLABLE_STR_1_r23 856 -#define _GUARD_CALLABLE_STR_1_r33 857 -#define _GUARD_CALLABLE_TUPLE_1_r03 858 -#define _GUARD_CALLABLE_TUPLE_1_r13 859 -#define _GUARD_CALLABLE_TUPLE_1_r23 860 -#define _GUARD_CALLABLE_TUPLE_1_r33 861 -#define _GUARD_CALLABLE_TYPE_1_r03 862 -#define _GUARD_CALLABLE_TYPE_1_r13 863 -#define _GUARD_CALLABLE_TYPE_1_r23 864 -#define _GUARD_CALLABLE_TYPE_1_r33 865 -#define _GUARD_CODE_VERSION_r00 866 -#define _GUARD_CODE_VERSION_r11 867 -#define _GUARD_CODE_VERSION_r22 868 -#define _GUARD_CODE_VERSION_r33 869 -#define _GUARD_DORV_NO_DICT_r01 870 -#define _GUARD_DORV_NO_DICT_r11 871 -#define _GUARD_DORV_NO_DICT_r22 872 -#define _GUARD_DORV_NO_DICT_r33 873 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 874 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 875 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 876 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 877 -#define _GUARD_GLOBALS_VERSION_r00 878 -#define _GUARD_GLOBALS_VERSION_r11 879 -#define _GUARD_GLOBALS_VERSION_r22 880 -#define _GUARD_GLOBALS_VERSION_r33 881 -#define _GUARD_IP_RETURN_GENERATOR_r00 882 -#define _GUARD_IP_RETURN_GENERATOR_r11 883 -#define _GUARD_IP_RETURN_GENERATOR_r22 884 -#define _GUARD_IP_RETURN_GENERATOR_r33 885 -#define _GUARD_IP_RETURN_VALUE_r00 886 -#define _GUARD_IP_RETURN_VALUE_r11 887 -#define _GUARD_IP_RETURN_VALUE_r22 888 -#define _GUARD_IP_RETURN_VALUE_r33 889 -#define _GUARD_IP_YIELD_VALUE_r00 890 -#define _GUARD_IP_YIELD_VALUE_r11 891 -#define _GUARD_IP_YIELD_VALUE_r22 892 -#define _GUARD_IP_YIELD_VALUE_r33 893 -#define _GUARD_IP__PUSH_FRAME_r00 894 -#define _GUARD_IP__PUSH_FRAME_r11 895 -#define _GUARD_IP__PUSH_FRAME_r22 896 -#define _GUARD_IP__PUSH_FRAME_r33 897 -#define _GUARD_IS_FALSE_POP_r00 898 -#define _GUARD_IS_FALSE_POP_r10 899 -#define _GUARD_IS_FALSE_POP_r21 900 -#define _GUARD_IS_FALSE_POP_r32 901 -#define _GUARD_IS_NONE_POP_r00 902 -#define _GUARD_IS_NONE_POP_r10 903 -#define _GUARD_IS_NONE_POP_r21 904 -#define _GUARD_IS_NONE_POP_r32 905 -#define _GUARD_IS_NOT_NONE_POP_r10 906 -#define _GUARD_IS_TRUE_POP_r00 907 -#define _GUARD_IS_TRUE_POP_r10 908 -#define _GUARD_IS_TRUE_POP_r21 909 -#define _GUARD_IS_TRUE_POP_r32 910 -#define _GUARD_KEYS_VERSION_r01 911 -#define _GUARD_KEYS_VERSION_r11 912 -#define _GUARD_KEYS_VERSION_r22 913 -#define _GUARD_KEYS_VERSION_r33 914 -#define _GUARD_NOS_ANY_DICT_r02 915 -#define _GUARD_NOS_ANY_DICT_r12 916 -#define _GUARD_NOS_ANY_DICT_r22 917 -#define _GUARD_NOS_ANY_DICT_r33 918 -#define _GUARD_NOS_COMPACT_ASCII_r02 919 -#define _GUARD_NOS_COMPACT_ASCII_r12 920 -#define _GUARD_NOS_COMPACT_ASCII_r22 921 -#define _GUARD_NOS_COMPACT_ASCII_r33 922 -#define _GUARD_NOS_DICT_r02 923 -#define _GUARD_NOS_DICT_r12 924 -#define _GUARD_NOS_DICT_r22 925 -#define _GUARD_NOS_DICT_r33 926 -#define _GUARD_NOS_FLOAT_r02 927 -#define _GUARD_NOS_FLOAT_r12 928 -#define _GUARD_NOS_FLOAT_r22 929 -#define _GUARD_NOS_FLOAT_r33 930 -#define _GUARD_NOS_INT_r02 931 -#define _GUARD_NOS_INT_r12 932 -#define _GUARD_NOS_INT_r22 933 -#define _GUARD_NOS_INT_r33 934 -#define _GUARD_NOS_LIST_r02 935 -#define _GUARD_NOS_LIST_r12 936 -#define _GUARD_NOS_LIST_r22 937 -#define _GUARD_NOS_LIST_r33 938 -#define _GUARD_NOS_NOT_NULL_r02 939 -#define _GUARD_NOS_NOT_NULL_r12 940 -#define _GUARD_NOS_NOT_NULL_r22 941 -#define _GUARD_NOS_NOT_NULL_r33 942 -#define _GUARD_NOS_NULL_r02 943 -#define _GUARD_NOS_NULL_r12 944 -#define _GUARD_NOS_NULL_r22 945 -#define _GUARD_NOS_NULL_r33 946 -#define _GUARD_NOS_OVERFLOWED_r02 947 -#define _GUARD_NOS_OVERFLOWED_r12 948 -#define _GUARD_NOS_OVERFLOWED_r22 949 -#define _GUARD_NOS_OVERFLOWED_r33 950 -#define _GUARD_NOS_TUPLE_r02 951 -#define _GUARD_NOS_TUPLE_r12 952 -#define _GUARD_NOS_TUPLE_r22 953 -#define _GUARD_NOS_TUPLE_r33 954 -#define _GUARD_NOS_UNICODE_r02 955 -#define _GUARD_NOS_UNICODE_r12 956 -#define _GUARD_NOS_UNICODE_r22 957 -#define _GUARD_NOS_UNICODE_r33 958 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 959 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 960 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 961 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 962 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 963 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 964 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 965 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 966 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 967 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 968 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 969 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 970 -#define _GUARD_THIRD_NULL_r03 971 -#define _GUARD_THIRD_NULL_r13 972 -#define _GUARD_THIRD_NULL_r23 973 -#define _GUARD_THIRD_NULL_r33 974 -#define _GUARD_TOS_ANY_DICT_r01 975 -#define _GUARD_TOS_ANY_DICT_r11 976 -#define _GUARD_TOS_ANY_DICT_r22 977 -#define _GUARD_TOS_ANY_DICT_r33 978 -#define _GUARD_TOS_ANY_SET_r01 979 -#define _GUARD_TOS_ANY_SET_r11 980 -#define _GUARD_TOS_ANY_SET_r22 981 -#define _GUARD_TOS_ANY_SET_r33 982 -#define _GUARD_TOS_DICT_r01 983 -#define _GUARD_TOS_DICT_r11 984 -#define _GUARD_TOS_DICT_r22 985 -#define _GUARD_TOS_DICT_r33 986 -#define _GUARD_TOS_FLOAT_r01 987 -#define _GUARD_TOS_FLOAT_r11 988 -#define _GUARD_TOS_FLOAT_r22 989 -#define _GUARD_TOS_FLOAT_r33 990 -#define _GUARD_TOS_FROZENDICT_r01 991 -#define _GUARD_TOS_FROZENDICT_r11 992 -#define _GUARD_TOS_FROZENDICT_r22 993 -#define _GUARD_TOS_FROZENDICT_r33 994 -#define _GUARD_TOS_FROZENSET_r01 995 -#define _GUARD_TOS_FROZENSET_r11 996 -#define _GUARD_TOS_FROZENSET_r22 997 -#define _GUARD_TOS_FROZENSET_r33 998 -#define _GUARD_TOS_INT_r01 999 -#define _GUARD_TOS_INT_r11 1000 -#define _GUARD_TOS_INT_r22 1001 -#define _GUARD_TOS_INT_r33 1002 -#define _GUARD_TOS_LIST_r01 1003 -#define _GUARD_TOS_LIST_r11 1004 -#define _GUARD_TOS_LIST_r22 1005 -#define _GUARD_TOS_LIST_r33 1006 -#define _GUARD_TOS_OVERFLOWED_r01 1007 -#define _GUARD_TOS_OVERFLOWED_r11 1008 -#define _GUARD_TOS_OVERFLOWED_r22 1009 -#define _GUARD_TOS_OVERFLOWED_r33 1010 -#define _GUARD_TOS_SET_r01 1011 -#define _GUARD_TOS_SET_r11 1012 -#define _GUARD_TOS_SET_r22 1013 -#define _GUARD_TOS_SET_r33 1014 -#define _GUARD_TOS_SLICE_r01 1015 -#define _GUARD_TOS_SLICE_r11 1016 -#define _GUARD_TOS_SLICE_r22 1017 -#define _GUARD_TOS_SLICE_r33 1018 -#define _GUARD_TOS_TUPLE_r01 1019 -#define _GUARD_TOS_TUPLE_r11 1020 -#define _GUARD_TOS_TUPLE_r22 1021 -#define _GUARD_TOS_TUPLE_r33 1022 -#define _GUARD_TOS_UNICODE_r01 1023 -#define _GUARD_TOS_UNICODE_r11 1024 -#define _GUARD_TOS_UNICODE_r22 1025 -#define _GUARD_TOS_UNICODE_r33 1026 -#define _GUARD_TYPE_VERSION_r01 1027 -#define _GUARD_TYPE_VERSION_r11 1028 -#define _GUARD_TYPE_VERSION_r22 1029 -#define _GUARD_TYPE_VERSION_r33 1030 -#define _GUARD_TYPE_VERSION_AND_LOCK_r01 1031 -#define _GUARD_TYPE_VERSION_AND_LOCK_r11 1032 -#define _GUARD_TYPE_VERSION_AND_LOCK_r22 1033 -#define _GUARD_TYPE_VERSION_AND_LOCK_r33 1034 -#define _HANDLE_PENDING_AND_DEOPT_r00 1035 -#define _HANDLE_PENDING_AND_DEOPT_r10 1036 -#define _HANDLE_PENDING_AND_DEOPT_r20 1037 -#define _HANDLE_PENDING_AND_DEOPT_r30 1038 -#define _IMPORT_FROM_r12 1039 -#define _IMPORT_NAME_r21 1040 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1041 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1042 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1043 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1044 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1045 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1046 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1047 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1048 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1049 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1050 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1051 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1052 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1053 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1054 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1055 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1056 -#define _INSERT_NULL_r10 1057 -#define _INSTRUMENTED_FOR_ITER_r23 1058 -#define _INSTRUMENTED_INSTRUCTION_r00 1059 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1060 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1061 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1062 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1063 -#define _INSTRUMENTED_LINE_r00 1064 -#define _INSTRUMENTED_NOT_TAKEN_r00 1065 -#define _INSTRUMENTED_NOT_TAKEN_r11 1066 -#define _INSTRUMENTED_NOT_TAKEN_r22 1067 -#define _INSTRUMENTED_NOT_TAKEN_r33 1068 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1069 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1070 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1071 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1072 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1073 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1074 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1075 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1076 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1077 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1078 -#define _IS_NONE_r11 1079 -#define _IS_OP_r03 1080 -#define _IS_OP_r13 1081 -#define _IS_OP_r23 1082 -#define _ITER_CHECK_LIST_r02 1083 -#define _ITER_CHECK_LIST_r12 1084 -#define _ITER_CHECK_LIST_r22 1085 -#define _ITER_CHECK_LIST_r33 1086 -#define _ITER_CHECK_RANGE_r02 1087 -#define _ITER_CHECK_RANGE_r12 1088 -#define _ITER_CHECK_RANGE_r22 1089 -#define _ITER_CHECK_RANGE_r33 1090 -#define _ITER_CHECK_TUPLE_r02 1091 -#define _ITER_CHECK_TUPLE_r12 1092 -#define _ITER_CHECK_TUPLE_r22 1093 -#define _ITER_CHECK_TUPLE_r33 1094 -#define _ITER_JUMP_LIST_r02 1095 -#define _ITER_JUMP_LIST_r12 1096 -#define _ITER_JUMP_LIST_r22 1097 -#define _ITER_JUMP_LIST_r33 1098 -#define _ITER_JUMP_RANGE_r02 1099 -#define _ITER_JUMP_RANGE_r12 1100 -#define _ITER_JUMP_RANGE_r22 1101 -#define _ITER_JUMP_RANGE_r33 1102 -#define _ITER_JUMP_TUPLE_r02 1103 -#define _ITER_JUMP_TUPLE_r12 1104 -#define _ITER_JUMP_TUPLE_r22 1105 -#define _ITER_JUMP_TUPLE_r33 1106 -#define _ITER_NEXT_LIST_r23 1107 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1108 -#define _ITER_NEXT_RANGE_r03 1109 -#define _ITER_NEXT_RANGE_r13 1110 -#define _ITER_NEXT_RANGE_r23 1111 -#define _ITER_NEXT_TUPLE_r03 1112 -#define _ITER_NEXT_TUPLE_r13 1113 -#define _ITER_NEXT_TUPLE_r23 1114 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1115 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1116 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1117 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1118 -#define _JUMP_TO_TOP_r00 1119 -#define _LIST_APPEND_r10 1120 -#define _LIST_EXTEND_r10 1121 -#define _LOAD_ATTR_r10 1122 -#define _LOAD_ATTR_CLASS_r11 1123 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1124 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1125 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1126 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1127 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1128 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1129 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1130 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1131 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1132 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1133 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1134 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1135 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1136 -#define _LOAD_ATTR_MODULE_r12 1137 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1138 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1139 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1140 -#define _LOAD_ATTR_SLOT_r02 1141 -#define _LOAD_ATTR_SLOT_r12 1142 -#define _LOAD_ATTR_SLOT_r23 1143 -#define _LOAD_ATTR_WITH_HINT_r12 1144 -#define _LOAD_BUILD_CLASS_r01 1145 -#define _LOAD_BYTECODE_r00 1146 -#define _LOAD_COMMON_CONSTANT_r01 1147 -#define _LOAD_COMMON_CONSTANT_r12 1148 -#define _LOAD_COMMON_CONSTANT_r23 1149 -#define _LOAD_CONST_r01 1150 -#define _LOAD_CONST_r12 1151 -#define _LOAD_CONST_r23 1152 -#define _LOAD_CONST_INLINE_r01 1153 -#define _LOAD_CONST_INLINE_r12 1154 -#define _LOAD_CONST_INLINE_r23 1155 -#define _LOAD_CONST_INLINE_BORROW_r01 1156 -#define _LOAD_CONST_INLINE_BORROW_r12 1157 -#define _LOAD_CONST_INLINE_BORROW_r23 1158 -#define _LOAD_CONST_UNDER_INLINE_r02 1159 -#define _LOAD_CONST_UNDER_INLINE_r12 1160 -#define _LOAD_CONST_UNDER_INLINE_r23 1161 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1162 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1163 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1164 -#define _LOAD_DEREF_r01 1165 -#define _LOAD_FAST_r01 1166 -#define _LOAD_FAST_r12 1167 -#define _LOAD_FAST_r23 1168 -#define _LOAD_FAST_0_r01 1169 -#define _LOAD_FAST_0_r12 1170 -#define _LOAD_FAST_0_r23 1171 -#define _LOAD_FAST_1_r01 1172 -#define _LOAD_FAST_1_r12 1173 -#define _LOAD_FAST_1_r23 1174 -#define _LOAD_FAST_2_r01 1175 -#define _LOAD_FAST_2_r12 1176 -#define _LOAD_FAST_2_r23 1177 -#define _LOAD_FAST_3_r01 1178 -#define _LOAD_FAST_3_r12 1179 -#define _LOAD_FAST_3_r23 1180 -#define _LOAD_FAST_4_r01 1181 -#define _LOAD_FAST_4_r12 1182 -#define _LOAD_FAST_4_r23 1183 -#define _LOAD_FAST_5_r01 1184 -#define _LOAD_FAST_5_r12 1185 -#define _LOAD_FAST_5_r23 1186 -#define _LOAD_FAST_6_r01 1187 -#define _LOAD_FAST_6_r12 1188 -#define _LOAD_FAST_6_r23 1189 -#define _LOAD_FAST_7_r01 1190 -#define _LOAD_FAST_7_r12 1191 -#define _LOAD_FAST_7_r23 1192 -#define _LOAD_FAST_AND_CLEAR_r01 1193 -#define _LOAD_FAST_AND_CLEAR_r12 1194 -#define _LOAD_FAST_AND_CLEAR_r23 1195 -#define _LOAD_FAST_BORROW_r01 1196 -#define _LOAD_FAST_BORROW_r12 1197 -#define _LOAD_FAST_BORROW_r23 1198 -#define _LOAD_FAST_BORROW_0_r01 1199 -#define _LOAD_FAST_BORROW_0_r12 1200 -#define _LOAD_FAST_BORROW_0_r23 1201 -#define _LOAD_FAST_BORROW_1_r01 1202 -#define _LOAD_FAST_BORROW_1_r12 1203 -#define _LOAD_FAST_BORROW_1_r23 1204 -#define _LOAD_FAST_BORROW_2_r01 1205 -#define _LOAD_FAST_BORROW_2_r12 1206 -#define _LOAD_FAST_BORROW_2_r23 1207 -#define _LOAD_FAST_BORROW_3_r01 1208 -#define _LOAD_FAST_BORROW_3_r12 1209 -#define _LOAD_FAST_BORROW_3_r23 1210 -#define _LOAD_FAST_BORROW_4_r01 1211 -#define _LOAD_FAST_BORROW_4_r12 1212 -#define _LOAD_FAST_BORROW_4_r23 1213 -#define _LOAD_FAST_BORROW_5_r01 1214 -#define _LOAD_FAST_BORROW_5_r12 1215 -#define _LOAD_FAST_BORROW_5_r23 1216 -#define _LOAD_FAST_BORROW_6_r01 1217 -#define _LOAD_FAST_BORROW_6_r12 1218 -#define _LOAD_FAST_BORROW_6_r23 1219 -#define _LOAD_FAST_BORROW_7_r01 1220 -#define _LOAD_FAST_BORROW_7_r12 1221 -#define _LOAD_FAST_BORROW_7_r23 1222 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1223 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1224 -#define _LOAD_FAST_CHECK_r01 1225 -#define _LOAD_FAST_CHECK_r12 1226 -#define _LOAD_FAST_CHECK_r23 1227 -#define _LOAD_FAST_LOAD_FAST_r02 1228 -#define _LOAD_FAST_LOAD_FAST_r13 1229 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1230 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1231 -#define _LOAD_GLOBAL_r00 1232 -#define _LOAD_GLOBAL_BUILTINS_r01 1233 -#define _LOAD_GLOBAL_MODULE_r01 1234 -#define _LOAD_LOCALS_r01 1235 -#define _LOAD_LOCALS_r12 1236 -#define _LOAD_LOCALS_r23 1237 -#define _LOAD_NAME_r01 1238 -#define _LOAD_SMALL_INT_r01 1239 -#define _LOAD_SMALL_INT_r12 1240 -#define _LOAD_SMALL_INT_r23 1241 -#define _LOAD_SMALL_INT_0_r01 1242 -#define _LOAD_SMALL_INT_0_r12 1243 -#define _LOAD_SMALL_INT_0_r23 1244 -#define _LOAD_SMALL_INT_1_r01 1245 -#define _LOAD_SMALL_INT_1_r12 1246 -#define _LOAD_SMALL_INT_1_r23 1247 -#define _LOAD_SMALL_INT_2_r01 1248 -#define _LOAD_SMALL_INT_2_r12 1249 -#define _LOAD_SMALL_INT_2_r23 1250 -#define _LOAD_SMALL_INT_3_r01 1251 -#define _LOAD_SMALL_INT_3_r12 1252 -#define _LOAD_SMALL_INT_3_r23 1253 -#define _LOAD_SPECIAL_r00 1254 -#define _LOAD_SUPER_ATTR_ATTR_r31 1255 -#define _LOAD_SUPER_ATTR_METHOD_r32 1256 -#define _MAKE_CALLARGS_A_TUPLE_r33 1257 -#define _MAKE_CELL_r00 1258 -#define _MAKE_FUNCTION_r11 1259 -#define _MAKE_HEAP_SAFE_r01 1260 -#define _MAKE_HEAP_SAFE_r11 1261 -#define _MAKE_HEAP_SAFE_r22 1262 -#define _MAKE_HEAP_SAFE_r33 1263 -#define _MAKE_WARM_r00 1264 -#define _MAKE_WARM_r11 1265 -#define _MAKE_WARM_r22 1266 -#define _MAKE_WARM_r33 1267 -#define _MAP_ADD_r20 1268 -#define _MATCH_CLASS_r31 1269 -#define _MATCH_KEYS_r23 1270 -#define _MATCH_MAPPING_r02 1271 -#define _MATCH_MAPPING_r12 1272 -#define _MATCH_MAPPING_r23 1273 -#define _MATCH_SEQUENCE_r02 1274 -#define _MATCH_SEQUENCE_r12 1275 -#define _MATCH_SEQUENCE_r23 1276 -#define _MAYBE_EXPAND_METHOD_r00 1277 -#define _MAYBE_EXPAND_METHOD_KW_r11 1278 -#define _MONITOR_CALL_r00 1279 -#define _MONITOR_CALL_KW_r11 1280 -#define _MONITOR_JUMP_BACKWARD_r00 1281 -#define _MONITOR_JUMP_BACKWARD_r11 1282 -#define _MONITOR_JUMP_BACKWARD_r22 1283 -#define _MONITOR_JUMP_BACKWARD_r33 1284 -#define _MONITOR_RESUME_r00 1285 -#define _NOP_r00 1286 -#define _NOP_r11 1287 -#define _NOP_r22 1288 -#define _NOP_r33 1289 -#define _POP_CALL_r20 1290 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1291 -#define _POP_CALL_ONE_r30 1292 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1293 -#define _POP_CALL_TWO_r30 1294 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1295 -#define _POP_EXCEPT_r10 1296 -#define _POP_ITER_r20 1297 -#define _POP_JUMP_IF_FALSE_r00 1298 -#define _POP_JUMP_IF_FALSE_r10 1299 -#define _POP_JUMP_IF_FALSE_r21 1300 -#define _POP_JUMP_IF_FALSE_r32 1301 -#define _POP_JUMP_IF_TRUE_r00 1302 -#define _POP_JUMP_IF_TRUE_r10 1303 -#define _POP_JUMP_IF_TRUE_r21 1304 -#define _POP_JUMP_IF_TRUE_r32 1305 -#define _POP_TOP_r10 1306 -#define _POP_TOP_FLOAT_r00 1307 -#define _POP_TOP_FLOAT_r10 1308 -#define _POP_TOP_FLOAT_r21 1309 -#define _POP_TOP_FLOAT_r32 1310 -#define _POP_TOP_INT_r00 1311 -#define _POP_TOP_INT_r10 1312 -#define _POP_TOP_INT_r21 1313 -#define _POP_TOP_INT_r32 1314 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1315 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1316 -#define _POP_TOP_NOP_r00 1317 -#define _POP_TOP_NOP_r10 1318 -#define _POP_TOP_NOP_r21 1319 -#define _POP_TOP_NOP_r32 1320 -#define _POP_TOP_UNICODE_r00 1321 -#define _POP_TOP_UNICODE_r10 1322 -#define _POP_TOP_UNICODE_r21 1323 -#define _POP_TOP_UNICODE_r32 1324 -#define _POP_TWO_r20 1325 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1326 -#define _PUSH_EXC_INFO_r02 1327 -#define _PUSH_EXC_INFO_r12 1328 -#define _PUSH_EXC_INFO_r23 1329 -#define _PUSH_FRAME_r10 1330 -#define _PUSH_NULL_r01 1331 -#define _PUSH_NULL_r12 1332 -#define _PUSH_NULL_r23 1333 -#define _PUSH_NULL_CONDITIONAL_r00 1334 -#define _PY_FRAME_EX_r31 1335 -#define _PY_FRAME_GENERAL_r01 1336 -#define _PY_FRAME_KW_r11 1337 -#define _QUICKEN_RESUME_r00 1338 -#define _QUICKEN_RESUME_r11 1339 -#define _QUICKEN_RESUME_r22 1340 -#define _QUICKEN_RESUME_r33 1341 -#define _REPLACE_WITH_TRUE_r02 1342 -#define _REPLACE_WITH_TRUE_r12 1343 -#define _REPLACE_WITH_TRUE_r23 1344 -#define _RESUME_CHECK_r00 1345 -#define _RESUME_CHECK_r11 1346 -#define _RESUME_CHECK_r22 1347 -#define _RESUME_CHECK_r33 1348 -#define _RETURN_GENERATOR_r01 1349 -#define _RETURN_VALUE_r11 1350 -#define _SAVE_RETURN_OFFSET_r00 1351 -#define _SAVE_RETURN_OFFSET_r11 1352 -#define _SAVE_RETURN_OFFSET_r22 1353 -#define _SAVE_RETURN_OFFSET_r33 1354 -#define _SEND_r22 1355 -#define _SEND_GEN_FRAME_r22 1356 -#define _SETUP_ANNOTATIONS_r00 1357 -#define _SET_ADD_r10 1358 -#define _SET_FUNCTION_ATTRIBUTE_r01 1359 -#define _SET_FUNCTION_ATTRIBUTE_r11 1360 -#define _SET_FUNCTION_ATTRIBUTE_r21 1361 -#define _SET_FUNCTION_ATTRIBUTE_r32 1362 -#define _SET_IP_r00 1363 -#define _SET_IP_r11 1364 -#define _SET_IP_r22 1365 -#define _SET_IP_r33 1366 -#define _SET_UPDATE_r10 1367 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1368 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1369 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1370 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1371 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1372 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1373 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1374 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1375 -#define _SPILL_OR_RELOAD_r01 1376 -#define _SPILL_OR_RELOAD_r02 1377 -#define _SPILL_OR_RELOAD_r03 1378 -#define _SPILL_OR_RELOAD_r10 1379 -#define _SPILL_OR_RELOAD_r12 1380 -#define _SPILL_OR_RELOAD_r13 1381 -#define _SPILL_OR_RELOAD_r20 1382 -#define _SPILL_OR_RELOAD_r21 1383 -#define _SPILL_OR_RELOAD_r23 1384 -#define _SPILL_OR_RELOAD_r30 1385 -#define _SPILL_OR_RELOAD_r31 1386 -#define _SPILL_OR_RELOAD_r32 1387 -#define _START_EXECUTOR_r00 1388 -#define _STORE_ATTR_r20 1389 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1390 -#define _STORE_ATTR_SLOT_r21 1391 -#define _STORE_ATTR_WITH_HINT_r21 1392 -#define _STORE_DEREF_r10 1393 -#define _STORE_FAST_LOAD_FAST_r11 1394 -#define _STORE_FAST_STORE_FAST_r20 1395 -#define _STORE_GLOBAL_r10 1396 -#define _STORE_NAME_r10 1397 -#define _STORE_SLICE_r30 1398 -#define _STORE_SUBSCR_r30 1399 -#define _STORE_SUBSCR_DICT_r31 1400 -#define _STORE_SUBSCR_LIST_INT_r32 1401 -#define _SWAP_r11 1402 -#define _SWAP_2_r02 1403 -#define _SWAP_2_r12 1404 -#define _SWAP_2_r22 1405 -#define _SWAP_2_r33 1406 -#define _SWAP_3_r03 1407 -#define _SWAP_3_r13 1408 -#define _SWAP_3_r23 1409 -#define _SWAP_3_r33 1410 -#define _SWAP_FAST_r01 1411 -#define _SWAP_FAST_r11 1412 -#define _SWAP_FAST_r22 1413 -#define _SWAP_FAST_r33 1414 -#define _SWAP_FAST_0_r01 1415 -#define _SWAP_FAST_0_r11 1416 -#define _SWAP_FAST_0_r22 1417 -#define _SWAP_FAST_0_r33 1418 -#define _SWAP_FAST_1_r01 1419 -#define _SWAP_FAST_1_r11 1420 -#define _SWAP_FAST_1_r22 1421 -#define _SWAP_FAST_1_r33 1422 -#define _SWAP_FAST_2_r01 1423 -#define _SWAP_FAST_2_r11 1424 -#define _SWAP_FAST_2_r22 1425 -#define _SWAP_FAST_2_r33 1426 -#define _SWAP_FAST_3_r01 1427 -#define _SWAP_FAST_3_r11 1428 -#define _SWAP_FAST_3_r22 1429 -#define _SWAP_FAST_3_r33 1430 -#define _SWAP_FAST_4_r01 1431 -#define _SWAP_FAST_4_r11 1432 -#define _SWAP_FAST_4_r22 1433 -#define _SWAP_FAST_4_r33 1434 -#define _SWAP_FAST_5_r01 1435 -#define _SWAP_FAST_5_r11 1436 -#define _SWAP_FAST_5_r22 1437 -#define _SWAP_FAST_5_r33 1438 -#define _SWAP_FAST_6_r01 1439 -#define _SWAP_FAST_6_r11 1440 -#define _SWAP_FAST_6_r22 1441 -#define _SWAP_FAST_6_r33 1442 -#define _SWAP_FAST_7_r01 1443 -#define _SWAP_FAST_7_r11 1444 -#define _SWAP_FAST_7_r22 1445 -#define _SWAP_FAST_7_r33 1446 -#define _TIER2_RESUME_CHECK_r00 1447 -#define _TIER2_RESUME_CHECK_r11 1448 -#define _TIER2_RESUME_CHECK_r22 1449 -#define _TIER2_RESUME_CHECK_r33 1450 -#define _TO_BOOL_r11 1451 -#define _TO_BOOL_BOOL_r01 1452 -#define _TO_BOOL_BOOL_r11 1453 -#define _TO_BOOL_BOOL_r22 1454 -#define _TO_BOOL_BOOL_r33 1455 -#define _TO_BOOL_INT_r02 1456 -#define _TO_BOOL_INT_r12 1457 -#define _TO_BOOL_INT_r23 1458 -#define _TO_BOOL_LIST_r02 1459 -#define _TO_BOOL_LIST_r12 1460 -#define _TO_BOOL_LIST_r23 1461 -#define _TO_BOOL_NONE_r01 1462 -#define _TO_BOOL_NONE_r11 1463 -#define _TO_BOOL_NONE_r22 1464 -#define _TO_BOOL_NONE_r33 1465 -#define _TO_BOOL_STR_r02 1466 -#define _TO_BOOL_STR_r12 1467 -#define _TO_BOOL_STR_r23 1468 -#define _TRACE_RECORD_r00 1469 -#define _UNARY_INVERT_r12 1470 -#define _UNARY_NEGATIVE_r12 1471 -#define _UNARY_NOT_r01 1472 -#define _UNARY_NOT_r11 1473 -#define _UNARY_NOT_r22 1474 -#define _UNARY_NOT_r33 1475 -#define _UNPACK_EX_r10 1476 -#define _UNPACK_SEQUENCE_r10 1477 -#define _UNPACK_SEQUENCE_LIST_r10 1478 -#define _UNPACK_SEQUENCE_TUPLE_r10 1479 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1480 -#define _WITH_EXCEPT_START_r33 1481 -#define _YIELD_VALUE_r11 1482 -#define MAX_UOP_REGS_ID 1482 +#define _YIELD_VALUE 597 +#define MAX_UOP_ID 597 +#define _BINARY_OP_r23 598 +#define _BINARY_OP_ADD_FLOAT_r03 599 +#define _BINARY_OP_ADD_FLOAT_r13 600 +#define _BINARY_OP_ADD_FLOAT_r23 601 +#define _BINARY_OP_ADD_INT_r03 602 +#define _BINARY_OP_ADD_INT_r13 603 +#define _BINARY_OP_ADD_INT_r23 604 +#define _BINARY_OP_ADD_UNICODE_r03 605 +#define _BINARY_OP_ADD_UNICODE_r13 606 +#define _BINARY_OP_ADD_UNICODE_r23 607 +#define _BINARY_OP_EXTEND_r23 608 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 609 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 610 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 611 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 612 +#define _BINARY_OP_MULTIPLY_INT_r03 613 +#define _BINARY_OP_MULTIPLY_INT_r13 614 +#define _BINARY_OP_MULTIPLY_INT_r23 615 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 616 +#define _BINARY_OP_SUBSCR_DICT_r23 617 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 618 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 619 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 620 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 621 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 622 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 623 +#define _BINARY_OP_SUBSCR_STR_INT_r23 624 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 625 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 626 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 627 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 628 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 629 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 630 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 631 +#define _BINARY_OP_SUBTRACT_INT_r03 632 +#define _BINARY_OP_SUBTRACT_INT_r13 633 +#define _BINARY_OP_SUBTRACT_INT_r23 634 +#define _BINARY_SLICE_r31 635 +#define _BUILD_INTERPOLATION_r01 636 +#define _BUILD_LIST_r01 637 +#define _BUILD_MAP_r01 638 +#define _BUILD_SET_r01 639 +#define _BUILD_SLICE_r01 640 +#define _BUILD_STRING_r01 641 +#define _BUILD_TEMPLATE_r21 642 +#define _BUILD_TUPLE_r01 643 +#define _CALL_BUILTIN_CLASS_r01 644 +#define _CALL_BUILTIN_FAST_r01 645 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 646 +#define _CALL_BUILTIN_O_r03 647 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 648 +#define _CALL_INTRINSIC_1_r11 649 +#define _CALL_INTRINSIC_2_r21 650 +#define _CALL_ISINSTANCE_r31 651 +#define _CALL_KW_NON_PY_r11 652 +#define _CALL_LEN_r33 653 +#define _CALL_LIST_APPEND_r03 654 +#define _CALL_LIST_APPEND_r13 655 +#define _CALL_LIST_APPEND_r23 656 +#define _CALL_LIST_APPEND_r33 657 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 658 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 659 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 660 +#define _CALL_METHOD_DESCRIPTOR_O_r03 661 +#define _CALL_NON_PY_GENERAL_r01 662 +#define _CALL_STR_1_r32 663 +#define _CALL_TUPLE_1_r32 664 +#define _CALL_TYPE_1_r02 665 +#define _CALL_TYPE_1_r12 666 +#define _CALL_TYPE_1_r22 667 +#define _CALL_TYPE_1_r32 668 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 669 +#define _CHECK_ATTR_CLASS_r01 670 +#define _CHECK_ATTR_CLASS_r11 671 +#define _CHECK_ATTR_CLASS_r22 672 +#define _CHECK_ATTR_CLASS_r33 673 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 674 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 675 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 676 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 677 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 678 +#define _CHECK_EG_MATCH_r22 679 +#define _CHECK_EXC_MATCH_r22 680 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 681 +#define _CHECK_FUNCTION_VERSION_r00 682 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 683 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 684 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 685 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 686 +#define _CHECK_FUNCTION_VERSION_KW_r11 687 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 688 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 689 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 690 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 691 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 692 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 693 +#define _CHECK_IS_PY_CALLABLE_EX_r03 694 +#define _CHECK_IS_PY_CALLABLE_EX_r13 695 +#define _CHECK_IS_PY_CALLABLE_EX_r23 696 +#define _CHECK_IS_PY_CALLABLE_EX_r33 697 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 698 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 699 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 700 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 701 +#define _CHECK_METHOD_VERSION_r00 702 +#define _CHECK_METHOD_VERSION_KW_r11 703 +#define _CHECK_PEP_523_r00 704 +#define _CHECK_PEP_523_r11 705 +#define _CHECK_PEP_523_r22 706 +#define _CHECK_PEP_523_r33 707 +#define _CHECK_PERIODIC_r00 708 +#define _CHECK_PERIODIC_AT_END_r00 709 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 710 +#define _CHECK_RECURSION_REMAINING_r00 711 +#define _CHECK_RECURSION_REMAINING_r11 712 +#define _CHECK_RECURSION_REMAINING_r22 713 +#define _CHECK_RECURSION_REMAINING_r33 714 +#define _CHECK_STACK_SPACE_r00 715 +#define _CHECK_STACK_SPACE_OPERAND_r00 716 +#define _CHECK_STACK_SPACE_OPERAND_r11 717 +#define _CHECK_STACK_SPACE_OPERAND_r22 718 +#define _CHECK_STACK_SPACE_OPERAND_r33 719 +#define _CHECK_VALIDITY_r00 720 +#define _CHECK_VALIDITY_r11 721 +#define _CHECK_VALIDITY_r22 722 +#define _CHECK_VALIDITY_r33 723 +#define _COLD_DYNAMIC_EXIT_r00 724 +#define _COLD_EXIT_r00 725 +#define _COMPARE_OP_r21 726 +#define _COMPARE_OP_FLOAT_r03 727 +#define _COMPARE_OP_FLOAT_r13 728 +#define _COMPARE_OP_FLOAT_r23 729 +#define _COMPARE_OP_INT_r23 730 +#define _COMPARE_OP_STR_r23 731 +#define _CONTAINS_OP_r23 732 +#define _CONTAINS_OP_DICT_r23 733 +#define _CONTAINS_OP_SET_r23 734 +#define _CONVERT_VALUE_r11 735 +#define _COPY_r01 736 +#define _COPY_1_r02 737 +#define _COPY_1_r12 738 +#define _COPY_1_r23 739 +#define _COPY_2_r03 740 +#define _COPY_2_r13 741 +#define _COPY_2_r23 742 +#define _COPY_3_r03 743 +#define _COPY_3_r13 744 +#define _COPY_3_r23 745 +#define _COPY_3_r33 746 +#define _COPY_FREE_VARS_r00 747 +#define _COPY_FREE_VARS_r11 748 +#define _COPY_FREE_VARS_r22 749 +#define _COPY_FREE_VARS_r33 750 +#define _CREATE_INIT_FRAME_r01 751 +#define _DELETE_ATTR_r10 752 +#define _DELETE_DEREF_r00 753 +#define _DELETE_FAST_r00 754 +#define _DELETE_GLOBAL_r00 755 +#define _DELETE_NAME_r00 756 +#define _DELETE_SUBSCR_r20 757 +#define _DEOPT_r00 758 +#define _DEOPT_r10 759 +#define _DEOPT_r20 760 +#define _DEOPT_r30 761 +#define _DICT_MERGE_r10 762 +#define _DICT_UPDATE_r10 763 +#define _DO_CALL_r01 764 +#define _DO_CALL_FUNCTION_EX_r31 765 +#define _DO_CALL_KW_r11 766 +#define _DYNAMIC_EXIT_r00 767 +#define _DYNAMIC_EXIT_r10 768 +#define _DYNAMIC_EXIT_r20 769 +#define _DYNAMIC_EXIT_r30 770 +#define _END_FOR_r10 771 +#define _END_SEND_r21 772 +#define _ERROR_POP_N_r00 773 +#define _EXIT_INIT_CHECK_r10 774 +#define _EXIT_TRACE_r00 775 +#define _EXIT_TRACE_r10 776 +#define _EXIT_TRACE_r20 777 +#define _EXIT_TRACE_r30 778 +#define _EXPAND_METHOD_r00 779 +#define _EXPAND_METHOD_KW_r11 780 +#define _FATAL_ERROR_r00 781 +#define _FATAL_ERROR_r11 782 +#define _FATAL_ERROR_r22 783 +#define _FATAL_ERROR_r33 784 +#define _FORMAT_SIMPLE_r11 785 +#define _FORMAT_WITH_SPEC_r21 786 +#define _FOR_ITER_r23 787 +#define _FOR_ITER_GEN_FRAME_r03 788 +#define _FOR_ITER_GEN_FRAME_r13 789 +#define _FOR_ITER_GEN_FRAME_r23 790 +#define _FOR_ITER_TIER_TWO_r23 791 +#define _GET_AITER_r11 792 +#define _GET_ANEXT_r12 793 +#define _GET_AWAITABLE_r11 794 +#define _GET_ITER_r12 795 +#define _GET_LEN_r12 796 +#define _GET_YIELD_FROM_ITER_r11 797 +#define _GUARD_BINARY_OP_EXTEND_r22 798 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 799 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 800 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 801 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 802 +#define _GUARD_BIT_IS_SET_POP_r00 803 +#define _GUARD_BIT_IS_SET_POP_r10 804 +#define _GUARD_BIT_IS_SET_POP_r21 805 +#define _GUARD_BIT_IS_SET_POP_r32 806 +#define _GUARD_BIT_IS_SET_POP_4_r00 807 +#define _GUARD_BIT_IS_SET_POP_4_r10 808 +#define _GUARD_BIT_IS_SET_POP_4_r21 809 +#define _GUARD_BIT_IS_SET_POP_4_r32 810 +#define _GUARD_BIT_IS_SET_POP_5_r00 811 +#define _GUARD_BIT_IS_SET_POP_5_r10 812 +#define _GUARD_BIT_IS_SET_POP_5_r21 813 +#define _GUARD_BIT_IS_SET_POP_5_r32 814 +#define _GUARD_BIT_IS_SET_POP_6_r00 815 +#define _GUARD_BIT_IS_SET_POP_6_r10 816 +#define _GUARD_BIT_IS_SET_POP_6_r21 817 +#define _GUARD_BIT_IS_SET_POP_6_r32 818 +#define _GUARD_BIT_IS_SET_POP_7_r00 819 +#define _GUARD_BIT_IS_SET_POP_7_r10 820 +#define _GUARD_BIT_IS_SET_POP_7_r21 821 +#define _GUARD_BIT_IS_SET_POP_7_r32 822 +#define _GUARD_BIT_IS_UNSET_POP_r00 823 +#define _GUARD_BIT_IS_UNSET_POP_r10 824 +#define _GUARD_BIT_IS_UNSET_POP_r21 825 +#define _GUARD_BIT_IS_UNSET_POP_r32 826 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 827 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 828 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 829 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 830 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 831 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 832 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 833 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 834 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 835 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 836 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 837 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 838 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 839 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 840 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 841 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 842 +#define _GUARD_CALLABLE_ISINSTANCE_r03 843 +#define _GUARD_CALLABLE_ISINSTANCE_r13 844 +#define _GUARD_CALLABLE_ISINSTANCE_r23 845 +#define _GUARD_CALLABLE_ISINSTANCE_r33 846 +#define _GUARD_CALLABLE_LEN_r03 847 +#define _GUARD_CALLABLE_LEN_r13 848 +#define _GUARD_CALLABLE_LEN_r23 849 +#define _GUARD_CALLABLE_LEN_r33 850 +#define _GUARD_CALLABLE_LIST_APPEND_r03 851 +#define _GUARD_CALLABLE_LIST_APPEND_r13 852 +#define _GUARD_CALLABLE_LIST_APPEND_r23 853 +#define _GUARD_CALLABLE_LIST_APPEND_r33 854 +#define _GUARD_CALLABLE_STR_1_r03 855 +#define _GUARD_CALLABLE_STR_1_r13 856 +#define _GUARD_CALLABLE_STR_1_r23 857 +#define _GUARD_CALLABLE_STR_1_r33 858 +#define _GUARD_CALLABLE_TUPLE_1_r03 859 +#define _GUARD_CALLABLE_TUPLE_1_r13 860 +#define _GUARD_CALLABLE_TUPLE_1_r23 861 +#define _GUARD_CALLABLE_TUPLE_1_r33 862 +#define _GUARD_CALLABLE_TYPE_1_r03 863 +#define _GUARD_CALLABLE_TYPE_1_r13 864 +#define _GUARD_CALLABLE_TYPE_1_r23 865 +#define _GUARD_CALLABLE_TYPE_1_r33 866 +#define _GUARD_CODE_VERSION_r00 867 +#define _GUARD_CODE_VERSION_r11 868 +#define _GUARD_CODE_VERSION_r22 869 +#define _GUARD_CODE_VERSION_r33 870 +#define _GUARD_DORV_NO_DICT_r01 871 +#define _GUARD_DORV_NO_DICT_r11 872 +#define _GUARD_DORV_NO_DICT_r22 873 +#define _GUARD_DORV_NO_DICT_r33 874 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 875 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 876 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 877 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 878 +#define _GUARD_GLOBALS_VERSION_r00 879 +#define _GUARD_GLOBALS_VERSION_r11 880 +#define _GUARD_GLOBALS_VERSION_r22 881 +#define _GUARD_GLOBALS_VERSION_r33 882 +#define _GUARD_IP_RETURN_GENERATOR_r00 883 +#define _GUARD_IP_RETURN_GENERATOR_r11 884 +#define _GUARD_IP_RETURN_GENERATOR_r22 885 +#define _GUARD_IP_RETURN_GENERATOR_r33 886 +#define _GUARD_IP_RETURN_VALUE_r00 887 +#define _GUARD_IP_RETURN_VALUE_r11 888 +#define _GUARD_IP_RETURN_VALUE_r22 889 +#define _GUARD_IP_RETURN_VALUE_r33 890 +#define _GUARD_IP_YIELD_VALUE_r00 891 +#define _GUARD_IP_YIELD_VALUE_r11 892 +#define _GUARD_IP_YIELD_VALUE_r22 893 +#define _GUARD_IP_YIELD_VALUE_r33 894 +#define _GUARD_IP__PUSH_FRAME_r00 895 +#define _GUARD_IP__PUSH_FRAME_r11 896 +#define _GUARD_IP__PUSH_FRAME_r22 897 +#define _GUARD_IP__PUSH_FRAME_r33 898 +#define _GUARD_IS_FALSE_POP_r00 899 +#define _GUARD_IS_FALSE_POP_r10 900 +#define _GUARD_IS_FALSE_POP_r21 901 +#define _GUARD_IS_FALSE_POP_r32 902 +#define _GUARD_IS_NONE_POP_r00 903 +#define _GUARD_IS_NONE_POP_r10 904 +#define _GUARD_IS_NONE_POP_r21 905 +#define _GUARD_IS_NONE_POP_r32 906 +#define _GUARD_IS_NOT_NONE_POP_r10 907 +#define _GUARD_IS_TRUE_POP_r00 908 +#define _GUARD_IS_TRUE_POP_r10 909 +#define _GUARD_IS_TRUE_POP_r21 910 +#define _GUARD_IS_TRUE_POP_r32 911 +#define _GUARD_KEYS_VERSION_r01 912 +#define _GUARD_KEYS_VERSION_r11 913 +#define _GUARD_KEYS_VERSION_r22 914 +#define _GUARD_KEYS_VERSION_r33 915 +#define _GUARD_NOS_ANY_DICT_r02 916 +#define _GUARD_NOS_ANY_DICT_r12 917 +#define _GUARD_NOS_ANY_DICT_r22 918 +#define _GUARD_NOS_ANY_DICT_r33 919 +#define _GUARD_NOS_COMPACT_ASCII_r02 920 +#define _GUARD_NOS_COMPACT_ASCII_r12 921 +#define _GUARD_NOS_COMPACT_ASCII_r22 922 +#define _GUARD_NOS_COMPACT_ASCII_r33 923 +#define _GUARD_NOS_DICT_r02 924 +#define _GUARD_NOS_DICT_r12 925 +#define _GUARD_NOS_DICT_r22 926 +#define _GUARD_NOS_DICT_r33 927 +#define _GUARD_NOS_FLOAT_r02 928 +#define _GUARD_NOS_FLOAT_r12 929 +#define _GUARD_NOS_FLOAT_r22 930 +#define _GUARD_NOS_FLOAT_r33 931 +#define _GUARD_NOS_INT_r02 932 +#define _GUARD_NOS_INT_r12 933 +#define _GUARD_NOS_INT_r22 934 +#define _GUARD_NOS_INT_r33 935 +#define _GUARD_NOS_LIST_r02 936 +#define _GUARD_NOS_LIST_r12 937 +#define _GUARD_NOS_LIST_r22 938 +#define _GUARD_NOS_LIST_r33 939 +#define _GUARD_NOS_NOT_NULL_r02 940 +#define _GUARD_NOS_NOT_NULL_r12 941 +#define _GUARD_NOS_NOT_NULL_r22 942 +#define _GUARD_NOS_NOT_NULL_r33 943 +#define _GUARD_NOS_NULL_r02 944 +#define _GUARD_NOS_NULL_r12 945 +#define _GUARD_NOS_NULL_r22 946 +#define _GUARD_NOS_NULL_r33 947 +#define _GUARD_NOS_OVERFLOWED_r02 948 +#define _GUARD_NOS_OVERFLOWED_r12 949 +#define _GUARD_NOS_OVERFLOWED_r22 950 +#define _GUARD_NOS_OVERFLOWED_r33 951 +#define _GUARD_NOS_TUPLE_r02 952 +#define _GUARD_NOS_TUPLE_r12 953 +#define _GUARD_NOS_TUPLE_r22 954 +#define _GUARD_NOS_TUPLE_r33 955 +#define _GUARD_NOS_UNICODE_r02 956 +#define _GUARD_NOS_UNICODE_r12 957 +#define _GUARD_NOS_UNICODE_r22 958 +#define _GUARD_NOS_UNICODE_r33 959 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 960 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 961 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 962 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 963 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 964 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 965 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 966 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 967 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 968 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 969 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 970 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 971 +#define _GUARD_THIRD_NULL_r03 972 +#define _GUARD_THIRD_NULL_r13 973 +#define _GUARD_THIRD_NULL_r23 974 +#define _GUARD_THIRD_NULL_r33 975 +#define _GUARD_TOS_ANY_DICT_r01 976 +#define _GUARD_TOS_ANY_DICT_r11 977 +#define _GUARD_TOS_ANY_DICT_r22 978 +#define _GUARD_TOS_ANY_DICT_r33 979 +#define _GUARD_TOS_ANY_SET_r01 980 +#define _GUARD_TOS_ANY_SET_r11 981 +#define _GUARD_TOS_ANY_SET_r22 982 +#define _GUARD_TOS_ANY_SET_r33 983 +#define _GUARD_TOS_DICT_r01 984 +#define _GUARD_TOS_DICT_r11 985 +#define _GUARD_TOS_DICT_r22 986 +#define _GUARD_TOS_DICT_r33 987 +#define _GUARD_TOS_FLOAT_r01 988 +#define _GUARD_TOS_FLOAT_r11 989 +#define _GUARD_TOS_FLOAT_r22 990 +#define _GUARD_TOS_FLOAT_r33 991 +#define _GUARD_TOS_FROZENDICT_r01 992 +#define _GUARD_TOS_FROZENDICT_r11 993 +#define _GUARD_TOS_FROZENDICT_r22 994 +#define _GUARD_TOS_FROZENDICT_r33 995 +#define _GUARD_TOS_FROZENSET_r01 996 +#define _GUARD_TOS_FROZENSET_r11 997 +#define _GUARD_TOS_FROZENSET_r22 998 +#define _GUARD_TOS_FROZENSET_r33 999 +#define _GUARD_TOS_INT_r01 1000 +#define _GUARD_TOS_INT_r11 1001 +#define _GUARD_TOS_INT_r22 1002 +#define _GUARD_TOS_INT_r33 1003 +#define _GUARD_TOS_LIST_r01 1004 +#define _GUARD_TOS_LIST_r11 1005 +#define _GUARD_TOS_LIST_r22 1006 +#define _GUARD_TOS_LIST_r33 1007 +#define _GUARD_TOS_OVERFLOWED_r01 1008 +#define _GUARD_TOS_OVERFLOWED_r11 1009 +#define _GUARD_TOS_OVERFLOWED_r22 1010 +#define _GUARD_TOS_OVERFLOWED_r33 1011 +#define _GUARD_TOS_SET_r01 1012 +#define _GUARD_TOS_SET_r11 1013 +#define _GUARD_TOS_SET_r22 1014 +#define _GUARD_TOS_SET_r33 1015 +#define _GUARD_TOS_SLICE_r01 1016 +#define _GUARD_TOS_SLICE_r11 1017 +#define _GUARD_TOS_SLICE_r22 1018 +#define _GUARD_TOS_SLICE_r33 1019 +#define _GUARD_TOS_TUPLE_r01 1020 +#define _GUARD_TOS_TUPLE_r11 1021 +#define _GUARD_TOS_TUPLE_r22 1022 +#define _GUARD_TOS_TUPLE_r33 1023 +#define _GUARD_TOS_UNICODE_r01 1024 +#define _GUARD_TOS_UNICODE_r11 1025 +#define _GUARD_TOS_UNICODE_r22 1026 +#define _GUARD_TOS_UNICODE_r33 1027 +#define _GUARD_TYPE_VERSION_r01 1028 +#define _GUARD_TYPE_VERSION_r11 1029 +#define _GUARD_TYPE_VERSION_r22 1030 +#define _GUARD_TYPE_VERSION_r33 1031 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1032 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1033 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1034 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1035 +#define _HANDLE_PENDING_AND_DEOPT_r00 1036 +#define _HANDLE_PENDING_AND_DEOPT_r10 1037 +#define _HANDLE_PENDING_AND_DEOPT_r20 1038 +#define _HANDLE_PENDING_AND_DEOPT_r30 1039 +#define _IMPORT_FROM_r12 1040 +#define _IMPORT_NAME_r21 1041 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1042 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1043 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1044 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1045 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1046 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1047 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1048 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1049 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1050 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1051 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1052 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1053 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1054 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1055 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1056 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1057 +#define _INSERT_NULL_r10 1058 +#define _INSTRUMENTED_FOR_ITER_r23 1059 +#define _INSTRUMENTED_INSTRUCTION_r00 1060 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1061 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1062 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1063 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1064 +#define _INSTRUMENTED_LINE_r00 1065 +#define _INSTRUMENTED_NOT_TAKEN_r00 1066 +#define _INSTRUMENTED_NOT_TAKEN_r11 1067 +#define _INSTRUMENTED_NOT_TAKEN_r22 1068 +#define _INSTRUMENTED_NOT_TAKEN_r33 1069 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1070 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1071 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1072 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1073 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1074 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1075 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1076 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1077 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1078 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1079 +#define _IS_NONE_r11 1080 +#define _IS_OP_r03 1081 +#define _IS_OP_r13 1082 +#define _IS_OP_r23 1083 +#define _ITER_CHECK_LIST_r02 1084 +#define _ITER_CHECK_LIST_r12 1085 +#define _ITER_CHECK_LIST_r22 1086 +#define _ITER_CHECK_LIST_r33 1087 +#define _ITER_CHECK_RANGE_r02 1088 +#define _ITER_CHECK_RANGE_r12 1089 +#define _ITER_CHECK_RANGE_r22 1090 +#define _ITER_CHECK_RANGE_r33 1091 +#define _ITER_CHECK_TUPLE_r02 1092 +#define _ITER_CHECK_TUPLE_r12 1093 +#define _ITER_CHECK_TUPLE_r22 1094 +#define _ITER_CHECK_TUPLE_r33 1095 +#define _ITER_JUMP_LIST_r02 1096 +#define _ITER_JUMP_LIST_r12 1097 +#define _ITER_JUMP_LIST_r22 1098 +#define _ITER_JUMP_LIST_r33 1099 +#define _ITER_JUMP_RANGE_r02 1100 +#define _ITER_JUMP_RANGE_r12 1101 +#define _ITER_JUMP_RANGE_r22 1102 +#define _ITER_JUMP_RANGE_r33 1103 +#define _ITER_JUMP_TUPLE_r02 1104 +#define _ITER_JUMP_TUPLE_r12 1105 +#define _ITER_JUMP_TUPLE_r22 1106 +#define _ITER_JUMP_TUPLE_r33 1107 +#define _ITER_NEXT_LIST_r23 1108 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1109 +#define _ITER_NEXT_RANGE_r03 1110 +#define _ITER_NEXT_RANGE_r13 1111 +#define _ITER_NEXT_RANGE_r23 1112 +#define _ITER_NEXT_TUPLE_r03 1113 +#define _ITER_NEXT_TUPLE_r13 1114 +#define _ITER_NEXT_TUPLE_r23 1115 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1116 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1117 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1118 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1119 +#define _JUMP_TO_TOP_r00 1120 +#define _LIST_APPEND_r10 1121 +#define _LIST_EXTEND_r10 1122 +#define _LOAD_ATTR_r10 1123 +#define _LOAD_ATTR_CLASS_r11 1124 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1125 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1126 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1127 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1128 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1129 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1130 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1131 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1132 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1133 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1134 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1135 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1136 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1137 +#define _LOAD_ATTR_MODULE_r12 1138 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1139 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1140 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1141 +#define _LOAD_ATTR_SLOT_r02 1142 +#define _LOAD_ATTR_SLOT_r12 1143 +#define _LOAD_ATTR_SLOT_r23 1144 +#define _LOAD_ATTR_WITH_HINT_r12 1145 +#define _LOAD_BUILD_CLASS_r01 1146 +#define _LOAD_BYTECODE_r00 1147 +#define _LOAD_COMMON_CONSTANT_r01 1148 +#define _LOAD_COMMON_CONSTANT_r12 1149 +#define _LOAD_COMMON_CONSTANT_r23 1150 +#define _LOAD_CONST_r01 1151 +#define _LOAD_CONST_r12 1152 +#define _LOAD_CONST_r23 1153 +#define _LOAD_CONST_INLINE_r01 1154 +#define _LOAD_CONST_INLINE_r12 1155 +#define _LOAD_CONST_INLINE_r23 1156 +#define _LOAD_CONST_INLINE_BORROW_r01 1157 +#define _LOAD_CONST_INLINE_BORROW_r12 1158 +#define _LOAD_CONST_INLINE_BORROW_r23 1159 +#define _LOAD_CONST_UNDER_INLINE_r02 1160 +#define _LOAD_CONST_UNDER_INLINE_r12 1161 +#define _LOAD_CONST_UNDER_INLINE_r23 1162 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1163 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1164 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1165 +#define _LOAD_DEREF_r01 1166 +#define _LOAD_FAST_r01 1167 +#define _LOAD_FAST_r12 1168 +#define _LOAD_FAST_r23 1169 +#define _LOAD_FAST_0_r01 1170 +#define _LOAD_FAST_0_r12 1171 +#define _LOAD_FAST_0_r23 1172 +#define _LOAD_FAST_1_r01 1173 +#define _LOAD_FAST_1_r12 1174 +#define _LOAD_FAST_1_r23 1175 +#define _LOAD_FAST_2_r01 1176 +#define _LOAD_FAST_2_r12 1177 +#define _LOAD_FAST_2_r23 1178 +#define _LOAD_FAST_3_r01 1179 +#define _LOAD_FAST_3_r12 1180 +#define _LOAD_FAST_3_r23 1181 +#define _LOAD_FAST_4_r01 1182 +#define _LOAD_FAST_4_r12 1183 +#define _LOAD_FAST_4_r23 1184 +#define _LOAD_FAST_5_r01 1185 +#define _LOAD_FAST_5_r12 1186 +#define _LOAD_FAST_5_r23 1187 +#define _LOAD_FAST_6_r01 1188 +#define _LOAD_FAST_6_r12 1189 +#define _LOAD_FAST_6_r23 1190 +#define _LOAD_FAST_7_r01 1191 +#define _LOAD_FAST_7_r12 1192 +#define _LOAD_FAST_7_r23 1193 +#define _LOAD_FAST_AND_CLEAR_r01 1194 +#define _LOAD_FAST_AND_CLEAR_r12 1195 +#define _LOAD_FAST_AND_CLEAR_r23 1196 +#define _LOAD_FAST_BORROW_r01 1197 +#define _LOAD_FAST_BORROW_r12 1198 +#define _LOAD_FAST_BORROW_r23 1199 +#define _LOAD_FAST_BORROW_0_r01 1200 +#define _LOAD_FAST_BORROW_0_r12 1201 +#define _LOAD_FAST_BORROW_0_r23 1202 +#define _LOAD_FAST_BORROW_1_r01 1203 +#define _LOAD_FAST_BORROW_1_r12 1204 +#define _LOAD_FAST_BORROW_1_r23 1205 +#define _LOAD_FAST_BORROW_2_r01 1206 +#define _LOAD_FAST_BORROW_2_r12 1207 +#define _LOAD_FAST_BORROW_2_r23 1208 +#define _LOAD_FAST_BORROW_3_r01 1209 +#define _LOAD_FAST_BORROW_3_r12 1210 +#define _LOAD_FAST_BORROW_3_r23 1211 +#define _LOAD_FAST_BORROW_4_r01 1212 +#define _LOAD_FAST_BORROW_4_r12 1213 +#define _LOAD_FAST_BORROW_4_r23 1214 +#define _LOAD_FAST_BORROW_5_r01 1215 +#define _LOAD_FAST_BORROW_5_r12 1216 +#define _LOAD_FAST_BORROW_5_r23 1217 +#define _LOAD_FAST_BORROW_6_r01 1218 +#define _LOAD_FAST_BORROW_6_r12 1219 +#define _LOAD_FAST_BORROW_6_r23 1220 +#define _LOAD_FAST_BORROW_7_r01 1221 +#define _LOAD_FAST_BORROW_7_r12 1222 +#define _LOAD_FAST_BORROW_7_r23 1223 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1224 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1225 +#define _LOAD_FAST_CHECK_r01 1226 +#define _LOAD_FAST_CHECK_r12 1227 +#define _LOAD_FAST_CHECK_r23 1228 +#define _LOAD_FAST_LOAD_FAST_r02 1229 +#define _LOAD_FAST_LOAD_FAST_r13 1230 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1231 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1232 +#define _LOAD_GLOBAL_r00 1233 +#define _LOAD_GLOBAL_BUILTINS_r01 1234 +#define _LOAD_GLOBAL_MODULE_r01 1235 +#define _LOAD_LOCALS_r01 1236 +#define _LOAD_LOCALS_r12 1237 +#define _LOAD_LOCALS_r23 1238 +#define _LOAD_NAME_r01 1239 +#define _LOAD_SMALL_INT_r01 1240 +#define _LOAD_SMALL_INT_r12 1241 +#define _LOAD_SMALL_INT_r23 1242 +#define _LOAD_SMALL_INT_0_r01 1243 +#define _LOAD_SMALL_INT_0_r12 1244 +#define _LOAD_SMALL_INT_0_r23 1245 +#define _LOAD_SMALL_INT_1_r01 1246 +#define _LOAD_SMALL_INT_1_r12 1247 +#define _LOAD_SMALL_INT_1_r23 1248 +#define _LOAD_SMALL_INT_2_r01 1249 +#define _LOAD_SMALL_INT_2_r12 1250 +#define _LOAD_SMALL_INT_2_r23 1251 +#define _LOAD_SMALL_INT_3_r01 1252 +#define _LOAD_SMALL_INT_3_r12 1253 +#define _LOAD_SMALL_INT_3_r23 1254 +#define _LOAD_SPECIAL_r00 1255 +#define _LOAD_SUPER_ATTR_ATTR_r31 1256 +#define _LOAD_SUPER_ATTR_METHOD_r32 1257 +#define _LOCK_OBJECT_r01 1258 +#define _LOCK_OBJECT_r11 1259 +#define _LOCK_OBJECT_r22 1260 +#define _LOCK_OBJECT_r33 1261 +#define _MAKE_CALLARGS_A_TUPLE_r33 1262 +#define _MAKE_CELL_r00 1263 +#define _MAKE_FUNCTION_r11 1264 +#define _MAKE_HEAP_SAFE_r01 1265 +#define _MAKE_HEAP_SAFE_r11 1266 +#define _MAKE_HEAP_SAFE_r22 1267 +#define _MAKE_HEAP_SAFE_r33 1268 +#define _MAKE_WARM_r00 1269 +#define _MAKE_WARM_r11 1270 +#define _MAKE_WARM_r22 1271 +#define _MAKE_WARM_r33 1272 +#define _MAP_ADD_r20 1273 +#define _MATCH_CLASS_r31 1274 +#define _MATCH_KEYS_r23 1275 +#define _MATCH_MAPPING_r02 1276 +#define _MATCH_MAPPING_r12 1277 +#define _MATCH_MAPPING_r23 1278 +#define _MATCH_SEQUENCE_r02 1279 +#define _MATCH_SEQUENCE_r12 1280 +#define _MATCH_SEQUENCE_r23 1281 +#define _MAYBE_EXPAND_METHOD_r00 1282 +#define _MAYBE_EXPAND_METHOD_KW_r11 1283 +#define _MONITOR_CALL_r00 1284 +#define _MONITOR_CALL_KW_r11 1285 +#define _MONITOR_JUMP_BACKWARD_r00 1286 +#define _MONITOR_JUMP_BACKWARD_r11 1287 +#define _MONITOR_JUMP_BACKWARD_r22 1288 +#define _MONITOR_JUMP_BACKWARD_r33 1289 +#define _MONITOR_RESUME_r00 1290 +#define _NOP_r00 1291 +#define _NOP_r11 1292 +#define _NOP_r22 1293 +#define _NOP_r33 1294 +#define _POP_CALL_r20 1295 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1296 +#define _POP_CALL_ONE_r30 1297 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1298 +#define _POP_CALL_TWO_r30 1299 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1300 +#define _POP_EXCEPT_r10 1301 +#define _POP_ITER_r20 1302 +#define _POP_JUMP_IF_FALSE_r00 1303 +#define _POP_JUMP_IF_FALSE_r10 1304 +#define _POP_JUMP_IF_FALSE_r21 1305 +#define _POP_JUMP_IF_FALSE_r32 1306 +#define _POP_JUMP_IF_TRUE_r00 1307 +#define _POP_JUMP_IF_TRUE_r10 1308 +#define _POP_JUMP_IF_TRUE_r21 1309 +#define _POP_JUMP_IF_TRUE_r32 1310 +#define _POP_TOP_r10 1311 +#define _POP_TOP_FLOAT_r00 1312 +#define _POP_TOP_FLOAT_r10 1313 +#define _POP_TOP_FLOAT_r21 1314 +#define _POP_TOP_FLOAT_r32 1315 +#define _POP_TOP_INT_r00 1316 +#define _POP_TOP_INT_r10 1317 +#define _POP_TOP_INT_r21 1318 +#define _POP_TOP_INT_r32 1319 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1320 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1321 +#define _POP_TOP_NOP_r00 1322 +#define _POP_TOP_NOP_r10 1323 +#define _POP_TOP_NOP_r21 1324 +#define _POP_TOP_NOP_r32 1325 +#define _POP_TOP_UNICODE_r00 1326 +#define _POP_TOP_UNICODE_r10 1327 +#define _POP_TOP_UNICODE_r21 1328 +#define _POP_TOP_UNICODE_r32 1329 +#define _POP_TWO_r20 1330 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1331 +#define _PUSH_EXC_INFO_r02 1332 +#define _PUSH_EXC_INFO_r12 1333 +#define _PUSH_EXC_INFO_r23 1334 +#define _PUSH_FRAME_r10 1335 +#define _PUSH_NULL_r01 1336 +#define _PUSH_NULL_r12 1337 +#define _PUSH_NULL_r23 1338 +#define _PUSH_NULL_CONDITIONAL_r00 1339 +#define _PY_FRAME_EX_r31 1340 +#define _PY_FRAME_GENERAL_r01 1341 +#define _PY_FRAME_KW_r11 1342 +#define _QUICKEN_RESUME_r00 1343 +#define _QUICKEN_RESUME_r11 1344 +#define _QUICKEN_RESUME_r22 1345 +#define _QUICKEN_RESUME_r33 1346 +#define _REPLACE_WITH_TRUE_r02 1347 +#define _REPLACE_WITH_TRUE_r12 1348 +#define _REPLACE_WITH_TRUE_r23 1349 +#define _RESUME_CHECK_r00 1350 +#define _RESUME_CHECK_r11 1351 +#define _RESUME_CHECK_r22 1352 +#define _RESUME_CHECK_r33 1353 +#define _RETURN_GENERATOR_r01 1354 +#define _RETURN_VALUE_r11 1355 +#define _SAVE_RETURN_OFFSET_r00 1356 +#define _SAVE_RETURN_OFFSET_r11 1357 +#define _SAVE_RETURN_OFFSET_r22 1358 +#define _SAVE_RETURN_OFFSET_r33 1359 +#define _SEND_r22 1360 +#define _SEND_GEN_FRAME_r22 1361 +#define _SETUP_ANNOTATIONS_r00 1362 +#define _SET_ADD_r10 1363 +#define _SET_FUNCTION_ATTRIBUTE_r01 1364 +#define _SET_FUNCTION_ATTRIBUTE_r11 1365 +#define _SET_FUNCTION_ATTRIBUTE_r21 1366 +#define _SET_FUNCTION_ATTRIBUTE_r32 1367 +#define _SET_IP_r00 1368 +#define _SET_IP_r11 1369 +#define _SET_IP_r22 1370 +#define _SET_IP_r33 1371 +#define _SET_UPDATE_r10 1372 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1373 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1374 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1375 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1376 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1377 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1378 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1379 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1380 +#define _SPILL_OR_RELOAD_r01 1381 +#define _SPILL_OR_RELOAD_r02 1382 +#define _SPILL_OR_RELOAD_r03 1383 +#define _SPILL_OR_RELOAD_r10 1384 +#define _SPILL_OR_RELOAD_r12 1385 +#define _SPILL_OR_RELOAD_r13 1386 +#define _SPILL_OR_RELOAD_r20 1387 +#define _SPILL_OR_RELOAD_r21 1388 +#define _SPILL_OR_RELOAD_r23 1389 +#define _SPILL_OR_RELOAD_r30 1390 +#define _SPILL_OR_RELOAD_r31 1391 +#define _SPILL_OR_RELOAD_r32 1392 +#define _START_EXECUTOR_r00 1393 +#define _STORE_ATTR_r20 1394 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1395 +#define _STORE_ATTR_SLOT_r21 1396 +#define _STORE_ATTR_WITH_HINT_r21 1397 +#define _STORE_DEREF_r10 1398 +#define _STORE_FAST_LOAD_FAST_r11 1399 +#define _STORE_FAST_STORE_FAST_r20 1400 +#define _STORE_GLOBAL_r10 1401 +#define _STORE_NAME_r10 1402 +#define _STORE_SLICE_r30 1403 +#define _STORE_SUBSCR_r30 1404 +#define _STORE_SUBSCR_DICT_r31 1405 +#define _STORE_SUBSCR_LIST_INT_r32 1406 +#define _SWAP_r11 1407 +#define _SWAP_2_r02 1408 +#define _SWAP_2_r12 1409 +#define _SWAP_2_r22 1410 +#define _SWAP_2_r33 1411 +#define _SWAP_3_r03 1412 +#define _SWAP_3_r13 1413 +#define _SWAP_3_r23 1414 +#define _SWAP_3_r33 1415 +#define _SWAP_FAST_r01 1416 +#define _SWAP_FAST_r11 1417 +#define _SWAP_FAST_r22 1418 +#define _SWAP_FAST_r33 1419 +#define _SWAP_FAST_0_r01 1420 +#define _SWAP_FAST_0_r11 1421 +#define _SWAP_FAST_0_r22 1422 +#define _SWAP_FAST_0_r33 1423 +#define _SWAP_FAST_1_r01 1424 +#define _SWAP_FAST_1_r11 1425 +#define _SWAP_FAST_1_r22 1426 +#define _SWAP_FAST_1_r33 1427 +#define _SWAP_FAST_2_r01 1428 +#define _SWAP_FAST_2_r11 1429 +#define _SWAP_FAST_2_r22 1430 +#define _SWAP_FAST_2_r33 1431 +#define _SWAP_FAST_3_r01 1432 +#define _SWAP_FAST_3_r11 1433 +#define _SWAP_FAST_3_r22 1434 +#define _SWAP_FAST_3_r33 1435 +#define _SWAP_FAST_4_r01 1436 +#define _SWAP_FAST_4_r11 1437 +#define _SWAP_FAST_4_r22 1438 +#define _SWAP_FAST_4_r33 1439 +#define _SWAP_FAST_5_r01 1440 +#define _SWAP_FAST_5_r11 1441 +#define _SWAP_FAST_5_r22 1442 +#define _SWAP_FAST_5_r33 1443 +#define _SWAP_FAST_6_r01 1444 +#define _SWAP_FAST_6_r11 1445 +#define _SWAP_FAST_6_r22 1446 +#define _SWAP_FAST_6_r33 1447 +#define _SWAP_FAST_7_r01 1448 +#define _SWAP_FAST_7_r11 1449 +#define _SWAP_FAST_7_r22 1450 +#define _SWAP_FAST_7_r33 1451 +#define _TIER2_RESUME_CHECK_r00 1452 +#define _TIER2_RESUME_CHECK_r11 1453 +#define _TIER2_RESUME_CHECK_r22 1454 +#define _TIER2_RESUME_CHECK_r33 1455 +#define _TO_BOOL_r11 1456 +#define _TO_BOOL_BOOL_r01 1457 +#define _TO_BOOL_BOOL_r11 1458 +#define _TO_BOOL_BOOL_r22 1459 +#define _TO_BOOL_BOOL_r33 1460 +#define _TO_BOOL_INT_r02 1461 +#define _TO_BOOL_INT_r12 1462 +#define _TO_BOOL_INT_r23 1463 +#define _TO_BOOL_LIST_r02 1464 +#define _TO_BOOL_LIST_r12 1465 +#define _TO_BOOL_LIST_r23 1466 +#define _TO_BOOL_NONE_r01 1467 +#define _TO_BOOL_NONE_r11 1468 +#define _TO_BOOL_NONE_r22 1469 +#define _TO_BOOL_NONE_r33 1470 +#define _TO_BOOL_STR_r02 1471 +#define _TO_BOOL_STR_r12 1472 +#define _TO_BOOL_STR_r23 1473 +#define _TRACE_RECORD_r00 1474 +#define _UNARY_INVERT_r12 1475 +#define _UNARY_NEGATIVE_r12 1476 +#define _UNARY_NOT_r01 1477 +#define _UNARY_NOT_r11 1478 +#define _UNARY_NOT_r22 1479 +#define _UNARY_NOT_r33 1480 +#define _UNPACK_EX_r10 1481 +#define _UNPACK_SEQUENCE_r10 1482 +#define _UNPACK_SEQUENCE_LIST_r10 1483 +#define _UNPACK_SEQUENCE_TUPLE_r10 1484 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1485 +#define _WITH_EXCEPT_START_r33 1486 +#define _YIELD_VALUE_r11 1487 +#define MAX_UOP_REGS_ID 1487 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 4a8245365f8..fbcb95baf2a 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -113,18 +113,18 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_OP_ADD_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, [_BINARY_OP_SUBTRACT_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, - [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_BINARY_OP_EXTEND] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_BINARY_OP_EXTEND] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_EXTEND] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_STORE_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_SUBSCR_LIST_INT] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_LIST_SLICE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_STR_INT] = HAS_DEOPT_FLAG, - [_BINARY_OP_SUBSCR_USTR_INT] = HAS_DEOPT_FLAG, + [_BINARY_OP_SUBSCR_STR_INT] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBSCR_USTR_INT] = HAS_EXIT_FLAG, [_GUARD_NOS_TUPLE] = HAS_EXIT_FLAG, [_GUARD_TOS_TUPLE] = HAS_EXIT_FLAG, - [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS] = HAS_DEOPT_FLAG, + [_GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_TUPLE_INT] = 0, [_GUARD_NOS_DICT] = HAS_EXIT_FLAG, [_GUARD_NOS_ANY_DICT] = HAS_EXIT_FLAG, @@ -132,7 +132,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GUARD_TOS_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_FROZENDICT] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_OP_SUBSCR_CHECK_FUNC] = HAS_DEOPT_FLAG, + [_BINARY_OP_SUBSCR_CHECK_FUNC] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_INIT_CALL] = 0, [_LIST_APPEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG, [_SET_ADD] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -147,7 +147,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GET_AITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GET_ANEXT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GET_AWAITABLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_SEND_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_SEND_GEN_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_YIELD_VALUE] = HAS_ARG_FLAG | HAS_NEEDS_GUARD_IP_FLAG, [_POP_EXCEPT] = HAS_ESCAPES_FLAG, [_LOAD_COMMON_CONSTANT] = HAS_ARG_FLAG, @@ -155,8 +155,8 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DELETE_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_UNPACK_SEQUENCE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_UNPACK_SEQUENCE_TWO_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, - [_UNPACK_SEQUENCE_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_UNPACK_SEQUENCE_TWO_TUPLE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, + [_UNPACK_SEQUENCE_TUPLE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, [_UNPACK_SEQUENCE_LIST] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_UNPACK_EX] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_STORE_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -190,21 +190,22 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_DICT_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DICT_MERGE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_MAP_ADD] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_LOAD_SUPER_ATTR_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_LOAD_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_SUPER_ATTR_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_LOAD_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_TYPE_VERSION] = HAS_EXIT_FLAG, - [_GUARD_TYPE_VERSION_AND_LOCK] = HAS_EXIT_FLAG, - [_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_DEOPT_FLAG, + [_GUARD_TYPE_VERSION_LOCKED] = HAS_EXIT_FLAG, + [_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_EXIT_FLAG, [_LOAD_ATTR_INSTANCE_VALUE] = HAS_DEOPT_FLAG, - [_LOAD_ATTR_MODULE] = HAS_DEOPT_FLAG, - [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG, - [_LOAD_ATTR_SLOT] = HAS_DEOPT_FLAG, + [_LOAD_ATTR_MODULE] = HAS_EXIT_FLAG, + [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_EXIT_FLAG, + [_LOAD_ATTR_SLOT] = HAS_EXIT_FLAG, [_CHECK_ATTR_CLASS] = HAS_EXIT_FLAG, [_LOAD_ATTR_CLASS] = HAS_ESCAPES_FLAG, - [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_GUARD_DORV_NO_DICT] = HAS_EXIT_FLAG, [_STORE_ATTR_INSTANCE_VALUE] = HAS_ESCAPES_FLAG, + [_LOCK_OBJECT] = HAS_DEOPT_FLAG, [_STORE_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_STORE_ATTR_SLOT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_COMPARE_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -213,9 +214,9 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_COMPARE_OP_STR] = HAS_ARG_FLAG, [_IS_OP] = HAS_ARG_FLAG, [_CONTAINS_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_TOS_ANY_SET] = HAS_DEOPT_FLAG, - [_GUARD_TOS_SET] = HAS_DEOPT_FLAG, - [_GUARD_TOS_FROZENSET] = HAS_DEOPT_FLAG, + [_GUARD_TOS_ANY_SET] = HAS_EXIT_FLAG, + [_GUARD_TOS_SET] = HAS_EXIT_FLAG, + [_GUARD_TOS_FROZENSET] = HAS_EXIT_FLAG, [_CONTAINS_OP_SET] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CONTAINS_OP_DICT] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CHECK_EG_MATCH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -240,18 +241,18 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_ITER_CHECK_RANGE] = HAS_EXIT_FLAG, [_GUARD_NOT_EXHAUSTED_RANGE] = HAS_EXIT_FLAG, [_ITER_NEXT_RANGE] = HAS_ERROR_FLAG, - [_FOR_ITER_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_FOR_ITER_GEN_FRAME] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_INSERT_NULL] = 0, [_LOAD_SPECIAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_WITH_EXCEPT_START] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_PUSH_EXC_INFO] = 0, - [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_DEOPT_FLAG, - [_GUARD_KEYS_VERSION] = HAS_DEOPT_FLAG, + [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_EXIT_FLAG, + [_GUARD_KEYS_VERSION] = HAS_EXIT_FLAG, [_LOAD_ATTR_METHOD_WITH_VALUES] = HAS_ARG_FLAG, [_LOAD_ATTR_METHOD_NO_DICT] = HAS_ARG_FLAG, [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, - [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG, + [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_EXIT_FLAG, [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG, [_MAYBE_EXPAND_METHOD] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, @@ -274,27 +275,27 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_INIT_CALL_PY_EXACT_ARGS_4] = HAS_PURE_FLAG, [_INIT_CALL_PY_EXACT_ARGS] = HAS_ARG_FLAG | HAS_PURE_FLAG, [_PUSH_FRAME] = HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG, - [_GUARD_NOS_NULL] = HAS_DEOPT_FLAG, + [_GUARD_NOS_NULL] = HAS_EXIT_FLAG, [_GUARD_NOS_NOT_NULL] = HAS_EXIT_FLAG, - [_GUARD_THIRD_NULL] = HAS_DEOPT_FLAG, - [_GUARD_CALLABLE_TYPE_1] = HAS_DEOPT_FLAG, + [_GUARD_THIRD_NULL] = HAS_EXIT_FLAG, + [_GUARD_CALLABLE_TYPE_1] = HAS_EXIT_FLAG, [_CALL_TYPE_1] = HAS_ARG_FLAG, - [_GUARD_CALLABLE_STR_1] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_STR_1] = HAS_EXIT_FLAG, [_CALL_STR_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_TUPLE_1] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_TUPLE_1] = HAS_EXIT_FLAG, [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CREATE_INIT_FRAME] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, [_EXIT_INIT_CHECK] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_LEN] = HAS_DEOPT_FLAG, + [_CALL_BUILTIN_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_BUILTIN_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GUARD_CALLABLE_LEN] = HAS_EXIT_FLAG, [_CALL_LEN] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_ISINSTANCE] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_ISINSTANCE] = HAS_EXIT_FLAG, [_CALL_ISINSTANCE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_GUARD_CALLABLE_LIST_APPEND] = HAS_DEOPT_FLAG, + [_GUARD_CALLABLE_LIST_APPEND] = HAS_EXIT_FLAG, [_CALL_LIST_APPEND] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_CALL_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -1835,13 +1836,13 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TYPE_VERSION_r33 }, }, }, - [_GUARD_TYPE_VERSION_AND_LOCK] = { + [_GUARD_TYPE_VERSION_LOCKED] = { .best = { 0, 1, 2, 3 }, .entries = { - { 1, 0, _GUARD_TYPE_VERSION_AND_LOCK_r01 }, - { 1, 1, _GUARD_TYPE_VERSION_AND_LOCK_r11 }, - { 2, 2, _GUARD_TYPE_VERSION_AND_LOCK_r22 }, - { 3, 3, _GUARD_TYPE_VERSION_AND_LOCK_r33 }, + { 1, 0, _GUARD_TYPE_VERSION_LOCKED_r01 }, + { 1, 1, _GUARD_TYPE_VERSION_LOCKED_r11 }, + { 2, 2, _GUARD_TYPE_VERSION_LOCKED_r22 }, + { 3, 3, _GUARD_TYPE_VERSION_LOCKED_r33 }, }, }, [_CHECK_MANAGED_OBJECT_HAS_VALUES] = { @@ -1934,6 +1935,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_LOCK_OBJECT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _LOCK_OBJECT_r01 }, + { 1, 1, _LOCK_OBJECT_r11 }, + { 2, 2, _LOCK_OBJECT_r22 }, + { 3, 3, _LOCK_OBJECT_r33 }, + }, + }, [_STORE_ATTR_WITH_HINT] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -3882,10 +3892,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TYPE_VERSION_r11] = _GUARD_TYPE_VERSION, [_GUARD_TYPE_VERSION_r22] = _GUARD_TYPE_VERSION, [_GUARD_TYPE_VERSION_r33] = _GUARD_TYPE_VERSION, - [_GUARD_TYPE_VERSION_AND_LOCK_r01] = _GUARD_TYPE_VERSION_AND_LOCK, - [_GUARD_TYPE_VERSION_AND_LOCK_r11] = _GUARD_TYPE_VERSION_AND_LOCK, - [_GUARD_TYPE_VERSION_AND_LOCK_r22] = _GUARD_TYPE_VERSION_AND_LOCK, - [_GUARD_TYPE_VERSION_AND_LOCK_r33] = _GUARD_TYPE_VERSION_AND_LOCK, + [_GUARD_TYPE_VERSION_LOCKED_r01] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_VERSION_LOCKED_r11] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_VERSION_LOCKED_r22] = _GUARD_TYPE_VERSION_LOCKED, + [_GUARD_TYPE_VERSION_LOCKED_r33] = _GUARD_TYPE_VERSION_LOCKED, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r01] = _CHECK_MANAGED_OBJECT_HAS_VALUES, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r11] = _CHECK_MANAGED_OBJECT_HAS_VALUES, [_CHECK_MANAGED_OBJECT_HAS_VALUES_r22] = _CHECK_MANAGED_OBJECT_HAS_VALUES, @@ -3909,6 +3919,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_DORV_NO_DICT_r22] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r33] = _GUARD_DORV_NO_DICT, [_STORE_ATTR_INSTANCE_VALUE_r21] = _STORE_ATTR_INSTANCE_VALUE, + [_LOCK_OBJECT_r01] = _LOCK_OBJECT, + [_LOCK_OBJECT_r11] = _LOCK_OBJECT, + [_LOCK_OBJECT_r22] = _LOCK_OBJECT, + [_LOCK_OBJECT_r33] = _LOCK_OBJECT, [_STORE_ATTR_WITH_HINT_r21] = _STORE_ATTR_WITH_HINT, [_STORE_ATTR_SLOT_r21] = _STORE_ATTR_SLOT, [_COMPARE_OP_r21] = _COMPARE_OP, @@ -4946,11 +4960,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_TYPE_VERSION_r11] = "_GUARD_TYPE_VERSION_r11", [_GUARD_TYPE_VERSION_r22] = "_GUARD_TYPE_VERSION_r22", [_GUARD_TYPE_VERSION_r33] = "_GUARD_TYPE_VERSION_r33", - [_GUARD_TYPE_VERSION_AND_LOCK] = "_GUARD_TYPE_VERSION_AND_LOCK", - [_GUARD_TYPE_VERSION_AND_LOCK_r01] = "_GUARD_TYPE_VERSION_AND_LOCK_r01", - [_GUARD_TYPE_VERSION_AND_LOCK_r11] = "_GUARD_TYPE_VERSION_AND_LOCK_r11", - [_GUARD_TYPE_VERSION_AND_LOCK_r22] = "_GUARD_TYPE_VERSION_AND_LOCK_r22", - [_GUARD_TYPE_VERSION_AND_LOCK_r33] = "_GUARD_TYPE_VERSION_AND_LOCK_r33", + [_GUARD_TYPE_VERSION_LOCKED] = "_GUARD_TYPE_VERSION_LOCKED", + [_GUARD_TYPE_VERSION_LOCKED_r01] = "_GUARD_TYPE_VERSION_LOCKED_r01", + [_GUARD_TYPE_VERSION_LOCKED_r11] = "_GUARD_TYPE_VERSION_LOCKED_r11", + [_GUARD_TYPE_VERSION_LOCKED_r22] = "_GUARD_TYPE_VERSION_LOCKED_r22", + [_GUARD_TYPE_VERSION_LOCKED_r33] = "_GUARD_TYPE_VERSION_LOCKED_r33", [_HANDLE_PENDING_AND_DEOPT] = "_HANDLE_PENDING_AND_DEOPT", [_HANDLE_PENDING_AND_DEOPT_r00] = "_HANDLE_PENDING_AND_DEOPT_r00", [_HANDLE_PENDING_AND_DEOPT_r10] = "_HANDLE_PENDING_AND_DEOPT_r10", @@ -5207,6 +5221,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_SUPER_ATTR_ATTR_r31] = "_LOAD_SUPER_ATTR_ATTR_r31", [_LOAD_SUPER_ATTR_METHOD] = "_LOAD_SUPER_ATTR_METHOD", [_LOAD_SUPER_ATTR_METHOD_r32] = "_LOAD_SUPER_ATTR_METHOD_r32", + [_LOCK_OBJECT] = "_LOCK_OBJECT", + [_LOCK_OBJECT_r01] = "_LOCK_OBJECT_r01", + [_LOCK_OBJECT_r11] = "_LOCK_OBJECT_r11", + [_LOCK_OBJECT_r22] = "_LOCK_OBJECT_r22", + [_LOCK_OBJECT_r33] = "_LOCK_OBJECT_r33", [_MAKE_CALLARGS_A_TUPLE] = "_MAKE_CALLARGS_A_TUPLE", [_MAKE_CALLARGS_A_TUPLE_r33] = "_MAKE_CALLARGS_A_TUPLE_r33", [_MAKE_CELL] = "_MAKE_CELL", @@ -5832,7 +5851,7 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _GUARD_TYPE_VERSION: return 0; - case _GUARD_TYPE_VERSION_AND_LOCK: + case _GUARD_TYPE_VERSION_LOCKED: return 0; case _CHECK_MANAGED_OBJECT_HAS_VALUES: return 0; @@ -5854,6 +5873,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _STORE_ATTR_INSTANCE_VALUE: return 2; + case _LOCK_OBJECT: + return 0; case _STORE_ATTR_WITH_HINT: return 2; case _STORE_ATTR_SLOT: diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 2615b1d4dd2..b025f7b0eb7 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -825,12 +825,10 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(BINARY_OP); - assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); - JUMP_TO_PREDICTED(BINARY_OP); + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; #ifdef Py_GIL_DISABLED _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index); @@ -840,15 +838,13 @@ assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); res = PyStackRef_FromPyObjectSteal(res_o); #else - if (index >= PyList_GET_SIZE(list)) { + if (index < 0 || index >= PyList_GET_SIZE(list)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -10979,21 +10975,25 @@ next_instr += 5; INSTRUCTION_STATS(STORE_ATTR_INSTANCE_VALUE); static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); - _PyStackRef owner; _PyStackRef value; + _PyStackRef owner; _PyStackRef o; /* Skip 1 cache entry */ - // _GUARD_TYPE_VERSION_AND_LOCK + // _LOCK_OBJECT { - owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&this_instr[2].cache); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { + value = stack_pointer[-1]; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { UPDATE_MISS_STATS(STORE_ATTR); assert(_PyOpcode_Deopt[opcode] == (STORE_ATTR)); JUMP_TO_PREDICTED(STORE_ATTR); } + } + // _GUARD_TYPE_VERSION_LOCKED + { + owner = value; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); + assert(type_version != 0); PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -11617,18 +11617,17 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(STORE_SUBSCR); - assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); - JUMP_TO_PREDICTED(STORE_SUBSCR); - } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); if (!LOCK_OBJECT(list)) { UPDATE_MISS_STATS(STORE_SUBSCR); assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); JUMP_TO_PREDICTED(STORE_SUBSCR); } - if (index >= PyList_GET_SIZE(list)) { + Py_ssize_t len = PyList_GET_SIZE(list); + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); if (true) { UPDATE_MISS_STATS(STORE_SUBSCR); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index ac3e519398d..0eff5f76740 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -794,7 +794,7 @@ dummy_func( #endif _PyStackRef *target_local = &GETLOCAL(next_oparg); assert(PyUnicode_CheckExact(left_o)); - DEOPT_IF(PyStackRef_AsPyObjectBorrow(*target_local) != left_o); + EXIT_IF(PyStackRef_AsPyObjectBorrow(*target_local) != left_o); STAT_INC(BINARY_OP, hit); /* Handle `left = left + right` or `left += right` for str. * @@ -830,7 +830,7 @@ dummy_func( assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5); assert(d && d->guard); int res = d->guard(left_o, right_o); - DEOPT_IF(!res); + EXIT_IF(!res); } op(_BINARY_OP_EXTEND, (descr/4, left, right -- res, l, r)) { @@ -930,17 +930,16 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - // Deopt unless 0 <= sub < PyList_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); + } #ifdef Py_GIL_DISABLED PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index); - DEOPT_IF(res_o == NULL); - STAT_INC(BINARY_OP, hit); + EXIT_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); #else - DEOPT_IF(index >= PyList_GET_SIZE(list)); - STAT_INC(BINARY_OP, hit); + EXIT_IF(index < 0 || index >= PyList_GET_SIZE(list)); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -981,9 +980,9 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyUnicode_CheckExact(str)); - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); + EXIT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(PyUnicode_GET_LENGTH(str) <= index); + EXIT_IF(PyUnicode_GET_LENGTH(str) <= index); uint8_t c = PyUnicode_1BYTE_DATA(str)[index]; assert(c < 128); STAT_INC(BINARY_OP, hit); @@ -1003,12 +1002,12 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyUnicode_CheckExact(str)); - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); + EXIT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject*)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(PyUnicode_GET_LENGTH(str) <= index); + EXIT_IF(PyUnicode_GET_LENGTH(str) <= index); // Specialize for reading an ASCII character from any string: Py_UCS4 c = PyUnicode_READ_CHAR(str, index); - DEOPT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c); + EXIT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c); STAT_INC(BINARY_OP, hit); PyObject *res_o = (PyObject*)&_Py_SINGLETON(strings).ascii[c]; s = str_st; @@ -1045,9 +1044,9 @@ dummy_func( assert(PyTuple_CheckExact(tuple)); // Deopt unless 0 <= sub < PyTuple_Size(list) - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); + EXIT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; - DEOPT_IF(index >= PyTuple_GET_SIZE(tuple)); + EXIT_IF(index >= PyTuple_GET_SIZE(tuple)); } op(_BINARY_OP_SUBSCR_TUPLE_INT, (tuple_st, sub_st -- res, ts, ss)) { @@ -1117,16 +1116,16 @@ dummy_func( op(_BINARY_OP_SUBSCR_CHECK_FUNC, (container, unused -- container, unused, getitem)) { PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container)); - DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)); + EXIT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)); PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; PyObject *getitem_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(ht->_spec_cache.getitem); - DEOPT_IF(getitem_o == NULL); + EXIT_IF(getitem_o == NULL); assert(PyFunction_Check(getitem_o)); uint32_t cached_version = FT_ATOMIC_LOAD_UINT32_RELAXED(ht->_spec_cache.getitem_version); - DEOPT_IF(((PyFunctionObject *)getitem_o)->func_version != cached_version); + EXIT_IF(((PyFunctionObject *)getitem_o)->func_version != cached_version); PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem_o); assert(code->co_argcount == 2); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); getitem = PyStackRef_FromPyObjectNew(getitem_o); } @@ -1196,12 +1195,14 @@ dummy_func( assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - // Ensure nonnegative, zero-or-one-digit ints. - DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)); - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); DEOPT_IF(!LOCK_OBJECT(list)); + Py_ssize_t len = PyList_GET_SIZE(list); // Ensure index < len(list) - if (index >= PyList_GET_SIZE(list)) { + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); DEOPT_IF(true); } @@ -1458,8 +1459,8 @@ dummy_func( op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame)) { PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type); - DEOPT_IF(!gen_try_set_executing((PyGenObject *)gen)); + EXIT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type); + EXIT_IF(!gen_try_set_executing((PyGenObject *)gen)); STAT_INC(SEND, hit); _PyInterpreterFrame *pushed_frame = &gen->gi_iframe; _PyFrame_StackPush(pushed_frame, PyStackRef_MakeHeapSafe(v)); @@ -1699,7 +1700,7 @@ dummy_func( assert(oparg == 2); PyObject *seq_o = PyStackRef_AsPyObjectBorrow(seq); assert(PyTuple_CheckExact(seq_o)); - DEOPT_IF(PyTuple_GET_SIZE(seq_o) != 2); + EXIT_IF(PyTuple_GET_SIZE(seq_o) != 2); STAT_INC(UNPACK_SEQUENCE, hit); val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0)); val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1)); @@ -1712,7 +1713,7 @@ dummy_func( op(_UNPACK_SEQUENCE_TUPLE, (seq -- values[oparg])) { PyObject *seq_o = PyStackRef_AsPyObjectBorrow(seq); assert(PyTuple_CheckExact(seq_o)); - DEOPT_IF(PyTuple_GET_SIZE(seq_o) != oparg); + EXIT_IF(PyTuple_GET_SIZE(seq_o) != oparg); STAT_INC(UNPACK_SEQUENCE, hit); PyObject **items = _PyTuple_ITEMS(seq_o); for (int i = oparg; --i >= 0; ) { @@ -2362,8 +2363,8 @@ dummy_func( PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); assert(!(oparg & 1)); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type); - DEOPT_IF(!PyType_Check(class)); + EXIT_IF(global_super != (PyObject *)&PySuper_Type); + EXIT_IF(!PyType_Check(class)); STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyObject *attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); @@ -2378,8 +2379,8 @@ dummy_func( PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); assert(oparg & 1); - DEOPT_IF(global_super != (PyObject *)&PySuper_Type); - DEOPT_IF(!PyType_Check(class)); + EXIT_IF(global_super != (PyObject *)&PySuper_Type); + EXIT_IF(!PyType_Check(class)); STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyTypeObject *cls = (PyTypeObject *)class; @@ -2462,10 +2463,9 @@ dummy_func( EXIT_IF(FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version); } - op(_GUARD_TYPE_VERSION_AND_LOCK, (type_version/2, owner -- owner)) { + op(_GUARD_TYPE_VERSION_LOCKED, (type_version/2, owner -- owner)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - EXIT_IF(!LOCK_OBJECT(owner_o)); PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -2477,7 +2477,7 @@ dummy_func( PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_dictoffset < 0); assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_INLINE_VALUES); - DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid)); + EXIT_IF(!FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner_o)->valid)); } op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, o)) { @@ -2510,20 +2510,20 @@ dummy_func( op(_LOAD_ATTR_MODULE, (dict_version/2, index/1, owner -- attr, o)) { PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - DEOPT_IF(Py_TYPE(owner_o)->tp_getattro != PyModule_Type.tp_getattro); + EXIT_IF(Py_TYPE(owner_o)->tp_getattro != PyModule_Type.tp_getattro); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict; assert(dict != NULL); PyDictKeysObject *keys = FT_ATOMIC_LOAD_PTR_ACQUIRE(dict->ma_keys); - DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != dict_version); + EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != dict_version); assert(keys->dk_kind == DICT_KEYS_UNICODE); assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(keys->dk_nentries)); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(keys) + index; PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value); - DEOPT_IF(attr_o == NULL); + EXIT_IF(attr_o == NULL); #ifdef Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); if (!increfed) { - DEOPT_IF(true); + EXIT_IF(true); } #else attr = PyStackRef_FromPyObjectNew(attr_o); @@ -2544,34 +2544,34 @@ dummy_func( PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictObject *dict = _PyObject_GetManagedDict(owner_o); - DEOPT_IF(dict == NULL); + EXIT_IF(dict == NULL); PyDictKeysObject *dk = FT_ATOMIC_LOAD_PTR(dict->ma_keys); assert(PyDict_CheckExact((PyObject *)dict)); #ifdef Py_GIL_DISABLED - DEOPT_IF(!_Py_IsOwnedByCurrentThread((PyObject *)dict) && !_PyObject_GC_IS_SHARED(dict)); + EXIT_IF(!_Py_IsOwnedByCurrentThread((PyObject *)dict) && !_PyObject_GC_IS_SHARED(dict)); #endif PyObject *attr_o; if (hint >= (size_t)FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_nentries)) { - DEOPT_IF(true); + EXIT_IF(true); } PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); if (dk->dk_kind != DICT_KEYS_UNICODE) { - DEOPT_IF(true); + EXIT_IF(true); } PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dk) + hint; if (FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key) != name) { - DEOPT_IF(true); + EXIT_IF(true); } attr_o = FT_ATOMIC_LOAD_PTR(ep->me_value); if (attr_o == NULL) { - DEOPT_IF(true); + EXIT_IF(true); } STAT_INC(LOAD_ATTR, hit); #ifdef Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); if (!increfed) { - DEOPT_IF(true); + EXIT_IF(true); } #else attr = PyStackRef_FromPyObjectNew(attr_o); @@ -2594,10 +2594,10 @@ dummy_func( PyObject **addr = (PyObject **)((char *)owner_o + index); PyObject *attr_o = FT_ATOMIC_LOAD_PTR(*addr); - DEOPT_IF(attr_o == NULL); + EXIT_IF(attr_o == NULL); #ifdef Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(addr, attr_o, &attr); - DEOPT_IF(!increfed); + EXIT_IF(!increfed); #else attr = PyStackRef_FromPyObjectNew(attr_o); #endif @@ -2650,10 +2650,10 @@ dummy_func( assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; PyCodeObject *code = (PyCodeObject *)f->func_code; - DEOPT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED); - DEOPT_IF(code->co_kwonlyargcount); - DEOPT_IF(code->co_argcount != 1); - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); + EXIT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED); + EXIT_IF(code->co_kwonlyargcount); + EXIT_IF(code->co_argcount != 1); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); pushed_frame->localsplus[0] = owner; @@ -2731,9 +2731,14 @@ dummy_func( Py_XDECREF(old_value); } + op(_LOCK_OBJECT, (value -- value)) { + DEOPT_IF(!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))); + } + macro(STORE_ATTR_INSTANCE_VALUE) = unused/1 + - _GUARD_TYPE_VERSION_AND_LOCK + + _LOCK_OBJECT + + _GUARD_TYPE_VERSION_LOCKED + _GUARD_DORV_NO_DICT + _STORE_ATTR_INSTANCE_VALUE + POP_TOP; @@ -2952,17 +2957,17 @@ dummy_func( op(_GUARD_TOS_ANY_SET, (tos -- tos)) { PyObject *o = PyStackRef_AsPyObjectBorrow(tos); - DEOPT_IF(!PyAnySet_CheckExact(o)); + EXIT_IF(!PyAnySet_CheckExact(o)); } op(_GUARD_TOS_SET, (tos -- tos)) { PyObject *o = PyStackRef_AsPyObjectBorrow(tos); - DEOPT_IF(!PySet_CheckExact(o)); + EXIT_IF(!PySet_CheckExact(o)); } op(_GUARD_TOS_FROZENSET, (tos -- tos)) { PyObject *o = PyStackRef_AsPyObjectBorrow(tos); - DEOPT_IF(!PyFrozenSet_CheckExact(o)); + EXIT_IF(!PyFrozenSet_CheckExact(o)); } macro(CONTAINS_OP_SET) = _GUARD_TOS_ANY_SET + unused/1 + _CONTAINS_OP_SET + POP_TOP + POP_TOP; @@ -3585,8 +3590,8 @@ dummy_func( op(_FOR_ITER_GEN_FRAME, (iter, null -- iter, null, gen_frame)) { PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type); - DEOPT_IF(!gen_try_set_executing((PyGenObject *)gen)); + EXIT_IF(Py_TYPE(gen) != &PyGen_Type); + EXIT_IF(!gen_try_set_executing((PyGenObject *)gen)); STAT_INC(FOR_ITER, hit); _PyInterpreterFrame *pushed_frame = &gen->gi_iframe; _PyFrame_StackPush(pushed_frame, PyStackRef_None); @@ -3711,14 +3716,14 @@ dummy_func( PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_INLINE_VALUES); PyDictValues *ivs = _PyObject_InlineValues(owner_o); - DEOPT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid)); + EXIT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid)); } op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) { PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version); + EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version); } op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) { @@ -3794,7 +3799,7 @@ dummy_func( char *ptr = ((char *)PyStackRef_AsPyObjectBorrow(owner)) + MANAGED_DICT_OFFSET + dictoffset; PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*(PyObject **)ptr); /* This object has a __dict__, just not yet created */ - DEOPT_IF(dict != NULL); + EXIT_IF(dict != NULL); } op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) { @@ -4150,7 +4155,7 @@ dummy_func( _PUSH_FRAME; op(_GUARD_NOS_NULL, (null, unused -- null, unused)) { - DEOPT_IF(!PyStackRef_IsNull(null)); + EXIT_IF(!PyStackRef_IsNull(null)); } op(_GUARD_NOS_NOT_NULL, (nos, unused -- nos, unused)) { @@ -4159,12 +4164,12 @@ dummy_func( } op(_GUARD_THIRD_NULL, (null, unused, unused -- null, unused, unused)) { - DEOPT_IF(!PyStackRef_IsNull(null)); + EXIT_IF(!PyStackRef_IsNull(null)); } op(_GUARD_CALLABLE_TYPE_1, (callable, unused, unused -- callable, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(callable_o != (PyObject *)&PyType_Type); + EXIT_IF(callable_o != (PyObject *)&PyType_Type); } op(_CALL_TYPE_1, (callable, null, arg -- res, a)) { @@ -4187,7 +4192,7 @@ dummy_func( op(_GUARD_CALLABLE_STR_1, (callable, unused, unused -- callable, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(callable_o != (PyObject *)&PyUnicode_Type); + EXIT_IF(callable_o != (PyObject *)&PyUnicode_Type); } op(_CALL_STR_1, (callable, null, arg -- res, a)) { @@ -4215,7 +4220,7 @@ dummy_func( op(_GUARD_CALLABLE_TUPLE_1, (callable, unused, unused -- callable, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(callable_o != (PyObject *)&PyTuple_Type); + EXIT_IF(callable_o != (PyObject *)&PyTuple_Type); } op(_CALL_TUPLE_1, (callable, null, arg -- res, a)) { @@ -4243,17 +4248,17 @@ dummy_func( op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyStackRef_IsNull(self_or_null)); - DEOPT_IF(!PyType_Check(callable_o)); + EXIT_IF(!PyStackRef_IsNull(self_or_null)); + EXIT_IF(!PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; - DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != type_version); + EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != type_version); assert(tp->tp_new == PyBaseObject_Type.tp_new); assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(tp->tp_alloc == PyType_GenericAlloc); PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o; PyFunctionObject *init_func = (PyFunctionObject *)FT_ATOMIC_LOAD_PTR_ACQUIRE(cls->_spec_cache.init); PyCodeObject *code = (PyCodeObject *)init_func->func_code; - DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize)); + EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize)); STAT_INC(CALL, hit); PyObject *self_o = PyType_GenericAlloc(tp, 0); if (self_o == NULL) { @@ -4310,7 +4315,7 @@ dummy_func( op(_CALL_BUILTIN_CLASS, (callable, self_or_null, args[oparg] -- res)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyType_Check(callable_o)); + EXIT_IF(!PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; int total_args = oparg; _PyStackRef *arguments = args; @@ -4318,7 +4323,7 @@ dummy_func( arguments--; total_args++; } - DEOPT_IF(tp->tp_vectorcall == NULL); + EXIT_IF(tp->tp_vectorcall == NULL); STAT_INC(CALL, hit); PyObject *res_o = _Py_CallBuiltinClass_StackRefSteal( callable, @@ -4385,8 +4390,8 @@ dummy_func( total_args++; } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyCFunction_CheckExact(callable_o)); - DEOPT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_FASTCALL); + EXIT_IF(!PyCFunction_CheckExact(callable_o)); + EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_FASTCALL); STAT_INC(CALL, hit); PyObject *res_o = _Py_BuiltinCallFast_StackRefSteal( callable, @@ -4416,8 +4421,8 @@ dummy_func( total_args++; } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyCFunction_CheckExact(callable_o)); - DEOPT_IF(PyCFunction_GET_FLAGS(callable_o) != (METH_FASTCALL | METH_KEYWORDS)); + EXIT_IF(!PyCFunction_CheckExact(callable_o)); + EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != (METH_FASTCALL | METH_KEYWORDS)); STAT_INC(CALL, hit); PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args); DEAD(args); @@ -4446,7 +4451,7 @@ dummy_func( op(_GUARD_CALLABLE_LEN, (callable, unused, unused -- callable, unused, unused)){ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable_o != interp->callable_cache.len); + EXIT_IF(callable_o != interp->callable_cache.len); } op(_CALL_LEN, (callable, null, arg -- res, a, c)) { @@ -4471,7 +4476,7 @@ dummy_func( op(_GUARD_CALLABLE_ISINSTANCE, (callable, unused, unused, unused -- callable, unused, unused, unused)) { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable_o != interp->callable_cache.isinstance); + EXIT_IF(callable_o != interp->callable_cache.isinstance); } op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) { @@ -4512,7 +4517,7 @@ dummy_func( op(_GUARD_CALLABLE_LIST_APPEND, (callable, unused, unused -- callable, unused, unused)){ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyInterpreterState *interp = tstate->interp; - DEOPT_IF(callable_o != interp->callable_cache.list_append); + EXIT_IF(callable_o != interp->callable_cache.list_append); } op(_CALL_LIST_APPEND, (callable, self, arg -- none, c, s)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 6271778bed4..032d6faeda6 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -5358,14 +5358,10 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache1 = sub_st; - _tos_cache0 = list_st; - SET_CURRENT_CACHED_VALUES(2); - JUMP_TO_JUMP_TARGET(); + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; #ifdef Py_GIL_DISABLED stack_pointer[0] = list_st; stack_pointer[1] = sub_st; @@ -5383,17 +5379,15 @@ ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); JUMP_TO_JUMP_TARGET(); } - STAT_INC(BINARY_OP, hit); res = PyStackRef_FromPyObjectSteal(res_o); #else - if (index >= PyList_GET_SIZE(list)) { + if (index < 0 || index >= PyList_GET_SIZE(list)) { UOP_STAT_INC(uopcode, miss); _tos_cache1 = sub_st; _tos_cache0 = list_st; SET_CURRENT_CACHED_VALUES(2); JUMP_TO_JUMP_TARGET(); } - STAT_INC(BINARY_OP, hit); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -6705,15 +6699,7 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache2 = sub_st; - _tos_cache1 = list_st; - _tos_cache0 = value; - SET_CURRENT_CACHED_VALUES(3); - JUMP_TO_JUMP_TARGET(); - } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); if (!LOCK_OBJECT(list)) { UOP_STAT_INC(uopcode, miss); _tos_cache2 = sub_st; @@ -6722,7 +6708,11 @@ SET_CURRENT_CACHED_VALUES(3); JUMP_TO_JUMP_TARGET(); } - if (index >= PyList_GET_SIZE(list)) { + Py_ssize_t len = PyList_GET_SIZE(list); + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); if (true) { UOP_STAT_INC(uopcode, miss); @@ -9189,7 +9179,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r01: { + case _GUARD_TYPE_VERSION_LOCKED_r01: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -9197,11 +9187,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -9219,7 +9204,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r11: { + case _GUARD_TYPE_VERSION_LOCKED_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -9228,12 +9213,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -9250,7 +9229,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r22: { + case _GUARD_TYPE_VERSION_LOCKED_r22: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -9260,13 +9239,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache1 = owner; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(2); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -9285,7 +9257,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK_r33: { + case _GUARD_TYPE_VERSION_LOCKED_r33: { CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef owner; @@ -9296,14 +9268,6 @@ uint32_t type_version = (uint32_t)CURRENT_OPERAND0_32(); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { - UOP_STAT_INC(uopcode, miss); - _tos_cache2 = owner; - _tos_cache1 = _stack_item_1; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - JUMP_TO_JUMP_TARGET(); - } PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -10153,6 +10117,87 @@ break; } + case _LOCK_OBJECT_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + value = stack_pointer[-1]; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOCK_OBJECT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + value = _stack_item_0; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = value; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOCK_OBJECT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + value = _stack_item_1; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = value; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = value; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOCK_OBJECT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef value; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + value = _stack_item_2; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = value; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = value; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _STORE_ATTR_WITH_HINT_r21: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 5d853998bf6..de036fb964b 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -825,12 +825,10 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(BINARY_OP); - assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); - JUMP_TO_PREDICTED(BINARY_OP); + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); + if (index < 0) { + index += PyList_GET_SIZE(list); } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; #ifdef Py_GIL_DISABLED _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index); @@ -840,15 +838,13 @@ assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); res = PyStackRef_FromPyObjectSteal(res_o); #else - if (index >= PyList_GET_SIZE(list)) { + if (index < 0 || index >= PyList_GET_SIZE(list)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - STAT_INC(BINARY_OP, hit); PyObject *res_o = PyList_GET_ITEM(list, index); assert(res_o != NULL); res = PyStackRef_FromPyObjectNew(res_o); @@ -10976,21 +10972,25 @@ next_instr += 5; INSTRUCTION_STATS(STORE_ATTR_INSTANCE_VALUE); static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); - _PyStackRef owner; _PyStackRef value; + _PyStackRef owner; _PyStackRef o; /* Skip 1 cache entry */ - // _GUARD_TYPE_VERSION_AND_LOCK + // _LOCK_OBJECT { - owner = stack_pointer[-1]; - uint32_t type_version = read_u32(&this_instr[2].cache); - PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); - assert(type_version != 0); - if (!LOCK_OBJECT(owner_o)) { + value = stack_pointer[-1]; + if (!LOCK_OBJECT(PyStackRef_AsPyObjectBorrow(value))) { UPDATE_MISS_STATS(STORE_ATTR); assert(_PyOpcode_Deopt[opcode] == (STORE_ATTR)); JUMP_TO_PREDICTED(STORE_ATTR); } + } + // _GUARD_TYPE_VERSION_LOCKED + { + owner = value; + uint32_t type_version = read_u32(&this_instr[2].cache); + PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); + assert(type_version != 0); PyTypeObject *tp = Py_TYPE(owner_o); if (FT_ATOMIC_LOAD_UINT_RELAXED(tp->tp_version_tag) != type_version) { UNLOCK_OBJECT(owner_o); @@ -11614,18 +11614,17 @@ PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); assert(PyLong_CheckExact(sub)); assert(PyList_CheckExact(list)); - if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { - UPDATE_MISS_STATS(STORE_SUBSCR); - assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); - JUMP_TO_PREDICTED(STORE_SUBSCR); - } - Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub); if (!LOCK_OBJECT(list)) { UPDATE_MISS_STATS(STORE_SUBSCR); assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); JUMP_TO_PREDICTED(STORE_SUBSCR); } - if (index >= PyList_GET_SIZE(list)) { + Py_ssize_t len = PyList_GET_SIZE(list); + if (index < 0) { + index += len; + } + if (index < 0 || index >= len) { UNLOCK_OBJECT(list); if (true) { UPDATE_MISS_STATS(STORE_SUBSCR); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index f996c1f6cc7..fe083411b7b 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1929,7 +1929,7 @@ break; } - case _GUARD_TYPE_VERSION_AND_LOCK: { + case _GUARD_TYPE_VERSION_LOCKED: { break; } @@ -2099,6 +2099,10 @@ break; } + case _LOCK_OBJECT: { + break; + } + case _STORE_ATTR_WITH_HINT: { JitOptRef owner; JitOptRef value; From 7836ecc5daf541061de2072070f7371d41b009ee Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Thu, 12 Mar 2026 14:27:07 +0100 Subject: [PATCH 106/775] gh-145681: do not deallocate list buffer in `_PyList_AsTupleAndClear` (GH-145680) Setting the size to 0 turns the list contents into overallocated memory that the deallocator will free. Ownership is transferred to the new tuple so no refcount adjustment is needed. --- Objects/listobject.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Objects/listobject.c b/Objects/listobject.c index 1fcedd3a28c..1cc62764e2f 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3283,10 +3283,8 @@ _PyList_AsTupleAndClear(PyListObject *self) Py_BEGIN_CRITICAL_SECTION(self); PyObject **items = self->ob_item; Py_ssize_t size = Py_SIZE(self); - self->ob_item = NULL; Py_SET_SIZE(self, 0); ret = _PyTuple_FromArraySteal(items, size); - free_list_items(items, false); Py_END_CRITICAL_SECTION(); return ret; } From 17eb0354ff3110b27f811343c2d4b3c85f2685d5 Mon Sep 17 00:00:00 2001 From: bkap123 <97006829+bkap123@users.noreply.github.com> Date: Thu, 12 Mar 2026 09:46:37 -0400 Subject: [PATCH 107/775] gh-145446: Add critical section in functools module for `PyDict_Next` (GH-145487) --- .../2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst | 1 + Modules/_functoolsmodule.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst diff --git a/Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst b/Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst new file mode 100644 index 00000000000..96eb0d9ddb0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst @@ -0,0 +1 @@ +Now :mod:`functools` is safer in free-threaded build when using keywords in :func:`functools.partial` diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 336a2e57ec0..723080ede1d 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -492,12 +492,15 @@ partial_vectorcall(PyObject *self, PyObject *const *args, /* Copy pto_keywords with overlapping call keywords merged * Note, tail is already coppied. */ Py_ssize_t pos = 0, i = 0; - while (PyDict_Next(n_merges ? pto_kw_merged : pto->kw, &pos, &key, &val)) { + PyObject *keyword_dict = n_merges ? pto_kw_merged : pto->kw; + Py_BEGIN_CRITICAL_SECTION(keyword_dict); + while (PyDict_Next(keyword_dict, &pos, &key, &val)) { assert(i < pto_nkwds); PyTuple_SET_ITEM(tot_kwnames, i, Py_NewRef(key)); stack[tot_nargs + i] = val; i++; } + Py_END_CRITICAL_SECTION(); assert(i == pto_nkwds); Py_XDECREF(pto_kw_merged); @@ -728,6 +731,8 @@ partial_repr(PyObject *self) } } /* Pack keyword arguments */ + int error = 0; + Py_BEGIN_CRITICAL_SECTION(kw); for (i = 0; PyDict_Next(kw, &i, &key, &value);) { /* Prevent key.__str__ from deleting the value. */ Py_INCREF(value); @@ -735,9 +740,14 @@ partial_repr(PyObject *self) key, value)); Py_DECREF(value); if (arglist == NULL) { - goto done; + error = 1; + break; } } + Py_END_CRITICAL_SECTION(); + if (error) { + goto done; + } mod = PyType_GetModuleName(Py_TYPE(pto)); if (mod == NULL) { From d4cc553294a558d632a2f69523eb04fa8c51f1a7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 12 Mar 2026 15:04:36 +0100 Subject: [PATCH 108/775] gh-141510: Update PyDict C API doc for frozendict (#145533) Mention frozendict support. --- Doc/c-api/dict.rst | 67 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index d63c2686589..f44c18e8075 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -42,6 +42,12 @@ Dictionary objects enforces read-only behavior. This is normally used to create a view to prevent modification of the dictionary for non-dynamic class types. + The first argument can be a :class:`dict`, a :class:`frozendict`, or a + mapping. + + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:var:: PyTypeObject PyDictProxy_Type @@ -68,6 +74,11 @@ Dictionary objects *key*, return ``1``, otherwise return ``0``. On error, return ``-1``. This is equivalent to the Python expression ``key in p``. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: int PyDict_ContainsString(PyObject *p, const char *key) @@ -75,8 +86,13 @@ Dictionary objects :c:expr:`const char*` UTF-8 encoded bytes string, rather than a :c:expr:`PyObject*`. + The first argument can be a :class:`dict` or a :class:`frozendict`. + .. versionadded:: 3.13 + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_Copy(PyObject *p) @@ -122,8 +138,13 @@ Dictionary objects * If the key is missing, set *\*result* to ``NULL`` and return ``0``. * On error, raise an exception and return ``-1``. + The first argument can be a :class:`dict` or a :class:`frozendict`. + .. versionadded:: 3.13 + .. versionchanged:: next + Also accept :class:`frozendict`. + See also the :c:func:`PyObject_GetItem` function. @@ -133,6 +154,8 @@ Dictionary objects has a key *key*. Return ``NULL`` if the key *key* is missing *without* setting an exception. + The first argument can be a :class:`dict` or a :class:`frozendict`. + .. note:: Exceptions that occur while this calls :meth:`~object.__hash__` and @@ -143,6 +166,9 @@ Dictionary objects Calling this API without an :term:`attached thread state` had been allowed for historical reason. It is no longer allowed. + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_GetItemWithError(PyObject *p, PyObject *key) @@ -151,6 +177,9 @@ Dictionary objects occurred. Return ``NULL`` **without** an exception set if the key wasn't present. + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_GetItemString(PyObject *p, const char *key) @@ -166,6 +195,9 @@ Dictionary objects Prefer using the :c:func:`PyDict_GetItemWithError` function with your own :c:func:`PyUnicode_FromString` *key* instead. + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result) @@ -175,6 +207,9 @@ Dictionary objects .. versionadded:: 3.13 + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *defaultobj) @@ -238,17 +273,32 @@ Dictionary objects Return a :c:type:`PyListObject` containing all the items from the dictionary. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_Keys(PyObject *p) Return a :c:type:`PyListObject` containing all the keys from the dictionary. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: PyObject* PyDict_Values(PyObject *p) Return a :c:type:`PyListObject` containing all the values from the dictionary *p*. + The first argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: Py_ssize_t PyDict_Size(PyObject *p) @@ -257,11 +307,19 @@ Dictionary objects Return the number of items in the dictionary. This is equivalent to ``len(p)`` on a dictionary. + The argument can be a :class:`dict` or a :class:`frozendict`. + + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: Py_ssize_t PyDict_GET_SIZE(PyObject *p) Similar to :c:func:`PyDict_Size`, but without error checking. + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) @@ -276,6 +334,8 @@ Dictionary objects value represents offsets within the internal dictionary structure, and since the structure is sparse, the offsets are not consecutive. + The first argument can be a :class:`dict` or a :class:`frozendict`. + For example:: PyObject *key, *value; @@ -309,7 +369,7 @@ Dictionary objects } The function is not thread-safe in the :term:`free-threaded ` - build without external synchronization. You can use + build without external synchronization for a mutable :class:`dict`. You can use :c:macro:`Py_BEGIN_CRITICAL_SECTION` to lock the dictionary while iterating over it:: @@ -319,6 +379,8 @@ Dictionary objects } Py_END_CRITICAL_SECTION(); + The function is thread-safe on a :class:`frozendict`. + .. note:: On the free-threaded build, this function can be used safely inside a @@ -329,6 +391,9 @@ Dictionary objects :term:`strong reference ` (for example, using :c:func:`Py_NewRef`). + .. versionchanged:: next + Also accept :class:`frozendict`. + .. c:function:: int PyDict_Merge(PyObject *a, PyObject *b, int override) Iterate over mapping object *b* adding key-value pairs to dictionary *a*. From e13f6dccd7a2f8df543a18c4a3ad92610dc087cb Mon Sep 17 00:00:00 2001 From: Tan Long Date: Thu, 12 Mar 2026 23:59:43 +0800 Subject: [PATCH 109/775] gh-140131: Fix REPL cursor position on Windows when module completion suggestion line hits console width (GH-140333) --- Lib/_pyrepl/windows_console.py | 17 +++---- Lib/test/test_pyrepl/test_pyrepl.py | 46 ++++++++++++++++++- ...-02-11-21-01-30.gh-issue-144259.OAhOR8.rst | 1 + ...-10-19-23-44-46.gh-issue-140131.AABF2k.rst | 2 + 4 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst create mode 100644 Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py index 6c949c04687..cb1834168e8 100644 --- a/Lib/_pyrepl/windows_console.py +++ b/Lib/_pyrepl/windows_console.py @@ -270,18 +270,13 @@ def __write_changed_line( self._erase_to_end() self.__write(newline[x_pos:]) - if wlen(newline) == self.width: - # If we wrapped we want to start at the next line - self._move_relative(0, y + 1) - self.posxy = 0, y + 1 - else: - self.posxy = wlen(newline), y + self.posxy = min(wlen(newline), self.width - 1), y - if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline: - # ANSI escape characters are present, so we can't assume - # anything about the position of the cursor. Moving the cursor - # to the left margin should work to get to a known position. - self.move_cursor(0, y) + if "\x1b" in newline or y != self.posxy[1] or '\x1a' in newline: + # ANSI escape characters are present, so we can't assume + # anything about the position of the cursor. Moving the cursor + # to the left margin should work to get to a known position. + self.move_cursor(0, y) def _scroll( self, top: int, bottom: int, left: int | None = None, right: int | None = None diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 35a1733787e..082215da0a3 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -12,7 +12,7 @@ import tempfile from pkgutil import ModuleInfo from unittest import TestCase, skipUnless, skipIf, SkipTest -from unittest.mock import patch +from unittest.mock import Mock, patch from test.support import force_not_colorized, make_clean_env, Py_DEBUG from test.support import has_subprocess_support, SHORT_TIMEOUT, STDLIB_DIR from test.support.import_helper import import_module @@ -2105,3 +2105,47 @@ def test_ctrl_d_single_line_end_no_newline(self): ) reader, _ = handle_all_events(events) self.assertEqual("hello", "".join(reader.buffer)) + + +@skipUnless(sys.platform == "win32", "windows console only") +class TestWindowsConsoleEolWrap(TestCase): + def _make_mock_console(self, width=80): + from _pyrepl import windows_console as wc + + console = object.__new__(wc.WindowsConsole) + + console.width = width + console.posxy = (0, 0) + console.screen = [""] + + console._hide_cursor = Mock() + console._show_cursor = Mock() + console._erase_to_end = Mock() + console._move_relative = Mock() + console.move_cursor = Mock() + console._WindowsConsole__write = Mock() + + return console, wc + + def test_short_line_sets_posxy_normally(self): + width = 10 + y = 3 + console, wc = self._make_mock_console(width=width) + old_line = "" + new_line = "a" * 3 + wc.WindowsConsole._WindowsConsole__write_changed_line( + console, y, old_line, new_line, 0 + ) + self.assertEqual(console.posxy, (3, y)) + + def test_exact_width_line_does_not_wrap(self): + width = 10 + y = 3 + console, wc = self._make_mock_console(width=width) + old_line = "" + new_line = "a" * width + + wc.WindowsConsole._WindowsConsole__write_changed_line( + console, y, old_line, new_line, 0 + ) + self.assertEqual(console.posxy, (width - 1, y)) diff --git a/Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst b/Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst new file mode 100644 index 00000000000..280f3b742b0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst @@ -0,0 +1 @@ +Fix inconsistent display of long multiline pasted content in the REPL. diff --git a/Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst b/Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst new file mode 100644 index 00000000000..3c2d30d8d98 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst @@ -0,0 +1,2 @@ +Fix REPL cursor position on Windows when module completion suggestion line +hits console width. From 7a65900764e27c5f9b4d69e0a117777a757f2d22 Mon Sep 17 00:00:00 2001 From: Charlie Lin Date: Thu, 12 Mar 2026 12:56:07 -0400 Subject: [PATCH 110/775] gh-145717: Add a few Microsoft-specific MIME types, and synchronize between `mimetypes` module and tests (#145718) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Petr Viktorin --- Doc/whatsnew/3.15.rst | 8 ++++++++ Lib/mimetypes.py | 3 +++ .../2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst | 1 + 3 files changed, 12 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index c979118abd0..7daea13d31c 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -828,6 +828,14 @@ mimetypes * Add ``application/sql`` and ``application/vnd.sqlite3``. (Contributed by Charlie Lin in :gh:`145698`.) * Add ``image/jxl``. (Contributed by Foolbar in :gh:`144213`.) +* Add the following MIME types: + + - ``application/vnd.ms-cab-compressed`` for ``.cab`` extension + - ``application/vnd.ms-htmlhelp`` for ``.chm`` extension + - ``application/vnd.ms-officetheme`` for ``.thmx`` extension + + (Contributed by Charlie Lin in :gh:`145718`.) + * Rename ``application/x-texinfo`` to ``application/texinfo``. (Contributed by Charlie Lin in :gh:`140165`.) * Changed the MIME type for ``.ai`` files to ``application/pdf``. diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index ee66160be63..60e8c2be1e2 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -510,9 +510,12 @@ def _default_mime_types(): '.m3u8' : 'application/vnd.apple.mpegurl', '.dll' : 'application/vnd.microsoft.portable-executable', '.exe' : 'application/vnd.microsoft.portable-executable', + '.cab' : 'application/vnd.ms-cab-compressed', '.xls' : 'application/vnd.ms-excel', '.xlb' : 'application/vnd.ms-excel', '.eot' : 'application/vnd.ms-fontobject', + '.chm' : 'application/vnd.ms-htmlhelp', + '.thmx' : 'application/vnd.ms-officetheme', '.ppt' : 'application/vnd.ms-powerpoint', '.pot' : 'application/vnd.ms-powerpoint', '.ppa' : 'application/vnd.ms-powerpoint', diff --git a/Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst b/Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst new file mode 100644 index 00000000000..55ef5206c99 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst @@ -0,0 +1 @@ +Add a few Microsoft-specific MIME types. From cd5217283112d41c0244e2d96302cbe33f0b4cb1 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Thu, 12 Mar 2026 13:30:36 -0400 Subject: [PATCH 111/775] gh-145685: Improve scaling of type attribute lookups (gh-145774) Avoid locking in the PyType_Lookup cache-miss path if the type's tp_version_tag is already valid. --- .../internal/pycore_pyatomic_ft_wrappers.h | 3 + ...-03-10-12-52-06.gh-issue-145685.80B7gK.rst | 2 + Objects/typeobject.c | 56 ++++++++++--------- 3 files changed, 36 insertions(+), 25 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index 70a32db663b..c0f859a23e1 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -95,6 +95,8 @@ extern "C" { _Py_atomic_store_int_relaxed(&value, new_value) #define FT_ATOMIC_LOAD_INT_RELAXED(value) \ _Py_atomic_load_int_relaxed(&value) +#define FT_ATOMIC_LOAD_UINT(value) \ + _Py_atomic_load_uint(&value) #define FT_ATOMIC_STORE_UINT_RELAXED(value, new_value) \ _Py_atomic_store_uint_relaxed(&value, new_value) #define FT_ATOMIC_LOAD_UINT_RELAXED(value) \ @@ -167,6 +169,7 @@ extern "C" { #define FT_ATOMIC_STORE_INT(value, new_value) value = new_value #define FT_ATOMIC_LOAD_INT_RELAXED(value) value #define FT_ATOMIC_STORE_INT_RELAXED(value, new_value) value = new_value +#define FT_ATOMIC_LOAD_UINT(value) value #define FT_ATOMIC_LOAD_UINT_RELAXED(value) value #define FT_ATOMIC_STORE_UINT_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_LOAD_LONG_RELAXED(value) value diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst new file mode 100644 index 00000000000..da34b67c952 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst @@ -0,0 +1,2 @@ +Improve scaling of type attribute lookups in the :term:`free-threaded build` by +avoiding contention on the internal type lock. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index bb473dce68f..2a818f5f020 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -52,8 +52,8 @@ class object "PyObject *" "&PyBaseObject_Type" MCACHE_HASH(FT_ATOMIC_LOAD_UINT_RELAXED((type)->tp_version_tag), \ ((Py_ssize_t)(name)) >> 3) #define MCACHE_CACHEABLE_NAME(name) \ - PyUnicode_CheckExact(name) && \ - (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE) + (PyUnicode_CheckExact(name) && \ + (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)) #define NEXT_VERSION_TAG(interp) \ (interp)->types.next_version_tag @@ -6134,6 +6134,14 @@ _PyType_LookupRefAndVersion(PyTypeObject *type, PyObject *name, unsigned int *ve return PyStackRef_AsPyObjectSteal(out); } +static int +should_assign_version_tag(PyTypeObject *type, PyObject *name, unsigned int version_tag) +{ + return (version_tag == 0 + && FT_ATOMIC_LOAD_UINT16_RELAXED(type->tp_versions_used) < MAX_VERSIONS_PER_CLASS + && MCACHE_CACHEABLE_NAME(name)); +} + unsigned int _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out) { @@ -6182,24 +6190,20 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef /* We may end up clearing live exceptions below, so make sure it's ours. */ assert(!PyErr_Occurred()); - // We need to atomically do the lookup and capture the version before - // anyone else can modify our mro or mutate the type. - int res; PyInterpreterState *interp = _PyInterpreterState_GET(); - int has_version = 0; - unsigned int assigned_version = 0; - BEGIN_TYPE_LOCK(); - // We must assign the version before doing the lookup. If - // find_name_in_mro() blocks and releases the critical section - // then the type version can change. - if (MCACHE_CACHEABLE_NAME(name)) { - has_version = assign_version_tag(interp, type); - assigned_version = type->tp_version_tag; + unsigned int version_tag = FT_ATOMIC_LOAD_UINT(type->tp_version_tag); + if (should_assign_version_tag(type, name, version_tag)) { + BEGIN_TYPE_LOCK(); + assign_version_tag(interp, type); + version_tag = type->tp_version_tag; + res = find_name_in_mro(type, name, out); + END_TYPE_LOCK(); + } + else { + res = find_name_in_mro(type, name, out); } - res = find_name_in_mro(type, name, out); - END_TYPE_LOCK(); /* Only put NULL results into cache if there was no error. */ if (res < 0) { @@ -6207,16 +6211,18 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef return 0; } - if (has_version) { - PyObject *res_obj = PyStackRef_AsPyObjectBorrow(*out); -#if Py_GIL_DISABLED - update_cache_gil_disabled(entry, name, assigned_version, res_obj); -#else - PyObject *old_value = update_cache(entry, name, assigned_version, res_obj); - Py_DECREF(old_value); -#endif + if (version_tag == 0 || !MCACHE_CACHEABLE_NAME(name)) { + return 0; } - return has_version ? assigned_version : 0; + + PyObject *res_obj = PyStackRef_AsPyObjectBorrow(*out); +#if Py_GIL_DISABLED + update_cache_gil_disabled(entry, name, version_tag, res_obj); +#else + PyObject *old_value = update_cache(entry, name, version_tag, res_obj); + Py_DECREF(old_value); +#endif + return version_tag; } /* Internal API to look for a name through the MRO. From f105265538823126dda5bc113fdb72cb2d5d2dbc Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Fri, 13 Mar 2026 03:16:53 +0500 Subject: [PATCH 112/775] GH-132042: Fix calculation of slotdef index in update_one_slot() (#145880) --- Objects/typeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2a818f5f020..7b4318e79fb 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -11737,7 +11737,7 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, if (Py_IS_TYPE(descr, &PyWrapperDescr_Type) && ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr; - size_t index = (p - slotdefs) / sizeof(slotdefs[0]); + size_t index = (p - slotdefs); if (slotdefs_name_counts[index] == 1) { tptr = slotptr(type, p->offset); } From 08a018ebe0d673e9c352f790d2e4604d69604188 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 12 Mar 2026 23:48:51 +0100 Subject: [PATCH 113/775] gh-145801: Use gcc -fprofile-update=atomic for PGO builds (#145802) When Python build is optimized with GCC using PGO, use -fprofile-update=atomic option to use atomic operations when updating profile information. This option reduces the risk of gcov Data Files (.gcda) corruption which can cause random GCC crashes. --- ...-03-11-11-58-42.gh-issue-145801.iCXa3v.rst | 4 ++ configure | 42 ++++++++++++++++++- configure.ac | 5 ++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst diff --git a/Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst b/Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst new file mode 100644 index 00000000000..c5f3982cc54 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst @@ -0,0 +1,4 @@ +When Python build is optimized with GCC using PGO, use +``-fprofile-update=atomic`` option to use atomic operations when updating +profile information. This option reduces the risk of gcov Data Files (.gcda) +corruption which can cause random GCC crashes. Patch by Victor Stinner. diff --git a/configure b/configure index a3eeef373bf..23f24d51c79 100755 --- a/configure +++ b/configure @@ -9083,7 +9083,47 @@ case "$ac_cv_cc_name" in fi ;; gcc) - PGO_PROF_GEN_FLAG="-fprofile-generate" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fprofile-update=atomic" >&5 +printf %s "checking whether C compiler accepts -fprofile-update=atomic... " >&6; } +if test ${ax_cv_check_cflags___fprofile_update_atomic+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fprofile-update=atomic" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ax_cv_check_cflags___fprofile_update_atomic=yes +else case e in #( + e) ax_cv_check_cflags___fprofile_update_atomic=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS=$ax_check_save_flags ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fprofile_update_atomic" >&5 +printf "%s\n" "$ax_cv_check_cflags___fprofile_update_atomic" >&6; } +if test "x$ax_cv_check_cflags___fprofile_update_atomic" = xyes +then : + PGO_PROF_GEN_FLAG="-fprofile-generate -fprofile-update=atomic" +else case e in #( + e) PGO_PROF_GEN_FLAG="-fprofile-generate" ;; +esac +fi + PGO_PROF_USE_FLAG="-fprofile-use -fprofile-correction" LLVM_PROF_MERGER="true" LLVM_PROF_FILE="" diff --git a/configure.ac b/configure.ac index 75e81761f95..635fce3f2e6 100644 --- a/configure.ac +++ b/configure.ac @@ -2084,7 +2084,10 @@ case "$ac_cv_cc_name" in fi ;; gcc) - PGO_PROF_GEN_FLAG="-fprofile-generate" + AX_CHECK_COMPILE_FLAG( + [-fprofile-update=atomic], + [PGO_PROF_GEN_FLAG="-fprofile-generate -fprofile-update=atomic"], + [PGO_PROF_GEN_FLAG="-fprofile-generate"]) PGO_PROF_USE_FLAG="-fprofile-use -fprofile-correction" LLVM_PROF_MERGER="true" LLVM_PROF_FILE="" From 0adc7289c3ab097b5608c0d288d91e1f5f236469 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Fri, 13 Mar 2026 01:53:29 +0000 Subject: [PATCH 114/775] Revert "gh-143050: Remove redundant decref in _PyLong_Negate (gh-143051)" (#145891) OSS Fuzzer caught an assertion failure. This reverts commit 5197ecb5e4df30ba0f6792d8bc0e36846154f58a. --- Objects/longobject.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 185226db43a..7ce5d0535b8 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -48,17 +48,6 @@ _Py_DECREF_INT(PyLongObject *op) _Py_DECREF_SPECIALIZED((PyObject *)op, _PyLong_ExactDealloc); } -static inline int -/// Return 1 if the object is one of the immortal small ints -_long_is_small_int(PyObject *op) -{ - assert(PyLong_Check(op)); - PyLongObject *long_object = (PyLongObject *)op; - int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; - assert((!is_small_int) || PyLong_CheckExact(op)); - return is_small_int; -} - static inline int is_medium_int(stwodigits x) { @@ -355,6 +344,8 @@ medium_from_stwodigits(stwodigits x) } +/* If a freshly-allocated int is already shared, it must + be a small integer, so negating it must go to PyLong_FromLong */ Py_LOCAL_INLINE(void) _PyLong_Negate(PyLongObject **x_p) { @@ -366,10 +357,8 @@ _PyLong_Negate(PyLongObject **x_p) return; } - /* If a freshly-allocated int is already shared, it must - be a small integer, so negating it will fit a single digit */ - assert(_long_is_small_int((PyObject *)x)); - *x_p = (PyLongObject *)_PyLong_FromSTwoDigits(-medium_value(x)); + *x_p = _PyLong_FromSTwoDigits(-medium_value(x)); + Py_DECREF(x); } #define PYLONG_FROM_INT(UINT_TYPE, INT_TYPE, ival) \ @@ -3633,6 +3622,16 @@ long_richcompare(PyObject *self, PyObject *other, int op) Py_RETURN_RICHCOMPARE(result, 0, op); } +static inline int +/// Return 1 if the object is one of the immortal small ints +_long_is_small_int(PyObject *op) +{ + PyLongObject *long_object = (PyLongObject *)op; + int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; + assert((!is_small_int) || PyLong_CheckExact(op)); + return is_small_int; +} + void _PyLong_ExactDealloc(PyObject *self) { From 6d1e9ceed3e70ebc39953f5ad4f20702ffa32119 Mon Sep 17 00:00:00 2001 From: Maurizio Sambati Date: Fri, 13 Mar 2026 10:40:20 +0100 Subject: [PATCH 115/775] Docs: except with multiple exceptions parentheses not required (#145848) As of PEP 758 the except statement doesn't require parentheses anymore for exception tuples. See: https://peps.python.org/pep-0758/ --- Doc/tutorial/errors.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/errors.rst b/Doc/tutorial/errors.rst index 1c20fa2f0b6..ae21dfdbf0a 100644 --- a/Doc/tutorial/errors.rst +++ b/Doc/tutorial/errors.rst @@ -121,9 +121,9 @@ A :keyword:`try` statement may have more than one *except clause*, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding *try clause*, not in other handlers of the same :keyword:`!try` statement. An *except clause* -may name multiple exceptions as a parenthesized tuple, for example:: +may name multiple exceptions, for example:: - ... except (RuntimeError, TypeError, NameError): + ... except RuntimeError, TypeError, NameError: ... pass A class in an :keyword:`except` clause matches exceptions which are instances of the From e1c224624ae601c464acbf173e2aa90fa980ab45 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Fri, 13 Mar 2026 11:05:20 +0000 Subject: [PATCH 116/775] gh-145783: Propagate errors raised in `NEW_TYPE_COMMENT` (#145784) --- Lib/test/test_type_comments.py | 8 + ...-03-10-19-00-39.gh-issue-145783.dS5TM9.rst | 2 + Modules/_testcapimodule.c | 13 + Parser/parser.c | 1070 ++++++++--------- Tools/peg_generator/pegen/c_generator.py | 2 +- 5 files changed, 559 insertions(+), 536 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst diff --git a/Lib/test/test_type_comments.py b/Lib/test/test_type_comments.py index c40c45594f4..dd2e6784165 100644 --- a/Lib/test/test_type_comments.py +++ b/Lib/test/test_type_comments.py @@ -1,6 +1,7 @@ import ast import sys import unittest +from test.support import import_helper funcdef = """\ @@ -391,6 +392,13 @@ def check_both_ways(source): check_both_ways("pass # type: ignorewhatever\n") check_both_ways("pass # type: ignoreé\n") + def test_non_utf8_type_comment_with_ignore_cookie(self): + _testcapi = import_helper.import_module('_testcapi') + flags = 0x0800 | 0x1000 # PyCF_IGNORE_COOKIE | PyCF_TYPE_COMMENTS + with self.assertRaises(UnicodeDecodeError): + _testcapi.Py_CompileStringExFlags( + b"a=1 # type: \x80", "", 256, flags) + def test_func_type_input(self): def parse_func_type_input(source): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst new file mode 100644 index 00000000000..ce9aa286068 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst @@ -0,0 +1,2 @@ +Fix an unlikely crash in the parser when certain errors were erroneously not +propagated. Found by OSS Fuzz in :oss-fuzz:`491369109`. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c0ab35cda19..a25b127f101 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -226,6 +226,18 @@ pycompilestring(PyObject* self, PyObject *obj) { return Py_CompileString(the_string, "", Py_file_input); } +static PyObject* +pycompilestringexflags(PyObject *self, PyObject *args) { + const char *the_string, *filename; + int start, flags; + if (!PyArg_ParseTuple(args, "ysii", &the_string, &filename, &start, &flags)) { + return NULL; + } + PyCompilerFlags cf = _PyCompilerFlags_INIT; + cf.cf_flags = flags; + return Py_CompileStringExFlags(the_string, filename, start, &cf, -1); +} + static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -2659,6 +2671,7 @@ static PyMethodDef TestMethods[] = { {"return_result_with_error", return_result_with_error, METH_NOARGS}, {"getitem_with_error", getitem_with_error, METH_VARARGS}, {"Py_CompileString", pycompilestring, METH_O}, + {"Py_CompileStringExFlags", pycompilestringexflags, METH_VARARGS}, {"raise_SIGINT_then_send_None", raise_SIGINT_then_send_None, METH_VARARGS}, {"stack_pointer", stack_pointer, METH_NOARGS}, #ifdef W_STOPCODE diff --git a/Parser/parser.c b/Parser/parser.c index f8d6d1ce89b..f853d309de9 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -1030,7 +1030,7 @@ file_rule(Parser *p) { D(fprintf(stderr, "%*c+ file[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statements? $")); _res = _PyPegen_make_module ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1073,7 +1073,7 @@ interactive_rule(Parser *p) { D(fprintf(stderr, "%*c+ interactive[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statement_newline")); _res = _PyAST_Interactive ( a , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1122,7 +1122,7 @@ eval_rule(Parser *p) { D(fprintf(stderr, "%*c+ eval[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions NEWLINE* $")); _res = _PyAST_Expression ( a , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1183,7 +1183,7 @@ func_type_rule(Parser *p) { D(fprintf(stderr, "%*c+ func_type[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' type_expressions? ')' '->' expression NEWLINE* $")); _res = _PyAST_FunctionType ( a , b , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1226,7 +1226,7 @@ statements_rule(Parser *p) { D(fprintf(stderr, "%*c+ statements[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statement+")); _res = ( asdl_stmt_seq* ) _PyPegen_seq_flatten ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1269,7 +1269,7 @@ statement_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "compound_stmt")); _res = _PyPegen_register_stmts ( p , ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1293,7 +1293,7 @@ statement_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmts")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1336,7 +1336,7 @@ single_compound_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ single_compound_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "compound_stmt")); _res = _PyPegen_register_stmts ( p , ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1391,7 +1391,7 @@ statement_newline_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_compound_stmt NEWLINE")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1443,7 +1443,7 @@ statement_newline_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , CHECK ( stmt_ty , _PyAST_Pass ( EXTRA ) ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1467,7 +1467,7 @@ statement_newline_rule(Parser *p) { D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "$")); _res = _PyPegen_interactive_exit ( p ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1515,7 +1515,7 @@ simple_stmts_rule(Parser *p) { D(fprintf(stderr, "%*c+ simple_stmts[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmt !';' NEWLINE")); _res = ( asdl_stmt_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1546,7 +1546,7 @@ simple_stmts_rule(Parser *p) { D(fprintf(stderr, "%*c+ simple_stmts[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "';'.simple_stmt+ ';'? NEWLINE")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -1686,7 +1686,7 @@ simple_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Expr ( e , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2165,7 +2165,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotation syntax is" , _PyAST_AnnAssign ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , c , 1 , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2207,7 +2207,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotations syntax is" , _PyAST_AnnAssign ( a , b , c , 0 , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2248,7 +2248,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Assign ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2290,7 +2290,7 @@ assignment_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_AugAssign ( a , b -> kind , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2426,7 +2426,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+='")); _res = _PyPegen_augoperator ( p , Add ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2450,7 +2450,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-='")); _res = _PyPegen_augoperator ( p , Sub ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2474,7 +2474,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*='")); _res = _PyPegen_augoperator ( p , Mult ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2498,7 +2498,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@='")); _res = CHECK_VERSION ( AugOperator* , 5 , "The '@' operator is" , _PyPegen_augoperator ( p , MatMult ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2522,7 +2522,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/='")); _res = _PyPegen_augoperator ( p , Div ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2546,7 +2546,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%='")); _res = _PyPegen_augoperator ( p , Mod ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2570,7 +2570,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'&='")); _res = _PyPegen_augoperator ( p , BitAnd ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2594,7 +2594,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|='")); _res = _PyPegen_augoperator ( p , BitOr ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2618,7 +2618,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'^='")); _res = _PyPegen_augoperator ( p , BitXor ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2642,7 +2642,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'<<='")); _res = _PyPegen_augoperator ( p , LShift ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2666,7 +2666,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'>>='")); _res = _PyPegen_augoperator ( p , RShift ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2690,7 +2690,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**='")); _res = _PyPegen_augoperator ( p , Pow ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2714,7 +2714,7 @@ augassign_rule(Parser *p) { D(fprintf(stderr, "%*c+ augassign[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//='")); _res = _PyPegen_augoperator ( p , FloorDiv ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2778,7 +2778,7 @@ return_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Return ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2852,7 +2852,7 @@ raise_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Raise ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2907,7 +2907,7 @@ raise_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Raise ( a , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -2940,7 +2940,7 @@ raise_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Raise ( NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3001,7 +3001,7 @@ pass_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Pass ( EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3062,7 +3062,7 @@ break_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Break ( EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3123,7 +3123,7 @@ continue_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Continue ( EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3187,7 +3187,7 @@ global_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Global ( CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3251,7 +3251,7 @@ nonlocal_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Nonlocal ( CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3317,7 +3317,7 @@ del_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Delete ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3397,7 +3397,7 @@ yield_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Expr ( y , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3483,7 +3483,7 @@ assert_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Assert ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3631,7 +3631,7 @@ import_name_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Import ( a , lazy ? 1 : 0 , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3709,7 +3709,7 @@ import_from_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_checked_future_import ( p , b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , lazy , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3754,7 +3754,7 @@ import_from_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ImportFrom ( NULL , b , _PyPegen_seq_count_dots ( a ) , lazy ? 1 : 0 , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3820,7 +3820,7 @@ import_from_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' import_from_as_names ','? ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3874,7 +3874,7 @@ import_from_targets_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = ( asdl_alias_seq* ) _PyPegen_singleton_seq ( p , CHECK ( alias_ty , _PyPegen_alias_for_star ( p , EXTRA ) ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -3936,7 +3936,7 @@ import_from_as_names_rule(Parser *p) { D(fprintf(stderr, "%*c+ import_from_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4019,7 +4019,7 @@ import_from_as_name_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4062,7 +4062,7 @@ dotted_as_names_rule(Parser *p) { D(fprintf(stderr, "%*c+ dotted_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4145,7 +4145,7 @@ dotted_as_name_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4230,7 +4230,7 @@ dotted_name_raw(Parser *p) { D(fprintf(stderr, "%*c+ dotted_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name '.' NAME")); _res = _PyPegen_join_names_with_dot ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4305,7 +4305,7 @@ block_rule(Parser *p) { D(fprintf(stderr, "%*c+ block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT statements DEDENT")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4387,7 +4387,7 @@ decorators_rule(Parser *p) { D(fprintf(stderr, "%*c+ decorators[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4433,7 +4433,7 @@ class_def_rule(Parser *p) { D(fprintf(stderr, "%*c+ class_def[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "decorators class_def_raw")); _res = _PyPegen_class_def_decorators ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4549,7 +4549,7 @@ class_def_raw_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , t , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4595,7 +4595,7 @@ function_def_rule(Parser *p) { D(fprintf(stderr, "%*c+ function_def[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "decorators function_def_raw")); _res = _PyPegen_function_def_decorators ( p , d , f ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4724,7 +4724,7 @@ function_def_raw_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , t , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4787,7 +4787,7 @@ function_def_raw_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , t , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4901,7 +4901,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default param_no_default* param_with_default* star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , a , NULL , b , c , d ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4931,7 +4931,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default param_with_default* star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4961,7 +4961,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default+ param_with_default* star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -4988,7 +4988,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+ star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5012,7 +5012,7 @@ parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_etc")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5061,7 +5061,7 @@ slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' ','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5090,7 +5090,7 @@ slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' &')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5144,7 +5144,7 @@ slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' ','")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5176,7 +5176,7 @@ slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' &')'")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5252,7 +5252,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' param_no_default param_maybe_default* kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5285,7 +5285,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' param_no_default_star_annotation param_maybe_default* kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5318,7 +5318,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' param_maybe_default+ kwds?")); _res = _PyPegen_star_etc ( p , NULL , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5342,7 +5342,7 @@ star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwds")); _res = _PyPegen_star_etc ( p , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5407,7 +5407,7 @@ kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param_no_default")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5456,7 +5456,7 @@ param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param ',' TYPE_COMMENT?")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5485,7 +5485,7 @@ param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param TYPE_COMMENT? &')'")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5536,7 +5536,7 @@ param_no_default_star_annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default_star_annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_star_annotation ',' TYPE_COMMENT?")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5565,7 +5565,7 @@ param_no_default_star_annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_no_default_star_annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_star_annotation TYPE_COMMENT? &')'")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5617,7 +5617,7 @@ param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default ',' TYPE_COMMENT?")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5649,7 +5649,7 @@ param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default TYPE_COMMENT? &')'")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5703,7 +5703,7 @@ param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default? ',' TYPE_COMMENT?")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5735,7 +5735,7 @@ param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default? TYPE_COMMENT? &')'")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5799,7 +5799,7 @@ param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_arg ( a -> v . Name . id , b , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5863,7 +5863,7 @@ param_star_annotation_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_arg ( a -> v . Name . id , b , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5909,7 +5909,7 @@ annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -5955,7 +5955,7 @@ star_annotation_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_annotation[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' star_expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6001,7 +6001,7 @@ default_rule(Parser *p) { D(fprintf(stderr, "%*c+ default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6115,7 +6115,7 @@ if_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq* , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6160,7 +6160,7 @@ if_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6255,7 +6255,7 @@ elif_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq* , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6300,7 +6300,7 @@ elif_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_If ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6368,7 +6368,7 @@ else_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ else_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' &&':' block")); _res = b; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6460,7 +6460,7 @@ while_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_While ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6568,7 +6568,7 @@ for_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_For ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6632,7 +6632,7 @@ for_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async for loops are" , _PyAST_AsyncFor ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6763,7 +6763,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6808,7 +6808,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6863,7 +6863,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NULL , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6911,7 +6911,7 @@ with_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -6984,7 +6984,7 @@ with_item_rule(Parser *p) { D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); _res = _PyAST_withitem ( e , t , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7027,7 +7027,7 @@ with_item_rule(Parser *p) { D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression")); _res = _PyAST_withitem ( e , NULL , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7120,7 +7120,7 @@ try_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Try ( b , NULL , NULL , f , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7168,7 +7168,7 @@ try_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Try ( b , ex , el , f , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7216,7 +7216,7 @@ try_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 11 , "Exception groups are" , _PyAST_TryStar ( b , ex , el , f , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7311,7 +7311,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7359,7 +7359,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , ( ( expr_ty ) t ) -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7401,7 +7401,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( excepthandler_ty , 14 , "except expressions without parentheses are" , _PyAST_ExceptHandler ( e , NULL , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7440,7 +7440,7 @@ except_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( NULL , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7556,7 +7556,7 @@ except_star_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7607,7 +7607,7 @@ except_star_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ExceptHandler ( e , ( ( expr_ty ) t ) -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7652,7 +7652,7 @@ except_star_block_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( excepthandler_ty , 14 , "except expressions without parentheses are" , _PyAST_ExceptHandler ( e , NULL , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7739,7 +7739,7 @@ finally_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ finally_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally' &&':' block")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7820,7 +7820,7 @@ match_stmt_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 10 , "Pattern matching is" , _PyAST_Match ( subject , cases , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7906,7 +7906,7 @@ subject_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , value , values ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -7999,7 +7999,7 @@ case_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ case_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block")); _res = _PyAST_match_case ( pattern , guard , body , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8045,7 +8045,7 @@ guard_rule(Parser *p) { D(fprintf(stderr, "%*c+ guard[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression")); _res = guard; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8106,7 +8106,7 @@ patterns_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSequence ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8249,7 +8249,7 @@ as_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchAs ( pattern , target -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8329,7 +8329,7 @@ or_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = asdl_seq_LEN ( patterns ) == 1 ? asdl_seq_GET ( patterns , 0 ) : _PyAST_MatchOr ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8582,7 +8582,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( value , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8615,7 +8615,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( value , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8648,7 +8648,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( value , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8681,7 +8681,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSingleton ( Py_None , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8714,7 +8714,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSingleton ( Py_True , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8747,7 +8747,7 @@ literal_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSingleton ( Py_False , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8875,7 +8875,7 @@ literal_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8908,7 +8908,7 @@ literal_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -8941,7 +8941,7 @@ literal_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9010,7 +9010,7 @@ complex_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( real , Add , imag , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9049,7 +9049,7 @@ complex_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( real , Sub , imag , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9132,7 +9132,7 @@ signed_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( USub , number , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9215,7 +9215,7 @@ signed_real_number_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( USub , real , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9258,7 +9258,7 @@ real_number_rule(Parser *p) { D(fprintf(stderr, "%*c+ real_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NUMBER")); _res = _PyPegen_ensure_real ( p , real ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9301,7 +9301,7 @@ imaginary_number_rule(Parser *p) { D(fprintf(stderr, "%*c+ imaginary_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NUMBER")); _res = _PyPegen_ensure_imaginary ( p , imag ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9362,7 +9362,7 @@ capture_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchAs ( NULL , target -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9409,7 +9409,7 @@ pattern_capture_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ pattern_capture_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); _res = _PyPegen_set_expr_context ( p , name , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9470,7 +9470,7 @@ wildcard_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchAs ( NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9533,7 +9533,7 @@ value_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchValue ( attr , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9636,7 +9636,7 @@ attr_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( value , attr -> v . Name . id , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9743,7 +9743,7 @@ group_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ group_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' pattern ')'")); _res = pattern; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9810,7 +9810,7 @@ sequence_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSequence ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9849,7 +9849,7 @@ sequence_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchSequence ( patterns , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9898,7 +9898,7 @@ open_sequence_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ open_sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern ',' maybe_sequence_pattern?")); _res = _PyPegen_seq_insert_in_front ( p , pattern , patterns ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -9945,7 +9945,7 @@ maybe_sequence_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ maybe_sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.maybe_star_pattern+ ','?")); _res = patterns; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10070,7 +10070,7 @@ star_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchStar ( target -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10106,7 +10106,7 @@ star_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchStar ( NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10176,7 +10176,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( NULL , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10219,7 +10219,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( NULL , NULL , rest -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10268,7 +10268,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , items ) ) , rest -> v . Name . id , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10311,7 +10311,7 @@ mapping_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , items ) ) , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10417,7 +10417,7 @@ key_value_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ key_value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(literal_expr | attr) ':' pattern")); _res = _PyPegen_key_pattern_pair ( p , key , pattern ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10463,7 +10463,7 @@ double_star_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ double_star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' pattern_capture_target")); _res = target; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10535,7 +10535,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , NULL , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10581,7 +10581,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , patterns , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10627,7 +10627,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , NULL , CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10679,7 +10679,7 @@ class_pattern_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_MatchClass ( cls , patterns , CHECK ( asdl_identifier_seq* , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq* , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq* , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10741,7 +10741,7 @@ positional_patterns_rule(Parser *p) { D(fprintf(stderr, "%*c+ positional_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.pattern+")); _res = args; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10828,7 +10828,7 @@ keyword_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ keyword_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' pattern")); _res = _PyPegen_key_pattern_pair ( p , arg , value ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10901,7 +10901,7 @@ type_alias_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( stmt_ty , 12 , "Type statement is" , _PyAST_TypeAlias ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , n , Store ) ) , t , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -10969,7 +10969,7 @@ type_params_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_params[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' type_param_seq ']'")); _res = CHECK_VERSION ( asdl_type_param_seq* , 12 , "Type parameter lists are" , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11016,7 +11016,7 @@ type_param_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_param_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.type_param+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11091,7 +11091,7 @@ type_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_TypeVar ( a -> v . Name . id , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11149,7 +11149,7 @@ type_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_TypeVarTuple ( a -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11188,7 +11188,7 @@ type_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ParamSpec ( a -> v . Name . id , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11235,7 +11235,7 @@ type_param_bound_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_param_bound[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression")); _res = e; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11281,7 +11281,7 @@ type_param_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_param_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' expression")); _res = CHECK_VERSION ( expr_ty , 13 , "Type parameter defaults are" , e ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11327,7 +11327,7 @@ type_param_starred_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_param_starred_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' star_expression")); _res = CHECK_VERSION ( expr_ty , 13 , "Type parameter defaults are" , e ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11395,7 +11395,7 @@ expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11431,7 +11431,7 @@ expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11667,7 +11667,7 @@ if_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_IfExp ( b , a , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11734,7 +11734,7 @@ yield_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_YieldFrom ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11770,7 +11770,7 @@ yield_expr_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Yield ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11841,7 +11841,7 @@ star_expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11877,7 +11877,7 @@ star_expressions_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -11964,7 +11964,7 @@ star_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12031,7 +12031,7 @@ star_named_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_named_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_named_expression+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12078,7 +12078,7 @@ star_named_expressions_sequence_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_named_expressions_sequence[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_named_expression_sequence+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12142,7 +12142,7 @@ star_named_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12290,7 +12290,7 @@ assignment_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( expr_ty , 8 , "Assignment expressions are" , _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12440,7 +12440,7 @@ disjunction_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BoolOp ( Or , CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12528,7 +12528,7 @@ conjunction_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BoolOp ( And , CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12616,7 +12616,7 @@ inversion_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( Not , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12700,7 +12700,7 @@ comparison_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Compare ( a , CHECK ( asdl_int_seq* , _PyPegen_get_cmpops ( p , b ) ) , CHECK ( asdl_expr_seq* , _PyPegen_get_exprs ( p , b ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -12984,7 +12984,7 @@ eq_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ eq_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'==' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Eq , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13030,7 +13030,7 @@ noteq_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ noteq_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , NotEq , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13076,7 +13076,7 @@ lte_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ lte_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'<=' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , LtE , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13122,7 +13122,7 @@ lt_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ lt_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'<' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Lt , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13168,7 +13168,7 @@ gte_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ gte_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'>=' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , GtE , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13214,7 +13214,7 @@ gt_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ gt_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'>' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Gt , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13263,7 +13263,7 @@ notin_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ notin_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'not' 'in' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , NotIn , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13309,7 +13309,7 @@ in_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ in_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'in' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , In , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13358,7 +13358,7 @@ isnot_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ isnot_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'is' 'not' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , IsNot , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13404,7 +13404,7 @@ is_bitwise_or_rule(Parser *p) { D(fprintf(stderr, "%*c+ is_bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'is' bitwise_or")); _res = _PyPegen_cmpop_expr_pair ( p , Is , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13507,7 +13507,7 @@ bitwise_or_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , BitOr , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13629,7 +13629,7 @@ bitwise_xor_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , BitXor , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13751,7 +13751,7 @@ bitwise_and_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , BitAnd , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13873,7 +13873,7 @@ shift_expr_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , LShift , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -13912,7 +13912,7 @@ shift_expr_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , RShift , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14053,7 +14053,7 @@ sum_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Add , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14092,7 +14092,7 @@ sum_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Sub , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14221,7 +14221,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Mult , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14260,7 +14260,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Div , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14299,7 +14299,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , FloorDiv , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14338,7 +14338,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Mod , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14377,7 +14377,7 @@ term_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( expr_ty , 5 , "The '@' operator is" , _PyAST_BinOp ( a , MatMult , b , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14483,7 +14483,7 @@ factor_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( UAdd , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14519,7 +14519,7 @@ factor_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( USub , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14555,7 +14555,7 @@ factor_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_UnaryOp ( Invert , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14642,7 +14642,7 @@ power_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_BinOp ( a , Pow , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14729,7 +14729,7 @@ await_primary_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = CHECK_VERSION ( expr_ty , 5 , "Await expressions are" , _PyAST_Await ( a , EXTRA ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14857,7 +14857,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14893,7 +14893,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq* , ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14935,7 +14935,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -14977,7 +14977,7 @@ primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15050,7 +15050,7 @@ slices_rule(Parser *p) { D(fprintf(stderr, "%*c+ slices[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice !','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15087,7 +15087,7 @@ slices_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15157,7 +15157,7 @@ slice_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Slice ( a , b , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15181,7 +15181,7 @@ slice_rule(Parser *p) { D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15271,7 +15271,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15304,7 +15304,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15337,7 +15337,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15473,7 +15473,7 @@ atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Constant ( Py_Ellipsis , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15522,7 +15522,7 @@ group_rule(Parser *p) { D(fprintf(stderr, "%*c+ group[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (yield_expr | named_expression) ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15611,7 +15611,7 @@ lambdef_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Lambda ( ( a ) ? a : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15725,7 +15725,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , a , NULL , b , c , d ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15755,7 +15755,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default lambda_param_with_default* lambda_star_etc?")); _res = CHECK_VERSION ( arguments_ty , 8 , "Positional-only parameters are" , _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15785,7 +15785,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ lambda_param_with_default* lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15812,7 +15812,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+ lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15836,7 +15836,7 @@ lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_star_etc")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15887,7 +15887,7 @@ lambda_slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' ','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15916,7 +15916,7 @@ lambda_slash_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' &':'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -15970,7 +15970,7 @@ lambda_slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' ','")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16002,7 +16002,7 @@ lambda_slash_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_slash_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' &':'")); _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq* ) a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16077,7 +16077,7 @@ lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16110,7 +16110,7 @@ lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' lambda_param_maybe_default+ lambda_kwds?")); _res = _PyPegen_star_etc ( p , NULL , b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16134,7 +16134,7 @@ lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_kwds")); _res = _PyPegen_star_etc ( p , NULL , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16199,7 +16199,7 @@ lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param_no_default")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16245,7 +16245,7 @@ lambda_param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param ','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16271,7 +16271,7 @@ lambda_param_no_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param &':'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16320,7 +16320,7 @@ lambda_param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default ','")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16349,7 +16349,7 @@ lambda_param_with_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default &':'")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16398,7 +16398,7 @@ lambda_param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default? ','")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16427,7 +16427,7 @@ lambda_param_maybe_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ lambda_param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param default? &':'")); _res = _PyPegen_name_default_pair ( p , a , c , NULL ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16488,7 +16488,7 @@ lambda_param_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_arg ( a -> v . Name . id , NULL , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16550,7 +16550,7 @@ fstring_middle_rule(Parser *p) { D(fprintf(stderr, "%*c+ fstring_middle[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); _res = _PyPegen_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16628,7 +16628,7 @@ fstring_replacement_field_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_formatted_value ( p , a , debug_expr , conversion , format , rbrace , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16693,7 +16693,7 @@ fstring_conversion_rule(Parser *p) { D(fprintf(stderr, "%*c+ fstring_conversion[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"!\" NAME")); _res = _PyPegen_check_fstring_conversion ( p , conv_token , conv ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16757,7 +16757,7 @@ fstring_full_format_spec_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_setup_full_format_spec ( p , colon , ( asdl_expr_seq* ) spec , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16800,7 +16800,7 @@ fstring_format_spec_rule(Parser *p) { D(fprintf(stderr, "%*c+ fstring_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); _res = _PyPegen_decoded_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16868,7 +16868,7 @@ fstring_rule(Parser *p) { D(fprintf(stderr, "%*c+ fstring[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START fstring_middle* FSTRING_END")); _res = _PyPegen_joined_str ( p , a , ( asdl_expr_seq* ) b , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -16946,7 +16946,7 @@ tstring_format_spec_replacement_field_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_formatted_value ( p , a , debug_expr , conversion , format , rbrace , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17008,7 +17008,7 @@ tstring_format_spec_rule(Parser *p) { D(fprintf(stderr, "%*c+ tstring_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TSTRING_MIDDLE")); _res = _PyPegen_decoded_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17091,7 +17091,7 @@ tstring_full_format_spec_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_setup_full_format_spec ( p , colon , ( asdl_expr_seq* ) spec , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17169,7 +17169,7 @@ tstring_replacement_field_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_interpolation ( p , a , debug_expr , conversion , format , rbrace , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17250,7 +17250,7 @@ tstring_middle_rule(Parser *p) { D(fprintf(stderr, "%*c+ tstring_middle[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TSTRING_MIDDLE")); _res = _PyPegen_constant_from_token ( p , t ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17303,7 +17303,7 @@ tstring_rule(Parser *p) { D(fprintf(stderr, "%*c+ tstring[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TSTRING_START tstring_middle* TSTRING_END")); _res = CHECK_VERSION ( expr_ty , 14 , "t-strings are" , _PyPegen_template_str ( p , a , ( asdl_expr_seq* ) b , c ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17347,7 +17347,7 @@ string_rule(Parser *p) { D(fprintf(stderr, "%*c+ string[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING")); _res = _PyPegen_constant_from_string ( p , s ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17431,7 +17431,7 @@ strings_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_concatenate_strings ( p , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17464,7 +17464,7 @@ strings_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_concatenate_tstrings ( p , a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17532,7 +17532,7 @@ list_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_List ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17599,7 +17599,7 @@ tuple_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17666,7 +17666,7 @@ set_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Set ( a , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17733,7 +17733,7 @@ dict_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Dict ( CHECK ( asdl_expr_seq* , _PyPegen_get_keys ( p , a ) ) , CHECK ( asdl_expr_seq* , _PyPegen_get_values ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17805,7 +17805,7 @@ double_starred_kvpairs_rule(Parser *p) { D(fprintf(stderr, "%*c+ double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17851,7 +17851,7 @@ double_starred_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ double_starred_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); _res = _PyPegen_key_value_pair ( p , NULL , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17919,7 +17919,7 @@ kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); _res = _PyPegen_key_value_pair ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -17962,7 +17962,7 @@ for_if_clauses_rule(Parser *p) { D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18027,7 +18027,7 @@ for_if_clause_rule(Parser *p) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async' 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); _res = CHECK_VERSION ( comprehension_ty , 6 , "Async comprehensions are" , _PyAST_comprehension ( a , b , c , 1 , p -> arena ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18070,7 +18070,7 @@ for_if_clause_rule(Parser *p) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); _res = _PyAST_comprehension ( a , b , c , 0 , p -> arena ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18182,7 +18182,7 @@ listcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_ListComp ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18271,7 +18271,7 @@ setcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_SetComp ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18362,7 +18362,7 @@ genexp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_GeneratorExp ( a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18451,7 +18451,7 @@ dictcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_DictComp ( a -> key , a -> value , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18496,7 +18496,7 @@ dictcomp_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_DictComp ( a , NULL , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18549,7 +18549,7 @@ arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','? &')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18635,7 +18635,7 @@ args_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18668,7 +18668,7 @@ args_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( _PyPegen_dummy_name ( p ) , CHECK_NULL_ALLOWED ( asdl_expr_seq* , _PyPegen_seq_extract_starred_exprs ( p , a ) ) , CHECK_NULL_ALLOWED ( asdl_keyword_seq* , _PyPegen_seq_delete_starred_exprs ( p , a ) ) , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18720,7 +18720,7 @@ kwargs_rule(Parser *p) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); _res = _PyPegen_join_sequences ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18844,7 +18844,7 @@ starred_expression_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( a , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18949,7 +18949,7 @@ kwarg_or_starred_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -18973,7 +18973,7 @@ kwarg_or_starred_rule(Parser *p) { D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = _PyPegen_keyword_or_starred ( p , a , 0 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19059,7 +19059,7 @@ kwarg_or_double_starred_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19095,7 +19095,7 @@ kwarg_or_double_starred_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( NULL , a , EXTRA ) ) , 1 ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19149,7 +19149,7 @@ star_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target !','")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19189,7 +19189,7 @@ star_targets_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq* , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19236,7 +19236,7 @@ star_targets_list_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets_list_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19286,7 +19286,7 @@ star_targets_tuple_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets_tuple_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?")); _res = ( asdl_expr_seq* ) _PyPegen_seq_insert_in_front ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19313,7 +19313,7 @@ star_targets_tuple_seq_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_targets_tuple_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ','")); _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19381,7 +19381,7 @@ star_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Starred ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19477,7 +19477,7 @@ target_with_star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19521,7 +19521,7 @@ target_with_star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19597,7 +19597,7 @@ star_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); _res = _PyPegen_set_expr_context ( p , a , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19627,7 +19627,7 @@ star_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'")); _res = _PyPegen_set_expr_context ( p , a , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19666,7 +19666,7 @@ star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19705,7 +19705,7 @@ star_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_List ( a , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19767,7 +19767,7 @@ single_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ single_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); _res = _PyPegen_set_expr_context ( p , a , Store ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19797,7 +19797,7 @@ single_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ single_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19868,7 +19868,7 @@ single_subscript_attribute_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -19912,7 +19912,7 @@ single_subscript_attribute_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20022,7 +20022,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20066,7 +20066,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Load , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20104,7 +20104,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq* , ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20148,7 +20148,7 @@ t_primary_raw(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20174,7 +20174,7 @@ t_primary_raw(Parser *p) { D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "atom &t_lookahead")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20297,7 +20297,7 @@ del_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ del_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.del_target+ ','?")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20373,7 +20373,7 @@ del_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Attribute ( a , b -> v . Name . id , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20417,7 +20417,7 @@ del_target_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Subscript ( a , b , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20489,7 +20489,7 @@ del_t_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); _res = _PyPegen_set_expr_context ( p , a , Del ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20519,7 +20519,7 @@ del_t_atom_rule(Parser *p) { D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' del_target ')'")); _res = _PyPegen_set_expr_context ( p , a , Del ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20558,7 +20558,7 @@ del_t_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_Tuple ( a , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20597,7 +20597,7 @@ del_t_atom_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_List ( a , Del , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20665,7 +20665,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression ',' '**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq* , _PyPegen_seq_append_to_end ( p , a , b ) ) , c ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20698,7 +20698,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20731,7 +20731,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20767,7 +20767,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression ',' '**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq* , _PyPegen_singleton_seq ( p , a ) ) , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20794,7 +20794,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression")); _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20821,7 +20821,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression")); _res = ( asdl_expr_seq* ) _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20845,7 +20845,7 @@ type_expressions_rule(Parser *p) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20896,7 +20896,7 @@ func_type_comment_rule(Parser *p) { D(fprintf(stderr, "%*c+ func_type_comment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); _res = t; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -20990,7 +20990,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' ','.(starred_expression !'=')+")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "iterable argument unpacking follows keyword argument unpacking" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21024,7 +21024,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , _PyPegen_get_last_comprehension_item ( PyPegen_last_item ( b , comprehension_ty ) ) , "Generator expression must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21057,7 +21057,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21090,7 +21090,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(args ',')] NAME '=' &(',' | ')')")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected argument value expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21117,7 +21117,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); _res = _PyPegen_nonparen_genexp_in_call ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21150,7 +21150,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , _PyPegen_get_last_comprehension_item ( PyPegen_last_item ( b , comprehension_ty ) ) , "Generator expression must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21180,7 +21180,7 @@ invalid_arguments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' args")); _res = _PyPegen_arguments_parsing_error ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21230,7 +21230,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s" , PyBytes_AS_STRING ( a -> bytes ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21263,7 +21263,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21292,7 +21292,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME '=') expression '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expression cannot contain assignment, perhaps you meant \"==\"?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21325,7 +21325,7 @@ invalid_kwarg_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to keyword argument unpacking" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21407,7 +21407,7 @@ expression_without_invalid_rule(Parser *p) int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro _res = _PyAST_IfExp ( b , a , c , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->call_invalid_rules = _prev_call_invalid; p->level--; @@ -21497,7 +21497,7 @@ invalid_legacy_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_legacy_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME !'(' star_expressions")); _res = _PyPegen_check_legacy_stmt ( p , a ) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Missing parentheses in call to '%U'. Did you mean %U(...)?" , a -> v . Name . id , a -> v . Name . id ) : NULL; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21549,7 +21549,7 @@ invalid_type_param_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME ':' expression")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with TypeVarTuple" : "cannot use bound with TypeVarTuple" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21582,7 +21582,7 @@ invalid_type_param_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME ':' expression")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with ParamSpec" : "cannot use bound with ParamSpec" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21638,7 +21638,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING ((!STRING expression_without_invalid))+ STRING")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , expr_ty ) , PyPegen_last_item ( a , expr_ty ) , "invalid syntax. Is this intended to be part of the string?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21667,7 +21667,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); _res = _PyPegen_raise_error_for_missing_comma ( p , a , b ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21699,7 +21699,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected 'else' after 'if' expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21734,7 +21734,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' !expression")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "expected expression after 'else', but statement is given" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21770,7 +21770,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(pass_stmt | break_stmt | continue_stmt) 'if' disjunction 'else' simple_stmt")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected expression before 'if', but statement is given" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21803,7 +21803,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &FSTRING_MIDDLE")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "f-string: lambda expressions are not allowed without parentheses" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21836,7 +21836,7 @@ invalid_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &TSTRING_MIDDLE")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "t-string: lambda expressions are not allowed without parentheses" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21893,7 +21893,7 @@ invalid_if_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_if_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' '*'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot unpack only part of a conditional expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21929,7 +21929,7 @@ invalid_if_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_if_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' '**'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use dict unpacking on only part of a conditional expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -21985,7 +21985,7 @@ invalid_named_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22017,7 +22017,7 @@ invalid_named_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22051,7 +22051,7 @@ invalid_named_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22107,7 +22107,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_ann_assign_target ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not %s) can be annotated" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22143,7 +22143,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not tuple) can be annotated" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22173,7 +22173,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal target for annotation" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22203,7 +22203,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22233,7 +22233,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "assignment to yield expression not possible" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22263,7 +22263,7 @@ invalid_assignment_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign annotated_rhs")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "'%s' is an illegal expression for augmented assignment" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22350,7 +22350,7 @@ invalid_ann_assign_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_ann_assign_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' invalid_ann_assign_target ')'")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22396,7 +22396,7 @@ invalid_raise_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' 'from'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "did you forget an expression between 'raise' and 'from'?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22426,7 +22426,7 @@ invalid_raise_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression 'from'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "did you forget an expression after 'from'?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22472,7 +22472,7 @@ invalid_del_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' star_expressions")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22528,7 +22528,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22567,7 +22567,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ',' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22600,7 +22600,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ':=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use named expression without parentheses here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22639,7 +22639,7 @@ invalid_assert_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ',' expression ':=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use named expression without parentheses here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22684,7 +22684,7 @@ invalid_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22740,7 +22740,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' '**' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in list comprehension" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22773,7 +22773,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' '**' expression for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in generator expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22809,7 +22809,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , expr_ty ) , "did you forget parentheses around the comprehension target?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22842,7 +22842,7 @@ invalid_comprehension_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "did you forget parentheses around the comprehension target?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22894,7 +22894,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"/\" ','")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "at least one parameter must precede /" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22924,7 +22924,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slash_no_default | slash_with_default) param_maybe_default* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22958,7 +22958,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default? param_no_default* invalid_parameters_helper param_no_default")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameter without a default follows parameter with a default" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -22995,7 +22995,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Function parameters cannot be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23035,7 +23035,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(slash_no_default | slash_with_default)] param_maybe_default* '*' (',' | param_no_default) param_maybe_default* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ must be ahead of *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23065,7 +23065,7 @@ invalid_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_maybe_default+ '/' '*'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected comma between / and *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23110,7 +23110,7 @@ invalid_default_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' &(')' | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected default value expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23160,7 +23160,7 @@ invalid_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "named parameters must follow bare *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23190,7 +23190,7 @@ invalid_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' TYPE_COMMENT")); _res = RAISE_SYNTAX_ERROR ( "bare * has associated type comment" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23220,7 +23220,7 @@ invalid_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-positional parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23256,7 +23256,7 @@ invalid_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "* may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23305,7 +23305,7 @@ invalid_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-keyword parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23338,7 +23338,7 @@ invalid_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' param")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23371,7 +23371,7 @@ invalid_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' ('*' | '**' | '/')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23414,7 +23414,7 @@ invalid_parameters_helper_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23485,7 +23485,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"/\" ','")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "at least one parameter must precede /" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23515,7 +23515,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23549,7 +23549,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameter without a default follows parameter with a default" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23586,7 +23586,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Lambda expression parameters cannot be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23626,7 +23626,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(lambda_slash_no_default | lambda_slash_with_default)] lambda_param_maybe_default* '*' (',' | lambda_param_no_default) lambda_param_maybe_default* '/'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "/ must be ahead of *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23656,7 +23656,7 @@ invalid_lambda_parameters_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default+ '/' '*'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expected comma between / and *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23701,7 +23701,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); _res = _PyPegen_singleton_seq ( p , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23769,7 +23769,7 @@ invalid_lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); _res = RAISE_SYNTAX_ERROR ( "named parameters must follow bare *" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23799,7 +23799,7 @@ invalid_lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' lambda_param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-positional parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23835,7 +23835,7 @@ invalid_lambda_star_etc_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "* may appear only once" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23887,7 +23887,7 @@ invalid_lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "var-keyword parameter cannot have default value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23920,7 +23920,7 @@ invalid_lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' lambda_param")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -23953,7 +23953,7 @@ invalid_lambda_kwds_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' ('*' | '**' | '/')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "parameters cannot follow var-keyword parameter" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24008,7 +24008,7 @@ invalid_double_type_comments_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_double_type_comments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT")); _res = RAISE_SYNTAX_ERROR ( "Cannot have two type comments on def" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24059,7 +24059,7 @@ invalid_with_item_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24111,7 +24111,7 @@ invalid_for_if_clause_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in'")); _res = RAISE_SYNTAX_ERROR ( "'in' expected after for-loop variables" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24161,7 +24161,7 @@ invalid_for_target_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_for_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' star_expressions")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( FOR_TARGETS , a ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24210,7 +24210,7 @@ invalid_group_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_group[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' starred_expression ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use starred expression here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24243,7 +24243,7 @@ invalid_group_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_group[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' '**' expression ')'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use double starred expression here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24295,7 +24295,7 @@ invalid_import_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "Did you mean to use 'from ... import ...' instead?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24322,7 +24322,7 @@ invalid_import_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' NEWLINE")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( token , "Expected one or more names after 'import'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24373,7 +24373,7 @@ invalid_dotted_as_name_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_dotted_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name 'as' !(NAME (',' | ')' | ';' | NEWLINE)) expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use %s as import target" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24424,7 +24424,7 @@ invalid_import_from_as_name_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import_from_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME 'as' !(NAME (',' | ')' | ';' | NEWLINE)) expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use %s as import target" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24473,7 +24473,7 @@ invalid_import_from_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_names ',' NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "trailing comma not allowed without surrounding parentheses" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24497,7 +24497,7 @@ invalid_import_from_targets_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( token , "Expected one or more names after 'import'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24556,7 +24556,7 @@ invalid_with_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ',' ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( trailing , "the last 'with' item has a trailing comma" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24590,7 +24590,7 @@ invalid_with_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24634,7 +24634,7 @@ invalid_with_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24694,7 +24694,7 @@ invalid_with_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24743,7 +24743,7 @@ invalid_with_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_with_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24798,7 +24798,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'try' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24830,7 +24830,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); _res = RAISE_SYNTAX_ERROR ( "expected 'except' or 'finally' block" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24879,7 +24879,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block* except_block+ 'except' '*' expression ['as' NAME] ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot have both 'except' and 'except*' on the same 'try'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24922,7 +24922,7 @@ invalid_try_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block* except_star_block+ 'except' [expression ['as' NAME]] ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot have both 'except' and 'except*' on the same 'try'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -24987,7 +24987,7 @@ invalid_except_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ',' expressions 'as' NAME ':'")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized when using 'as'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25021,7 +25021,7 @@ invalid_except_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25048,7 +25048,7 @@ invalid_except_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25087,7 +25087,7 @@ invalid_except_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression 'as' expression ':' block")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use except statement with %s" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25155,7 +25155,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ',' expressions 'as' NAME ':'")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized when using 'as'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25192,7 +25192,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25222,7 +25222,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); _res = RAISE_SYNTAX_ERROR ( "expected one or more exception types" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25264,7 +25264,7 @@ invalid_except_star_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression 'as' expression ':' block")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use except* statement with %s" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25315,7 +25315,7 @@ invalid_finally_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_finally_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'finally' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25375,7 +25375,7 @@ invalid_except_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25407,7 +25407,7 @@ invalid_except_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25469,7 +25469,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt_indent[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' expression ['as' NAME] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except*' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25521,7 +25521,7 @@ invalid_match_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr NEWLINE")); _res = CHECK_VERSION ( void* , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected ':'" ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25556,7 +25556,7 @@ invalid_match_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'match' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25593,7 +25593,7 @@ invalid_match_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "case statement must be inside match statement" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25648,7 +25648,7 @@ invalid_case_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_case_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25687,7 +25687,7 @@ invalid_case_block_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_case_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'case' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25736,7 +25736,7 @@ invalid_as_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' \"_\"")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use '_' as a target" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25766,7 +25766,7 @@ invalid_as_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use %s as pattern target" , _PyPegen_get_expr_name ( a ) ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25815,7 +25815,7 @@ invalid_class_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' invalid_class_argument_pattern")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , pattern_ty ) , PyPegen_last_item ( a , pattern_ty ) , "positional patterns follow keyword patterns" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25879,7 +25879,7 @@ invalid_mapping_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' [(items_pattern ',')] double_star_pattern ',' items_pattern ','? '}'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( rest , "double star pattern must be the last (right-most) subpattern in the mapping pattern" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25933,7 +25933,7 @@ invalid_class_argument_pattern_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_class_argument_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[positional_patterns ','] keyword_patterns ',' positional_patterns")); _res = a; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -25984,7 +25984,7 @@ invalid_if_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26019,7 +26019,7 @@ invalid_if_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'if' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26070,7 +26070,7 @@ invalid_elif_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26105,7 +26105,7 @@ invalid_elif_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'elif' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26156,7 +26156,7 @@ invalid_else_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_else_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'else' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26189,7 +26189,7 @@ invalid_else_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_else_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' ':' block 'elif'")); _res = RAISE_SYNTAX_ERROR ( "'elif' block follows an 'else' block" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26240,7 +26240,7 @@ invalid_while_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26275,7 +26275,7 @@ invalid_while_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'while' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26336,7 +26336,7 @@ invalid_for_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' star_targets 'in' star_expressions NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26381,7 +26381,7 @@ invalid_for_stmt_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'for' statement on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26459,7 +26459,7 @@ invalid_def_raw_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'def' NAME type_params? '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after function definition on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26572,7 +26572,7 @@ invalid_class_def_raw_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26615,7 +26615,7 @@ invalid_class_def_raw_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' NEWLINE !INDENT")); _res = RAISE_INDENTATION_ERROR ( "expected an indented block after class definition on line %d" , a -> lineno ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26714,7 +26714,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26765,7 +26765,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' if_expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid double starred expression. Did you forget to wrap the conditional expression in parentheses?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26798,7 +26798,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use a starred expression in a dictionary key" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26831,7 +26831,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or ':' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in a dictionary key" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26864,7 +26864,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use a starred expression in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26897,7 +26897,7 @@ invalid_kvpair_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '**' bitwise_or")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use dict unpacking in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26946,7 +26946,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !(':')")); _res = RAISE_ERROR_KNOWN_LOCATION ( p , PyExc_SyntaxError , a -> lineno , a -> end_col_offset - 1 , a -> end_lineno , - 1 , "':' expected after dictionary key" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -26979,7 +26979,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27012,7 +27012,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' '**' bitwise_or")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use dict unpacking in a dictionary value" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27041,7 +27041,7 @@ invalid_kvpair_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27087,7 +27087,7 @@ invalid_starred_expression_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' if_expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid starred expression. Did you forget to wrap the conditional expression in parentheses?" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27120,7 +27120,7 @@ invalid_starred_expression_unpacking_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression_unpacking[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression '=' expression")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to iterable argument unpacking" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27168,7 +27168,7 @@ invalid_starred_expression_unpacking_sequence_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression_unpacking_sequence[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use dict unpacking here" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27230,7 +27230,7 @@ invalid_starred_expression_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_starred_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = RAISE_SYNTAX_ERROR ( "Invalid star expression" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27287,7 +27287,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before '='" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27314,7 +27314,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '!'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before '!'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27341,7 +27341,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27368,7 +27368,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '}'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "f-string: valid expression required before '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27394,7 +27394,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !annotated_rhs")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting a valid expression after '{'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27423,7 +27423,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '=', or '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27455,7 +27455,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27521,7 +27521,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting ':' or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27564,7 +27564,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '}', or format specs" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27601,7 +27601,7 @@ invalid_fstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: expecting '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27646,7 +27646,7 @@ invalid_fstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: missing conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27672,7 +27672,7 @@ invalid_fstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_fstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' !NAME")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "f-string: invalid conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27729,7 +27729,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '='")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before '='" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27756,7 +27756,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '!'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before '!'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27783,7 +27783,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' ':'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before ':'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27810,7 +27810,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '}'")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "t-string: valid expression required before '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27836,7 +27836,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !annotated_rhs")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting a valid expression after '{'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27865,7 +27865,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '=', or '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27897,7 +27897,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '!', or ':', or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -27963,7 +27963,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting ':' or '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28006,7 +28006,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '}', or format specs" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28043,7 +28043,7 @@ invalid_tstring_replacement_field_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !'}'")); _res = PyErr_Occurred ( ) ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: expecting '}'" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28088,7 +28088,7 @@ invalid_tstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: missing conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28114,7 +28114,7 @@ invalid_tstring_conversion_character_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_tstring_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' !NAME")); _res = RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN ( "t-string: invalid conversion character" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28162,7 +28162,7 @@ invalid_string_tstring_concat_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_string_tstring_concat[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((fstring | string))+ tstring")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_last_item ( a , expr_ty ) , b , "cannot mix t-string literals with string or bytes literals" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28189,7 +28189,7 @@ invalid_string_tstring_concat_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_string_tstring_concat[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tstring+ (fstring | string)")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_last_item ( a , expr_ty ) , b , "cannot mix t-string literals with string or bytes literals" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28241,7 +28241,7 @@ invalid_arithmetic_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_arithmetic[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum ('+' | '-' | '*' | '/' | '%' | '//' | '@') 'not' inversion")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "'not' after an operator must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28290,7 +28290,7 @@ invalid_factor_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('+' | '-' | '~') 'not' factor")); _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "'not' after an operator must be parenthesized" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28336,7 +28336,7 @@ invalid_type_params_rule(Parser *p) { D(fprintf(stderr, "%*c+ invalid_type_params[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' ']'")); _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( token , "Type parameter list cannot be empty" ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -28529,7 +28529,7 @@ _loop0_3_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -28961,7 +28961,7 @@ _tmp_10_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); _res = d; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29010,7 +29010,7 @@ _tmp_11_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); _res = b; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29155,7 +29155,7 @@ _loop0_13_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -29321,7 +29321,7 @@ _tmp_16_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29514,7 +29514,7 @@ _loop0_19_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -29623,7 +29623,7 @@ _tmp_21_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_21[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29677,7 +29677,7 @@ _loop0_22_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -29861,7 +29861,7 @@ _tmp_25_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_25[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -29907,7 +29907,7 @@ _tmp_26_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_26[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -30378,7 +30378,7 @@ _loop0_33_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -30787,7 +30787,7 @@ _loop0_39_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31113,7 +31113,7 @@ _loop0_44_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31230,7 +31230,7 @@ _loop0_46_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31404,7 +31404,7 @@ _loop0_49_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31521,7 +31521,7 @@ _loop0_51_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31638,7 +31638,7 @@ _loop0_53_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -31899,7 +31899,7 @@ _loop0_57_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -32016,7 +32016,7 @@ _loop0_59_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -32338,7 +32338,7 @@ _tmp_64_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_64[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -32392,7 +32392,7 @@ _loop0_65_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -32501,7 +32501,7 @@ _tmp_67_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); _res = d; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -33664,7 +33664,7 @@ _tmp_84_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_84[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression_sequence ',' star_named_expressions_sequence?")); _res = _PyPegen_seq_insert_in_front ( p , y , z ); - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -33718,7 +33718,7 @@ _loop0_85_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34052,7 +34052,7 @@ _loop0_90_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34162,7 +34162,7 @@ _tmp_92_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); _res = k; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -34216,7 +34216,7 @@ _loop0_93_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34333,7 +34333,7 @@ _loop0_95_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34517,7 +34517,7 @@ _loop0_98_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34746,7 +34746,7 @@ _loop0_102_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -34863,7 +34863,7 @@ _loop0_104_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -35080,7 +35080,7 @@ _loop0_108_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -36539,7 +36539,7 @@ _loop0_131_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -36875,7 +36875,7 @@ _loop0_137_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -37033,7 +37033,7 @@ _loop0_140_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -37150,7 +37150,7 @@ _loop0_142_rule(Parser *p) ) { _res = elem; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); p->level--; @@ -38232,7 +38232,7 @@ _tmp_159_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38338,7 +38338,7 @@ _tmp_161_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38384,7 +38384,7 @@ _tmp_162_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38430,7 +38430,7 @@ _tmp_163_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38476,7 +38476,7 @@ _tmp_164_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38579,7 +38579,7 @@ _tmp_166_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; @@ -38684,7 +38684,7 @@ _tmp_168_rule(Parser *p) { D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; - if (_res == NULL && PyErr_Occurred()) { + if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { p->error_indicator = 1; p->level--; return NULL; diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index a4e111972bd..d9236dfb228 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -739,7 +739,7 @@ def join_conditions(self, keyword: str, node: Any) -> None: def emit_action(self, node: Alt, cleanup_code: str | None = None) -> None: self.print(f"_res = {node.action};") - self.print("if (_res == NULL && PyErr_Occurred()) {") + self.print("if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) {") with self.indent(): self.print("p->error_indicator = 1;") if cleanup_code: From 962fb872ebd97ab6ab808a1b8e2034577e5501bf Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 13 Mar 2026 13:05:41 +0200 Subject: [PATCH 117/775] gh-145850: Change some implementation details in struct.Struct (GH-145851) * calling it with non-ASCII string format will now raise a ValueError instead of UnicodeEncodeError * calling it with non-ASCII bytes format will now raise a ValueError instead of struct.error * getting the format attribute of uninitialized object will now raise an AttributeError instead of RuntimeError. --- Lib/test/test_struct.py | 21 ++++-- ...-03-12-12-17-39.gh-issue-145850.uW3stt.rst | 6 ++ Modules/_struct.c | 68 +++++++------------ Modules/_xxtestfuzz/fuzzer.c | 4 ++ 4 files changed, 48 insertions(+), 51 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index e3e02097b1f..c7dc69defde 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -605,7 +605,7 @@ def test_Struct_reinitialization(self): self.assertEqual(s.unpack(packed), (1, 2)) with self.assertWarnsRegex(FutureWarning, msg): - with self.assertRaises(UnicodeEncodeError): + with self.assertRaises(ValueError): s.__init__('\udc00') self.assertEqual(s.format, '>hh') self.assertEqual(s.pack(1, 2), packed) @@ -872,10 +872,10 @@ def __init__(self, *args, **kwargs): with self.assertWarnsRegex(DeprecationWarning, warnmsg + 'bad char'): my_struct = MyStruct(format='$') self.assertEqual(my_struct.pack(12345), b'\x30\x39') - with self.assertWarnsRegex(DeprecationWarning, warnmsg + ".*can't encode"): + with self.assertWarnsRegex(DeprecationWarning, warnmsg + "non-ASCII"): my_struct = MyStruct('\udc00') self.assertEqual(my_struct.pack(12345), b'\x30\x39') - with self.assertWarnsRegex(DeprecationWarning, warnmsg + ".*can't encode"): + with self.assertWarnsRegex(DeprecationWarning, warnmsg + "non-ASCII"): my_struct = MyStruct(format='\udc00') self.assertEqual(my_struct.pack(12345), b'\x30\x39') @@ -928,11 +928,16 @@ def __init__(self, newargs, initargs): with self.assertWarns(FutureWarning): with self.assertRaises(struct.error): MyStruct(('>h',), ('$',)) - with self.assertRaises(UnicodeEncodeError): + with self.assertRaises(ValueError): MyStruct(('\udc00',), ('>h',)) + with self.assertRaises(ValueError): + MyStruct((b'\xa4',), ('>h',)) with self.assertWarns(FutureWarning): - with self.assertRaises(UnicodeEncodeError): + with self.assertRaises(ValueError): MyStruct(('>h',), ('\udc00',)) + with self.assertWarns(FutureWarning): + with self.assertRaises(ValueError): + MyStruct(('>h',), (b'\xa4',)) with self.assertWarns(FutureWarning): my_struct = MyStruct(('>h',), ('h', 42) with self.assertRaises(TypeError): @@ -1004,7 +1011,7 @@ def test_operations_on_half_initialized_Struct(self): self.assertRaises(RuntimeError, S.pack_into, spam, 1) self.assertRaises(RuntimeError, S.unpack, spam) self.assertRaises(RuntimeError, S.unpack_from, spam) - self.assertRaises(RuntimeError, getattr, S, 'format') + self.assertRaises(AttributeError, getattr, S, 'format') self.assertRaises(RuntimeError, S.__sizeof__) self.assertRaises(RuntimeError, repr, S) self.assertEqual(S.size, -1) diff --git a/Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst b/Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst new file mode 100644 index 00000000000..35ba57a95b0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst @@ -0,0 +1,6 @@ +Changed some implementation details in :class:`struct.Struct`: calling it +with non-ASCII string format will now raise a :exc:`ValueError` instead of +:exc:`UnicodeEncodeError`, calling it with non-ASCII bytes format will now +raise a :exc:`ValueError` instead of :exc:`struct.error`, getting +the :attr:`!format` attribute of uninitialized object will now raise an +:exc:`AttributeError` instead of :exc:`RuntimeError`. diff --git a/Modules/_struct.c b/Modules/_struct.c index 7eddc9bdc38..2059218029e 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1635,8 +1635,12 @@ prepare_s(PyStructObject *self, PyObject *format) _structmodulestate *state = get_struct_state_structinst(self); - fmt = PyBytes_AS_STRING(format); - if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(format)) { + if (!PyUnicode_IS_ASCII(format)) { + PyErr_SetString(PyExc_ValueError, "non-ASCII character in struct format"); + return -1; + } + fmt = (const char *)PyUnicode_1BYTE_DATA(format); + if (strlen(fmt) != (size_t)PyUnicode_GET_LENGTH(format)) { PyErr_SetString(state->StructError, "embedded null character"); return -1; @@ -1780,12 +1784,11 @@ static int set_format(PyStructObject *self, PyObject *format) { if (PyUnicode_Check(format)) { - format = PyUnicode_AsASCIIString(format); - if (format == NULL) - return -1; + format = PyUnicode_FromObject(format); } else if (PyBytes_Check(format)) { - Py_INCREF(format); + format = PyUnicode_DecodeASCII(PyBytes_AS_STRING(format), + PyBytes_GET_SIZE(format), "surrogateescape"); } else { PyErr_Format(PyExc_TypeError, @@ -1793,6 +1796,9 @@ set_format(PyStructObject *self, PyObject *format) "not %T", format); return -1; } + if (format == NULL) { + return -1; + } if (prepare_s(self, format)) { Py_DECREF(format); return -1; @@ -1821,7 +1827,7 @@ Struct_impl(PyTypeObject *type, PyObject *format) if (self == NULL) { return NULL; } - self->s_format = Py_NewRef(Py_None); + self->s_format = NULL; self->s_codes = NULL; self->s_size = -1; self->s_len = -1; @@ -1878,7 +1884,7 @@ s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (self == NULL) { return NULL; } - self->s_format = Py_NewRef(Py_None); + self->s_format = NULL; self->s_codes = NULL; self->s_size = -1; self->s_len = -1; @@ -1892,7 +1898,7 @@ s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } PyObject *exc = PyErr_GetRaisedException(); - Py_SETREF(self->s_format, Py_NewRef(Py_None)); + Py_CLEAR(self->s_format); if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "Invalid 'format' argument for Struct.__new__(): %S", exc)) { @@ -1910,8 +1916,8 @@ s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static bool same_format(PyStructObject *s, PyObject *format) { - Py_ssize_t size = PyBytes_GET_SIZE(s->s_format); - const void *data = PyBytes_AS_STRING(s->s_format); + Py_ssize_t size = PyUnicode_GET_LENGTH(s->s_format); + const void *data = PyUnicode_1BYTE_DATA(s->s_format); if (PyUnicode_Check(format) && PyUnicode_IS_ASCII(format)) { return PyUnicode_GET_LENGTH(format) == size && memcmp(PyUnicode_1BYTE_DATA(format), data, size) == 0; @@ -1938,7 +1944,7 @@ static int Struct___init___impl(PyStructObject *self, PyObject *format) /*[clinic end generated code: output=b8e80862444e92d0 input=1af78a5f57d82cec]*/ { - if (self->s_format == Py_None) { + if (self->s_format == NULL) { if (set_format(self, format) < 0) { return -1; } @@ -1965,7 +1971,7 @@ s_init(PyObject *self, PyObject *args, PyObject *kwargs) { if (!((PyStructObject *)self)->init_called && Py_TYPE(self)->tp_init == s_init - && ((PyStructObject *)self)->s_format != Py_None) + && ((PyStructObject *)self)->s_format != NULL) { /* Struct.__init__() was called implicitly. * __new__() already did all the work. */ @@ -2508,22 +2514,6 @@ Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer, Py_RETURN_NONE; } -static PyObject * -s_get_format(PyObject *op, void *Py_UNUSED(closure)) -{ - PyStructObject *self = PyStructObject_CAST(op); - ENSURE_STRUCT_IS_READY(self); - return PyUnicode_FromStringAndSize(PyBytes_AS_STRING(self->s_format), - PyBytes_GET_SIZE(self->s_format)); -} - -static PyObject * -s_get_size(PyObject *op, void *Py_UNUSED(closure)) -{ - PyStructObject *self = PyStructObject_CAST(op); - return PyLong_FromSsize_t(self->s_size); -} - /*[clinic input] Struct.__sizeof__ [clinic start generated code]*/ @@ -2545,14 +2535,7 @@ s_repr(PyObject *op) { PyStructObject *self = PyStructObject_CAST(op); ENSURE_STRUCT_IS_READY(self); - PyObject* fmt = PyUnicode_FromStringAndSize( - PyBytes_AS_STRING(self->s_format), PyBytes_GET_SIZE(self->s_format)); - if (fmt == NULL) { - return NULL; - } - PyObject* s = PyUnicode_FromFormat("%s(%R)", _PyType_Name(Py_TYPE(self)), fmt); - Py_DECREF(fmt); - return s; + return PyUnicode_FromFormat("%s(%R)", _PyType_Name(Py_TYPE(self)), self->s_format); } /* List of functions */ @@ -2569,15 +2552,13 @@ static struct PyMethodDef s_methods[] = { static PyMemberDef s_members[] = { {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(PyStructObject, weakreflist), Py_READONLY}, + {"format", Py_T_OBJECT_EX, offsetof(PyStructObject, s_format), + Py_READONLY, PyDoc_STR("struct format string")}, + {"size", Py_T_PYSSIZET, offsetof(PyStructObject, s_size), Py_READONLY, + PyDoc_STR("struct size in bytes")}, {NULL} /* sentinel */ }; -static PyGetSetDef s_getsetlist[] = { - {"format", s_get_format, NULL, PyDoc_STR("struct format string"), NULL}, - {"size", s_get_size, NULL, PyDoc_STR("struct size in bytes"), NULL}, - {NULL} /* sentinel */ -}; - static PyType_Slot PyStructType_slots[] = { {Py_tp_dealloc, s_dealloc}, {Py_tp_getattro, PyObject_GenericGetAttr}, @@ -2588,7 +2569,6 @@ static PyType_Slot PyStructType_slots[] = { {Py_tp_clear, s_clear}, {Py_tp_methods, s_methods}, {Py_tp_members, s_members}, - {Py_tp_getset, s_getsetlist}, {Py_tp_init, s_init}, {Py_tp_new, s_new}, {0, 0}, diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index f3a22f3f6a8..6cb11562476 100644 --- a/Modules/_xxtestfuzz/fuzzer.c +++ b/Modules/_xxtestfuzz/fuzzer.c @@ -133,6 +133,10 @@ static int fuzz_struct_unpack(const char* data, size_t size) { if (unpacked == NULL && PyErr_ExceptionMatches(PyExc_SystemError)) { PyErr_Clear(); } + /* Ignore any ValueError, these are triggered by non-ASCII format. */ + if (unpacked == NULL && PyErr_ExceptionMatches(PyExc_ValueError)) { + PyErr_Clear(); + } /* Ignore any struct.error exceptions, these can be caused by invalid formats or incomplete buffers both of which are common. */ if (unpacked == NULL && PyErr_ExceptionMatches(struct_error)) { From 0b6a2346e5b203fb988a382fdc3d51b36641fe1a Mon Sep 17 00:00:00 2001 From: devdanzin <74280297+devdanzin@users.noreply.github.com> Date: Fri, 13 Mar 2026 08:57:35 -0300 Subject: [PATCH 118/775] gh-145887: Use `write()` instead of `stream.write()` in `PrettyPrinter._pprint_frozendict` (#145894) --- Lib/pprint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/pprint.py b/Lib/pprint.py index e111bd59d41..a0e484b1c09 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -238,7 +238,7 @@ def _pprint_dict(self, object, stream, indent, allowance, context, level): def _pprint_frozendict(self, object, stream, indent, allowance, context, level): write = stream.write cls = object.__class__ - stream.write(cls.__name__ + '(') + write(cls.__name__ + '(') length = len(object) if length: self._pprint_dict(object, stream, From 59d97683c19923b06e2b2110efadb90fe37f53f3 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 <148854295+VanshAgarwal24036@users.noreply.github.com> Date: Fri, 13 Mar 2026 17:45:26 +0530 Subject: [PATCH 119/775] gh-145792: Fix incorrect alloca allocation size in traceback.c (#145814) --- .../2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst | 2 ++ Python/traceback.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst new file mode 100644 index 00000000000..bd42f32d6ae --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst @@ -0,0 +1,2 @@ +Fix out-of-bounds access when invoking faulthandler on a CPython build +compiled without support for VLAs. diff --git a/Python/traceback.c b/Python/traceback.c index 74360a1c73c..1e8c9c879f9 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -41,7 +41,7 @@ #if defined(__STDC_NO_VLA__) && (__STDC_NO_VLA__ == 1) /* Use alloca() for VLAs. */ -# define VLA(type, name, size) type *name = alloca(size) +# define VLA(type, name, size) type *name = alloca(sizeof(type) * (size)) #elif !defined(__STDC_NO_VLA__) || (__STDC_NO_VLA__ == 0) /* Use actual C VLAs.*/ # define VLA(type, name, size) type name[size] From 9162238511197be119c5e7cdc554c1e39522a946 Mon Sep 17 00:00:00 2001 From: Furkan Onder Date: Fri, 13 Mar 2026 21:38:06 +0900 Subject: [PATCH 120/775] gh-99631: Add shelve custom serialization to What's New in 3.15 (#145253) --- Doc/whatsnew/3.15.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 7daea13d31c..459846e55cc 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -912,6 +912,9 @@ shelve * Added new :meth:`!reorganize` method to :mod:`shelve` used to recover unused free space previously occupied by deleted entries. (Contributed by Andrea Oliveri in :gh:`134004`.) +* Add support for custom serialization and deserialization functions + in the :mod:`shelve` module. + (Contributed by Furkan Onder in :gh:`99631`.) socket From f884dc6f70fde3550a175ff7ddce79ccc38b3ec6 Mon Sep 17 00:00:00 2001 From: "Jason Yalim, PhD" <4813268+jyalim@users.noreply.github.com> Date: Fri, 13 Mar 2026 06:00:39 -0700 Subject: [PATCH 121/775] gh-140715: Add %t and %n format codes support to strptime() (GH-144896) Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- Doc/library/datetime.rst | 14 +++++++++----- Lib/_strptime.py | 5 ++++- Lib/test/datetimetester.py | 14 ++++++++++++++ Lib/test/test_strptime.py | 17 +++++++++++++++++ Lib/test/test_time.py | 2 +- ...26-02-17-03-43-07.gh-issue-140715.twmcM_.rst | 1 + 6 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 73217136f14..8993049a720 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2611,8 +2611,10 @@ requires, and these work on all supported platforms. | ``%M`` | Minute as a zero-padded | 00, 01, ..., 59 | \(9) | | | decimal number. | | | +-----------+--------------------------------+------------------------+-------+ -| ``%n`` | The newline character | ``\n`` | \(0) | -| | (``'\n'``). | | | +| ``%n`` | The newline character | ``\n`` | | +| | (``'\n'``). For | | | +| | :meth:`!strptime`, zero or | | | +| | more whitespace. | | | +-----------+--------------------------------+------------------------+-------+ | ``%p`` | Locale's equivalent of either || AM, PM (en_US); | \(1), | | | AM or PM. || am, pm (de_DE) | \(3) | @@ -2625,8 +2627,9 @@ requires, and these work on all supported platforms. | ``%S`` | Second as a zero-padded | 00, 01, ..., 59 | \(4), | | | decimal number. | | \(9) | +-----------+--------------------------------+------------------------+-------+ -| ``%t`` | The tab character | ``\t`` | \(0) | -| | (``'\t'``). | | | +| ``%t`` | The tab character (``'\t'``). | ``\t`` | | +| | For :meth:`!strptime`, | | | +| | zero or more whitespace. | | | +-----------+--------------------------------+------------------------+-------+ | ``%T`` | ISO 8601 time format, | 10:01:59 | | | | equivalent to ``%H:%M:%S``. | | | @@ -2717,7 +2720,8 @@ differences between platforms in handling of unsupported format specifiers. ``%:z`` was added for :meth:`~.datetime.strftime`. .. versionadded:: 3.15 - ``%:z``, ``%F``, and ``%D`` were added for :meth:`~.datetime.strptime`. + ``%D``, ``%F``, ``%n``, ``%t``, and ``%:z`` were added for + :meth:`~.datetime.strptime`. Technical detail diff --git a/Lib/_strptime.py b/Lib/_strptime.py index 0d81ff6765e..3367ac485a5 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -382,7 +382,10 @@ def __init__(self, locale_time=None): 'Z': self.__seqToRE((tz for tz_names in self.locale_time.timezone for tz in tz_names), 'Z'), - '%': '%'} + 'n': r'\s*', + 't': r'\s*', + '%': '%', + } if self.locale_time.LC_alt_digits is None: for d in 'dmyCHIMS': mapping['O' + d] = r'(?P<%s>\d\d|\d| \d)' % d diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 97eec618932..e264433ca59 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -2207,6 +2207,20 @@ def test_strptime_D_format(self): self.theclass.strptime(test_date, "%m/%d/%y") ) + def test_strptime_n_and_t_format(self): + format_directives = ('%n', '%t', '%n%t', '%t%n') + whitespaces = ('', ' ', '\t', '\r', '\v', '\n', '\f') + for fd in format_directives: + for ws in (*whitespaces, ''.join(whitespaces)): + with self.subTest(format_directive=fd, whitespace=ws): + self.assertEqual( + self.theclass.strptime( + f"2026{ws}02{ws}03", + f"%Y{fd}%m{fd}%d", + ), + self.theclass(2026, 2, 3), + ) + ############################################################################# # datetime tests diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index fd8525feb88..dfc8ef6d2c5 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -670,6 +670,23 @@ def test_strptime_D_format(self): time.strptime(test_date, "%m/%d/%y") ) + def test_strptime_n_and_t_format(self): + format_directives = ('%n', '%t', '%n%t', '%t%n') + whitespaces = ('', ' ', '\t', '\r', '\v', '\n', '\f') + for fd in format_directives: + for ws in (*whitespaces, ''.join(whitespaces)): + with self.subTest(format_directive=fd, whitespace=ws): + self.assertEqual( + time.strptime( + f"2026{ws}02{ws}03", + f"%Y{fd}%m{fd}%d", + ), + time.strptime( + f'2026-02-03', + "%Y-%m-%d", + ), + ) + class Strptime12AMPMTests(unittest.TestCase): """Test a _strptime regression in '%I %p' at 12 noon (12 PM)""" diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index da5fd16b8b6..be8f6b05765 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -359,7 +359,7 @@ def test_strptime(self): # raising an exception. tt = time.gmtime(self.t) for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'D', 'F', 'H', 'I', - 'j', 'm', 'M', 'p', 'S', 'T', + 'j', 'm', 'M', 'n', 'p', 'S', 't', 'T', 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): format = '%' + directive if directive == 'd': diff --git a/Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst b/Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst new file mode 100644 index 00000000000..3bebc6660df --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst @@ -0,0 +1 @@ +Add ``%n`` and ``%t`` support to :meth:`~datetime.datetime.strptime`. From 61f2a1a5993967ed4b97ba93a4477c37fe68cf59 Mon Sep 17 00:00:00 2001 From: "Michiel W. Beijen" Date: Fri, 13 Mar 2026 14:10:48 +0100 Subject: [PATCH 122/775] GH-60729: Add IEEE format wave audio support (GH-145384) Co-authored-by: Lionel Koenig --- Doc/library/wave.rst | 69 ++++++- Doc/whatsnew/3.15.rst | 15 ++ Lib/test/audiodata/pluck-float32.wav | Bin 0 -> 26514 bytes Lib/test/audiotests.py | 16 +- Lib/test/test_wave.py | 188 +++++++++++++++++- Lib/wave.py | 88 ++++++-- ...3-03-10-13-10-06.gh-issue-60729.KCCHTe.rst | 1 + 7 files changed, 352 insertions(+), 25 deletions(-) create mode 100644 Lib/test/audiodata/pluck-float32.wav create mode 100644 Misc/NEWS.d/next/Library/2023-03-10-13-10-06.gh-issue-60729.KCCHTe.rst diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index ff020b52da3..9d30a14f112 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -9,14 +9,19 @@ -------------- The :mod:`!wave` module provides a convenient interface to the Waveform Audio -"WAVE" (or "WAV") file format. Only uncompressed PCM encoded wave files are -supported. +"WAVE" (or "WAV") file format. + +The module supports uncompressed PCM and IEEE floating-point WAV formats. .. versionchanged:: 3.12 Support for ``WAVE_FORMAT_EXTENSIBLE`` headers was added, provided that the extended format is ``KSDATAFORMAT_SUBTYPE_PCM``. +.. versionchanged:: next + + Support for reading and writing ``WAVE_FORMAT_IEEE_FLOAT`` files was added. + The :mod:`!wave` module defines the following function and exception: @@ -60,6 +65,21 @@ The :mod:`!wave` module defines the following function and exception: specification or hits an implementation deficiency. +.. data:: WAVE_FORMAT_PCM + + Format code for uncompressed PCM audio. + + +.. data:: WAVE_FORMAT_IEEE_FLOAT + + Format code for IEEE floating-point audio. + + +.. data:: WAVE_FORMAT_EXTENSIBLE + + Format code for WAVE extensible headers. + + .. _wave-read-objects: Wave_read Objects @@ -98,6 +118,14 @@ Wave_read Objects Returns number of audio frames. + .. method:: getformat() + + Returns the frame format code. + + This is one of :data:`WAVE_FORMAT_PCM`, + :data:`WAVE_FORMAT_IEEE_FLOAT`, or :data:`WAVE_FORMAT_EXTENSIBLE`. + + .. method:: getcomptype() Returns compression type (``'NONE'`` is the only supported type). @@ -112,8 +140,8 @@ Wave_read Objects .. method:: getparams() Returns a :func:`~collections.namedtuple` ``(nchannels, sampwidth, - framerate, nframes, comptype, compname)``, equivalent to output of the - ``get*()`` methods. + framerate, nframes, comptype, compname)``, equivalent to output + of the ``get*()`` methods. .. method:: readframes(n) @@ -190,6 +218,9 @@ Wave_write Objects Set the sample width to *n* bytes. + For :data:`WAVE_FORMAT_IEEE_FLOAT`, only 4-byte (32-bit) and + 8-byte (64-bit) sample widths are supported. + .. method:: getsampwidth() @@ -238,11 +269,32 @@ Wave_write Objects Return the human-readable compression type name. + .. method:: setformat(format) + + Set the frame format code. + + Supported values are :data:`WAVE_FORMAT_PCM` and + :data:`WAVE_FORMAT_IEEE_FLOAT`. + + When setting :data:`WAVE_FORMAT_IEEE_FLOAT`, the sample width must be + 4 or 8 bytes. + + + .. method:: getformat() + + Return the current frame format code. + + .. method:: setparams(tuple) - The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype, - compname)``, with values valid for the ``set*()`` methods. Sets all - parameters. + The *tuple* should be + ``(nchannels, sampwidth, framerate, nframes, comptype, compname, format)``, + with values valid for the ``set*()`` methods. Sets all parameters. + + For backwards compatibility, a 6-item tuple without *format* is also + accepted and defaults to :data:`WAVE_FORMAT_PCM`. + + For ``format=WAVE_FORMAT_IEEE_FLOAT``, *sampwidth* must be 4 or 8. .. method:: getparams() @@ -279,3 +331,6 @@ Wave_write Objects Note that it is invalid to set any parameters after calling :meth:`writeframes` or :meth:`writeframesraw`, and any attempt to do so will raise :exc:`wave.Error`. + + For :data:`WAVE_FORMAT_IEEE_FLOAT` output, a ``fact`` chunk is written as + required by the WAVE specification for non-PCM formats. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 459846e55cc..d5b14216770 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1518,6 +1518,21 @@ typing wave ---- +* Added support for IEEE floating-point WAVE audio + (``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`. + +* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`, + and :meth:`wave.Wave_write.setformat` for explicit frame format handling. + +* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including + ``format`` and 6-item tuples for backwards compatibility (defaulting to + ``WAVE_FORMAT_PCM``). + +* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk, + as required for non-PCM WAVE formats. + +(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.) + * Removed the ``getmark()``, ``setmark()`` and ``getmarkers()`` methods of the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes, which were deprecated since Python 3.13. diff --git a/Lib/test/audiodata/pluck-float32.wav b/Lib/test/audiodata/pluck-float32.wav new file mode 100644 index 0000000000000000000000000000000000000000..2030fb16d6e3bd797523605091ff1d732b432b88 GIT binary patch literal 26514 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±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 4: + if self._format == WAVE_FORMAT_IEEE_FLOAT: + if sampwidth not in (4, 8): + raise Error('unsupported sample width for IEEE float format') + elif sampwidth < 1 or sampwidth > 4: raise Error('bad sample width') self._sampwidth = sampwidth @@ -518,6 +546,18 @@ def setcomptype(self, comptype, compname): self._comptype = comptype self._compname = compname + def setformat(self, format): + if self._datawritten: + raise Error('cannot change parameters after starting to write') + if format not in (WAVE_FORMAT_IEEE_FLOAT, WAVE_FORMAT_PCM): + raise Error('unsupported wave format') + if format == WAVE_FORMAT_IEEE_FLOAT and self._sampwidth and self._sampwidth not in (4, 8): + raise Error('unsupported sample width for IEEE float format') + self._format = format + + def getformat(self): + return self._format + def getcomptype(self): return self._comptype @@ -525,10 +565,15 @@ def getcompname(self): return self._compname def setparams(self, params): - nchannels, sampwidth, framerate, nframes, comptype, compname = params if self._datawritten: raise Error('cannot change parameters after starting to write') + if len(params) == 6: + nchannels, sampwidth, framerate, nframes, comptype, compname = params + format = WAVE_FORMAT_PCM + else: + nchannels, sampwidth, framerate, nframes, comptype, compname, format = params self.setnchannels(nchannels) + self.setformat(format) self.setsampwidth(sampwidth) self.setframerate(framerate) self.setnframes(nframes) @@ -589,6 +634,9 @@ def _ensure_header_written(self, datasize): raise Error('sampling rate not specified') self._write_header(datasize) + def _needs_fact_chunk(self): + return self._format == WAVE_FORMAT_IEEE_FLOAT + def _write_header(self, initlength): assert not self._headerwritten self._file.write(b'RIFF') @@ -599,12 +647,23 @@ def _write_header(self, initlength): self._form_length_pos = self._file.tell() except (AttributeError, OSError): self._form_length_pos = None - self._file.write(struct.pack(' Date: Fri, 13 Mar 2026 14:53:01 +0100 Subject: [PATCH 123/775] gh-142518: Document thread-safety guarantees of set objects (#145225) --- Doc/library/stdtypes.rst | 5 ++ Doc/library/threadsafety.rst | 105 +++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 6b55daa9b6e..7ae399eb95b 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -5251,6 +5251,11 @@ Note, the *elem* argument to the :meth:`~object.__contains__`, :meth:`~set.discard` methods may be a set. To support searching for an equivalent frozenset, a temporary one is created from *elem*. +.. seealso:: + + For detailed information on thread-safety guarantees for :class:`set` + objects, see :ref:`thread-safety-set`. + .. _typesmapping: diff --git a/Doc/library/threadsafety.rst b/Doc/library/threadsafety.rst index 7ab5921c7ec..4f2eda19b85 100644 --- a/Doc/library/threadsafety.rst +++ b/Doc/library/threadsafety.rst @@ -342,3 +342,108 @@ thread, iterate over a copy: Consider external synchronization when sharing :class:`dict` instances across threads. + + +.. _thread-safety-set: + +Thread safety for set objects +============================== + +The :func:`len` function is lock-free and :term:`atomic `. + +The following read operation is lock-free. It does not block concurrent +modifications and may observe intermediate states from operations that +hold the per-object lock: + +.. code-block:: + :class: good + + elem in s # set.__contains__ + +This operation may compare elements using :meth:`~object.__eq__`, which can +execute arbitrary Python code. During such comparisons, the set may be +modified by another thread. For built-in types like :class:`str`, +:class:`int`, and :class:`float`, :meth:`!__eq__` does not release the +underlying lock during comparisons and this is not a concern. + +All other operations from here on hold the per-object lock. + +Adding or removing a single element is safe to call from multiple threads +and will not corrupt the set: + +.. code-block:: + :class: good + + s.add(elem) # add element + s.remove(elem) # remove element, raise if missing + s.discard(elem) # remove element if present + s.pop() # remove and return arbitrary element + +These operations also compare elements, so the same :meth:`~object.__eq__` +considerations as above apply. + +The :meth:`~set.copy` method returns a new object and holds the per-object lock +for the duration so that it is always atomic. + +The :meth:`~set.clear` method holds the lock for its duration. Other +threads cannot observe elements being removed. + +The following operations only accept :class:`set` or :class:`frozenset` +as operands and always lock both objects: + +.. code-block:: + :class: good + + s |= other # other must be set/frozenset + s &= other # other must be set/frozenset + s -= other # other must be set/frozenset + s ^= other # other must be set/frozenset + s & other # other must be set/frozenset + s | other # other must be set/frozenset + s - other # other must be set/frozenset + s ^ other # other must be set/frozenset + +:meth:`set.update`, :meth:`set.union`, :meth:`set.intersection` and +:meth:`set.difference` can take multiple iterables as arguments. They all +iterate through all the passed iterables and do the following: + + * :meth:`set.update` and :meth:`set.union` lock both objects only when + the other operand is a :class:`set`, :class:`frozenset`, or :class:`dict`. + * :meth:`set.intersection` and :meth:`set.difference` always try to lock + all objects. + +:meth:`set.symmetric_difference` tries to lock both objects. + +The update variants of the above methods also have some differences between +them: + + * :meth:`set.difference_update` and :meth:`set.intersection_update` try + to lock all objects one-by-one. + * :meth:`set.symmetric_difference_update` only locks the arguments if it is + of type :class:`set`, :class:`frozenset`, or :class:`dict`. + +The following methods always try to lock both objects: + +.. code-block:: + :class: good + + s.isdisjoint(other) # both locked + s.issubset(other) # both locked + s.issuperset(other) # both locked + +Operations that involve multiple accesses, as well as iteration, are never +atomic: + +.. code-block:: + :class: bad + + # NOT atomic: check-then-act + if elem in s: + s.remove(elem) + + # NOT thread-safe: iteration while modifying + for elem in s: + process(elem) # another thread may modify s + +Consider external synchronization when sharing :class:`set` instances +across threads. See :ref:`freethreading-python-howto` for more information. From 00a25859a94b6bf34e58a5176e2befab7e273d20 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 13 Mar 2026 16:42:19 +0100 Subject: [PATCH 124/775] gh-145376: Fix GC tracking in `structseq.__replace__` (#145820) --- Lib/test/test_structseq.py | 9 +++++++++ .../2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst | 1 + Objects/structseq.c | 1 + 3 files changed, 11 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst diff --git a/Lib/test/test_structseq.py b/Lib/test/test_structseq.py index 9622151143c..74506fc54de 100644 --- a/Lib/test/test_structseq.py +++ b/Lib/test/test_structseq.py @@ -1,4 +1,5 @@ import copy +import gc import os import pickle import re @@ -355,6 +356,14 @@ def test_reference_cycle(self): type(t).refcyle = t """)) + def test_replace_gc_tracked(self): + # Verify that __replace__ results are properly GC-tracked + time_struct = time.gmtime(0) + lst = [] + replaced_struct = time_struct.__replace__(tm_year=lst) + lst.append(replaced_struct) + + self.assertTrue(gc.is_tracked(replaced_struct)) if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst new file mode 100644 index 00000000000..476be205da8 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst @@ -0,0 +1 @@ +Fix GC tracking in ``structseq.__replace__()``. diff --git a/Objects/structseq.c b/Objects/structseq.c index b8bb041f0cf..8fa9cbba3bc 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -445,6 +445,7 @@ structseq_replace(PyObject *op, PyObject *args, PyObject *kwargs) } } + _PyObject_GC_TRACK(result); return (PyObject *)result; error: From 747ef70faa8637ccf6dd896323fa84aee8f14513 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 13 Mar 2026 18:51:23 +0100 Subject: [PATCH 125/775] GH-60729: Revert "Add IEEE format wave audio support (GH-145384)" (GH-145928) Revert "GH-60729: Add IEEE format wave audio support (GH-145384)" This reverts commit 61f2a1a5993967ed4b97ba93a4477c37fe68cf59 for now; as tests fail on big-endian machines. --- Doc/library/wave.rst | 69 +------ Doc/whatsnew/3.15.rst | 15 -- Lib/test/audiodata/pluck-float32.wav | Bin 26514 -> 0 bytes Lib/test/audiotests.py | 16 +- Lib/test/test_wave.py | 188 +----------------- Lib/wave.py | 88 ++------ ...3-03-10-13-10-06.gh-issue-60729.KCCHTe.rst | 1 - 7 files changed, 25 insertions(+), 352 deletions(-) delete mode 100644 Lib/test/audiodata/pluck-float32.wav delete mode 100644 Misc/NEWS.d/next/Library/2023-03-10-13-10-06.gh-issue-60729.KCCHTe.rst diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 9d30a14f112..ff020b52da3 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -9,19 +9,14 @@ -------------- The :mod:`!wave` module provides a convenient interface to the Waveform Audio -"WAVE" (or "WAV") file format. - -The module supports uncompressed PCM and IEEE floating-point WAV formats. +"WAVE" (or "WAV") file format. Only uncompressed PCM encoded wave files are +supported. .. versionchanged:: 3.12 Support for ``WAVE_FORMAT_EXTENSIBLE`` headers was added, provided that the extended format is ``KSDATAFORMAT_SUBTYPE_PCM``. -.. versionchanged:: next - - Support for reading and writing ``WAVE_FORMAT_IEEE_FLOAT`` files was added. - The :mod:`!wave` module defines the following function and exception: @@ -65,21 +60,6 @@ The :mod:`!wave` module defines the following function and exception: specification or hits an implementation deficiency. -.. data:: WAVE_FORMAT_PCM - - Format code for uncompressed PCM audio. - - -.. data:: WAVE_FORMAT_IEEE_FLOAT - - Format code for IEEE floating-point audio. - - -.. data:: WAVE_FORMAT_EXTENSIBLE - - Format code for WAVE extensible headers. - - .. _wave-read-objects: Wave_read Objects @@ -118,14 +98,6 @@ Wave_read Objects Returns number of audio frames. - .. method:: getformat() - - Returns the frame format code. - - This is one of :data:`WAVE_FORMAT_PCM`, - :data:`WAVE_FORMAT_IEEE_FLOAT`, or :data:`WAVE_FORMAT_EXTENSIBLE`. - - .. method:: getcomptype() Returns compression type (``'NONE'`` is the only supported type). @@ -140,8 +112,8 @@ Wave_read Objects .. method:: getparams() Returns a :func:`~collections.namedtuple` ``(nchannels, sampwidth, - framerate, nframes, comptype, compname)``, equivalent to output - of the ``get*()`` methods. + framerate, nframes, comptype, compname)``, equivalent to output of the + ``get*()`` methods. .. method:: readframes(n) @@ -218,9 +190,6 @@ Wave_write Objects Set the sample width to *n* bytes. - For :data:`WAVE_FORMAT_IEEE_FLOAT`, only 4-byte (32-bit) and - 8-byte (64-bit) sample widths are supported. - .. method:: getsampwidth() @@ -269,32 +238,11 @@ Wave_write Objects Return the human-readable compression type name. - .. method:: setformat(format) - - Set the frame format code. - - Supported values are :data:`WAVE_FORMAT_PCM` and - :data:`WAVE_FORMAT_IEEE_FLOAT`. - - When setting :data:`WAVE_FORMAT_IEEE_FLOAT`, the sample width must be - 4 or 8 bytes. - - - .. method:: getformat() - - Return the current frame format code. - - .. method:: setparams(tuple) - The *tuple* should be - ``(nchannels, sampwidth, framerate, nframes, comptype, compname, format)``, - with values valid for the ``set*()`` methods. Sets all parameters. - - For backwards compatibility, a 6-item tuple without *format* is also - accepted and defaults to :data:`WAVE_FORMAT_PCM`. - - For ``format=WAVE_FORMAT_IEEE_FLOAT``, *sampwidth* must be 4 or 8. + The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype, + compname)``, with values valid for the ``set*()`` methods. Sets all + parameters. .. method:: getparams() @@ -331,6 +279,3 @@ Wave_write Objects Note that it is invalid to set any parameters after calling :meth:`writeframes` or :meth:`writeframesraw`, and any attempt to do so will raise :exc:`wave.Error`. - - For :data:`WAVE_FORMAT_IEEE_FLOAT` output, a ``fact`` chunk is written as - required by the WAVE specification for non-PCM formats. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index d5b14216770..459846e55cc 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1518,21 +1518,6 @@ typing wave ---- -* Added support for IEEE floating-point WAVE audio - (``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`. - -* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`, - and :meth:`wave.Wave_write.setformat` for explicit frame format handling. - -* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including - ``format`` and 6-item tuples for backwards compatibility (defaulting to - ``WAVE_FORMAT_PCM``). - -* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk, - as required for non-PCM WAVE formats. - -(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.) - * Removed the ``getmark()``, ``setmark()`` and ``getmarkers()`` methods of the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes, which were deprecated since Python 3.13. diff --git a/Lib/test/audiodata/pluck-float32.wav b/Lib/test/audiodata/pluck-float32.wav deleted file mode 100644 index 2030fb16d6e3bd797523605091ff1d732b432b88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26514 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±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 4: + if sampwidth < 1 or sampwidth > 4: raise Error('bad sample width') self._sampwidth = sampwidth @@ -546,18 +518,6 @@ def setcomptype(self, comptype, compname): self._comptype = comptype self._compname = compname - def setformat(self, format): - if self._datawritten: - raise Error('cannot change parameters after starting to write') - if format not in (WAVE_FORMAT_IEEE_FLOAT, WAVE_FORMAT_PCM): - raise Error('unsupported wave format') - if format == WAVE_FORMAT_IEEE_FLOAT and self._sampwidth and self._sampwidth not in (4, 8): - raise Error('unsupported sample width for IEEE float format') - self._format = format - - def getformat(self): - return self._format - def getcomptype(self): return self._comptype @@ -565,15 +525,10 @@ def getcompname(self): return self._compname def setparams(self, params): + nchannels, sampwidth, framerate, nframes, comptype, compname = params if self._datawritten: raise Error('cannot change parameters after starting to write') - if len(params) == 6: - nchannels, sampwidth, framerate, nframes, comptype, compname = params - format = WAVE_FORMAT_PCM - else: - nchannels, sampwidth, framerate, nframes, comptype, compname, format = params self.setnchannels(nchannels) - self.setformat(format) self.setsampwidth(sampwidth) self.setframerate(framerate) self.setnframes(nframes) @@ -634,9 +589,6 @@ def _ensure_header_written(self, datasize): raise Error('sampling rate not specified') self._write_header(datasize) - def _needs_fact_chunk(self): - return self._format == WAVE_FORMAT_IEEE_FLOAT - def _write_header(self, initlength): assert not self._headerwritten self._file.write(b'RIFF') @@ -647,23 +599,12 @@ def _write_header(self, initlength): self._form_length_pos = self._file.tell() except (AttributeError, OSError): self._form_length_pos = None - has_fact = self._needs_fact_chunk() - header_overhead = 36 + (12 if has_fact else 0) - self._file.write(struct.pack(' Date: Fri, 13 Mar 2026 19:44:51 +0100 Subject: [PATCH 126/775] gh-129813: Document that PyBytesWriter_GetData() cannot fail (#145900) Document that PyBytesWriter_GetData() and PyBytesWriter_GetSize() getter functions cannot fail --- Doc/c-api/bytes.rst | 4 ++++ Modules/binascii.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst index 82c25573683..b3cd26a8504 100644 --- a/Doc/c-api/bytes.rst +++ b/Doc/c-api/bytes.rst @@ -371,6 +371,8 @@ Getters Get the writer size. + The function cannot fail. + .. c:function:: void* PyBytesWriter_GetData(PyBytesWriter *writer) Get the writer data: start of the internal buffer. @@ -378,6 +380,8 @@ Getters The pointer is valid until :c:func:`PyBytesWriter_Finish` or :c:func:`PyBytesWriter_Discard` is called on *writer*. + The function cannot fail. + Low-level API ^^^^^^^^^^^^^ diff --git a/Modules/binascii.c b/Modules/binascii.c index 3f3695d50f2..c076b12fb14 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -923,9 +923,6 @@ binascii_a2b_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, return NULL; } unsigned char *bin_data = PyBytesWriter_GetData(writer); - if (bin_data == NULL) { - goto error; - } uint32_t leftchar = 0; int group_pos = 0; From 77c06f3da629b5088975309959ef6895bef841e3 Mon Sep 17 00:00:00 2001 From: Konstantin Vlasov Date: Sat, 14 Mar 2026 06:37:30 +0100 Subject: [PATCH 127/775] gh-145703: Fix `asyncio.BaseEventLoop` low clock resolution (#145706) --- Lib/asyncio/base_events.py | 8 ++++++-- .../2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index b565b1d8a9e..0930ef403c6 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -19,14 +19,15 @@ import errno import heapq import itertools +import math import os import socket import stat import subprocess +import sys import threading import time import traceback -import sys import warnings import weakref @@ -2022,7 +2023,10 @@ def _run_once(self): event_list = None # Handle 'later' callbacks that are ready. - end_time = self.time() + self._clock_resolution + now = self.time() + # Ensure that `end_time` is strictly increasing + # when the clock resolution is too small. + end_time = now + max(self._clock_resolution, math.ulp(now)) while self._scheduled: handle = self._scheduled[0] if handle._when >= end_time: diff --git a/Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst b/Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst new file mode 100644 index 00000000000..bc239ce58c9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst @@ -0,0 +1,3 @@ +:mod:`asyncio`: Make sure that :meth:`loop.call_at ` and +:meth:`loop.call_later ` trigger scheduled events on +time when the clock resolution becomes too small. From 51e8acf8de1aa1f1751dd5bb84d44b8d42143b9c Mon Sep 17 00:00:00 2001 From: Connor Gibson Date: Sat, 14 Mar 2026 02:19:00 -0700 Subject: [PATCH 128/775] Docs: fix missing period in `Doc/library/stdtypes.rst` (#145935) --- Doc/library/stdtypes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 7ae399eb95b..6e2c72daf7a 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1286,7 +1286,7 @@ Mutable sequence types also support the following methods: :no-typesetting: .. method:: sequence.append(value, /) - Append *value* to the end of the sequence + Append *value* to the end of the sequence. This is equivalent to writing ``seq[len(seq):len(seq)] = [value]``. .. method:: bytearray.clear() From 97968564b61965f2a65a9be8af731cee6913eb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 14 Mar 2026 10:58:15 +0100 Subject: [PATCH 129/775] gh-143636: fix a crash when calling ``__replace__`` on invalid `SimpleNamespace` instances (#143655) --- Lib/test/test_types.py | 15 +++++++++++++++ ...2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst | 2 ++ Objects/namespaceobject.c | 9 +++++++++ 3 files changed, 26 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 39d57c5f5b6..2084b30d71f 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -2168,6 +2168,21 @@ class Spam(types.SimpleNamespace): self.assertIs(type(spam2), Spam) self.assertEqual(vars(spam2), {'ham': 5, 'eggs': 9}) + def test_replace_invalid_subtype(self): + # See https://github.com/python/cpython/issues/143636. + class MyNS(types.SimpleNamespace): + def __new__(cls, *args, **kwargs): + if created: + return 12345 + return super().__new__(cls) + + created = False + ns = MyNS() + created = True + err = (r"^expect types\.SimpleNamespace type, " + r"but .+\.MyNS\(\) returned 'int' object") + self.assertRaisesRegex(TypeError, err, copy.replace, ns) + def test_fake_namespace_compare(self): # Issue #24257: Incorrect use of PyObject_IsInstance() caused # SystemError. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst new file mode 100644 index 00000000000..4d5249ffe3a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst @@ -0,0 +1,2 @@ +Fix a crash when calling :class:`SimpleNamespace.__replace__() +` on non-namespace instances. Patch by Bénédikt Tran. diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c index 201cb8a7df8..3803c41027d 100644 --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -13,6 +13,7 @@ typedef struct { } _PyNamespaceObject; #define _PyNamespace_CAST(op) _Py_CAST(_PyNamespaceObject*, (op)) +#define _PyNamespace_Check(op) PyObject_TypeCheck((op), &_PyNamespace_Type) static PyMemberDef namespace_members[] = { @@ -234,6 +235,14 @@ namespace_replace(PyObject *self, PyObject *args, PyObject *kwargs) if (!result) { return NULL; } + if (!_PyNamespace_Check(result)) { + PyErr_Format(PyExc_TypeError, + "expect %N type, but %T() returned '%T' object", + &_PyNamespace_Type, self, result); + Py_DECREF(result); + return NULL; + } + if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict, ((_PyNamespaceObject*)self)->ns_dict) < 0) { From 798070d8ca4a32c1d7d10e69defcb1b2f934bea6 Mon Sep 17 00:00:00 2001 From: Sacul <183588943+Sacul0457@users.noreply.github.com> Date: Sat, 14 Mar 2026 20:00:18 +0800 Subject: [PATCH 130/775] gh-134584: Eliminate redundant refcounting in JIT for `MATCH_CLASS` (GH-144821) --- Include/internal/pycore_opcode_metadata.h | 4 +- Include/internal/pycore_uop_ids.h | 1940 ++++++++--------- Include/internal/pycore_uop_metadata.h | 8 +- Lib/test/test_capi/test_opt.py | 18 + ...-02-14-15-51-16.gh-issue-134584.6WFSuB.rst | 1 + Modules/_testinternalcapi/test_cases.c.h | 91 +- Python/bytecodes.c | 13 +- Python/executor_cases.c.h | 33 +- Python/generated_cases.c.h | 91 +- Python/optimizer_bytecodes.c | 7 + Python/optimizer_cases.c.h | 19 +- 11 files changed, 1155 insertions(+), 1070 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 2586ed3a529..c64d4e8ba85 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1260,7 +1260,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [MAKE_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [MATCH_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MATCH_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [MATCH_KEYS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_MAPPING] = { true, INSTR_FMT_IX, 0 }, [MATCH_SEQUENCE] = { true, INSTR_FMT_IX, 0 }, @@ -1478,7 +1478,7 @@ _PyOpcode_macro_expansion[256] = { [MAKE_CELL] = { .nuops = 1, .uops = { { _MAKE_CELL, OPARG_SIMPLE, 0 } } }, [MAKE_FUNCTION] = { .nuops = 1, .uops = { { _MAKE_FUNCTION, OPARG_SIMPLE, 0 } } }, [MAP_ADD] = { .nuops = 1, .uops = { { _MAP_ADD, OPARG_SIMPLE, 0 } } }, - [MATCH_CLASS] = { .nuops = 1, .uops = { { _MATCH_CLASS, OPARG_SIMPLE, 0 } } }, + [MATCH_CLASS] = { .nuops = 4, .uops = { { _MATCH_CLASS, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [MATCH_KEYS] = { .nuops = 1, .uops = { { _MATCH_KEYS, OPARG_SIMPLE, 0 } } }, [MATCH_MAPPING] = { .nuops = 1, .uops = { { _MATCH_MAPPING, OPARG_SIMPLE, 0 } } }, [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { _MATCH_SEQUENCE, OPARG_SIMPLE, 0 } } }, diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 79e62edfeed..0fdeb56122e 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -293,1000 +293,1000 @@ extern "C" { #define _MAKE_HEAP_SAFE 519 #define _MAKE_WARM 520 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS MATCH_CLASS +#define _MATCH_CLASS 521 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 521 -#define _MAYBE_EXPAND_METHOD_KW 522 -#define _MONITOR_CALL 523 -#define _MONITOR_CALL_KW 524 -#define _MONITOR_JUMP_BACKWARD 525 -#define _MONITOR_RESUME 526 +#define _MAYBE_EXPAND_METHOD 522 +#define _MAYBE_EXPAND_METHOD_KW 523 +#define _MONITOR_CALL 524 +#define _MONITOR_CALL_KW 525 +#define _MONITOR_JUMP_BACKWARD 526 +#define _MONITOR_RESUME 527 #define _NOP NOP -#define _POP_CALL 527 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 528 -#define _POP_CALL_ONE 529 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 530 -#define _POP_CALL_TWO 531 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 532 +#define _POP_CALL 528 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 529 +#define _POP_CALL_ONE 530 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 531 +#define _POP_CALL_TWO 532 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 533 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 533 -#define _POP_JUMP_IF_TRUE 534 +#define _POP_JUMP_IF_FALSE 534 +#define _POP_JUMP_IF_TRUE 535 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 535 -#define _POP_TOP_INT 536 -#define _POP_TOP_LOAD_CONST_INLINE 537 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 538 -#define _POP_TOP_NOP 539 -#define _POP_TOP_UNICODE 540 -#define _POP_TWO 541 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 542 +#define _POP_TOP_FLOAT 536 +#define _POP_TOP_INT 537 +#define _POP_TOP_LOAD_CONST_INLINE 538 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 539 +#define _POP_TOP_NOP 540 +#define _POP_TOP_UNICODE 541 +#define _POP_TWO 542 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 543 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 543 +#define _PUSH_FRAME 544 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 544 -#define _PY_FRAME_EX 545 -#define _PY_FRAME_GENERAL 546 -#define _PY_FRAME_KW 547 -#define _QUICKEN_RESUME 548 -#define _RECORD_4OS 549 -#define _RECORD_BOUND_METHOD 550 -#define _RECORD_CALLABLE 551 -#define _RECORD_CODE 552 -#define _RECORD_NOS 553 -#define _RECORD_NOS_GEN_FUNC 554 -#define _RECORD_TOS 555 -#define _RECORD_TOS_TYPE 556 -#define _REPLACE_WITH_TRUE 557 +#define _PUSH_NULL_CONDITIONAL 545 +#define _PY_FRAME_EX 546 +#define _PY_FRAME_GENERAL 547 +#define _PY_FRAME_KW 548 +#define _QUICKEN_RESUME 549 +#define _RECORD_4OS 550 +#define _RECORD_BOUND_METHOD 551 +#define _RECORD_CALLABLE 552 +#define _RECORD_CODE 553 +#define _RECORD_NOS 554 +#define _RECORD_NOS_GEN_FUNC 555 +#define _RECORD_TOS 556 +#define _RECORD_TOS_TYPE 557 +#define _REPLACE_WITH_TRUE 558 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 558 -#define _SAVE_RETURN_OFFSET 559 -#define _SEND 560 -#define _SEND_GEN_FRAME 561 +#define _RETURN_VALUE 559 +#define _SAVE_RETURN_OFFSET 560 +#define _SEND 561 +#define _SEND_GEN_FRAME 562 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 562 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 563 -#define _SPILL_OR_RELOAD 564 -#define _START_EXECUTOR 565 -#define _STORE_ATTR 566 -#define _STORE_ATTR_INSTANCE_VALUE 567 -#define _STORE_ATTR_SLOT 568 -#define _STORE_ATTR_WITH_HINT 569 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 563 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 564 +#define _SPILL_OR_RELOAD 565 +#define _START_EXECUTOR 566 +#define _STORE_ATTR 567 +#define _STORE_ATTR_INSTANCE_VALUE 568 +#define _STORE_ATTR_SLOT 569 +#define _STORE_ATTR_WITH_HINT 570 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 570 -#define _STORE_SUBSCR 571 -#define _STORE_SUBSCR_DICT 572 -#define _STORE_SUBSCR_LIST_INT 573 -#define _SWAP 574 -#define _SWAP_2 575 -#define _SWAP_3 576 -#define _SWAP_FAST 577 -#define _SWAP_FAST_0 578 -#define _SWAP_FAST_1 579 -#define _SWAP_FAST_2 580 -#define _SWAP_FAST_3 581 -#define _SWAP_FAST_4 582 -#define _SWAP_FAST_5 583 -#define _SWAP_FAST_6 584 -#define _SWAP_FAST_7 585 -#define _TIER2_RESUME_CHECK 586 -#define _TO_BOOL 587 +#define _STORE_SLICE 571 +#define _STORE_SUBSCR 572 +#define _STORE_SUBSCR_DICT 573 +#define _STORE_SUBSCR_LIST_INT 574 +#define _SWAP 575 +#define _SWAP_2 576 +#define _SWAP_3 577 +#define _SWAP_FAST 578 +#define _SWAP_FAST_0 579 +#define _SWAP_FAST_1 580 +#define _SWAP_FAST_2 581 +#define _SWAP_FAST_3 582 +#define _SWAP_FAST_4 583 +#define _SWAP_FAST_5 584 +#define _SWAP_FAST_6 585 +#define _SWAP_FAST_7 586 +#define _TIER2_RESUME_CHECK 587 +#define _TO_BOOL 588 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 588 -#define _TO_BOOL_LIST 589 +#define _TO_BOOL_INT 589 +#define _TO_BOOL_LIST 590 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 590 +#define _TO_BOOL_STR 591 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 591 -#define _UNARY_NEGATIVE 592 +#define _UNARY_INVERT 592 +#define _UNARY_NEGATIVE 593 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 593 -#define _UNPACK_SEQUENCE_LIST 594 -#define _UNPACK_SEQUENCE_TUPLE 595 -#define _UNPACK_SEQUENCE_TWO_TUPLE 596 +#define _UNPACK_SEQUENCE 594 +#define _UNPACK_SEQUENCE_LIST 595 +#define _UNPACK_SEQUENCE_TUPLE 596 +#define _UNPACK_SEQUENCE_TWO_TUPLE 597 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 597 -#define MAX_UOP_ID 597 -#define _BINARY_OP_r23 598 -#define _BINARY_OP_ADD_FLOAT_r03 599 -#define _BINARY_OP_ADD_FLOAT_r13 600 -#define _BINARY_OP_ADD_FLOAT_r23 601 -#define _BINARY_OP_ADD_INT_r03 602 -#define _BINARY_OP_ADD_INT_r13 603 -#define _BINARY_OP_ADD_INT_r23 604 -#define _BINARY_OP_ADD_UNICODE_r03 605 -#define _BINARY_OP_ADD_UNICODE_r13 606 -#define _BINARY_OP_ADD_UNICODE_r23 607 -#define _BINARY_OP_EXTEND_r23 608 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 609 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 610 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 611 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 612 -#define _BINARY_OP_MULTIPLY_INT_r03 613 -#define _BINARY_OP_MULTIPLY_INT_r13 614 -#define _BINARY_OP_MULTIPLY_INT_r23 615 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 616 -#define _BINARY_OP_SUBSCR_DICT_r23 617 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 618 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 619 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 620 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 621 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 622 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 623 -#define _BINARY_OP_SUBSCR_STR_INT_r23 624 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 625 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 626 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 627 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 628 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 629 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 630 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 631 -#define _BINARY_OP_SUBTRACT_INT_r03 632 -#define _BINARY_OP_SUBTRACT_INT_r13 633 -#define _BINARY_OP_SUBTRACT_INT_r23 634 -#define _BINARY_SLICE_r31 635 -#define _BUILD_INTERPOLATION_r01 636 -#define _BUILD_LIST_r01 637 -#define _BUILD_MAP_r01 638 -#define _BUILD_SET_r01 639 -#define _BUILD_SLICE_r01 640 -#define _BUILD_STRING_r01 641 -#define _BUILD_TEMPLATE_r21 642 -#define _BUILD_TUPLE_r01 643 -#define _CALL_BUILTIN_CLASS_r01 644 -#define _CALL_BUILTIN_FAST_r01 645 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 646 -#define _CALL_BUILTIN_O_r03 647 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 648 -#define _CALL_INTRINSIC_1_r11 649 -#define _CALL_INTRINSIC_2_r21 650 -#define _CALL_ISINSTANCE_r31 651 -#define _CALL_KW_NON_PY_r11 652 -#define _CALL_LEN_r33 653 -#define _CALL_LIST_APPEND_r03 654 -#define _CALL_LIST_APPEND_r13 655 -#define _CALL_LIST_APPEND_r23 656 -#define _CALL_LIST_APPEND_r33 657 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 658 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 659 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 660 -#define _CALL_METHOD_DESCRIPTOR_O_r03 661 -#define _CALL_NON_PY_GENERAL_r01 662 -#define _CALL_STR_1_r32 663 -#define _CALL_TUPLE_1_r32 664 -#define _CALL_TYPE_1_r02 665 -#define _CALL_TYPE_1_r12 666 -#define _CALL_TYPE_1_r22 667 -#define _CALL_TYPE_1_r32 668 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 669 -#define _CHECK_ATTR_CLASS_r01 670 -#define _CHECK_ATTR_CLASS_r11 671 -#define _CHECK_ATTR_CLASS_r22 672 -#define _CHECK_ATTR_CLASS_r33 673 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 674 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 675 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 676 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 677 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 678 -#define _CHECK_EG_MATCH_r22 679 -#define _CHECK_EXC_MATCH_r22 680 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 681 -#define _CHECK_FUNCTION_VERSION_r00 682 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 683 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 684 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 685 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 686 -#define _CHECK_FUNCTION_VERSION_KW_r11 687 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 688 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 689 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 690 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 691 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 692 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 693 -#define _CHECK_IS_PY_CALLABLE_EX_r03 694 -#define _CHECK_IS_PY_CALLABLE_EX_r13 695 -#define _CHECK_IS_PY_CALLABLE_EX_r23 696 -#define _CHECK_IS_PY_CALLABLE_EX_r33 697 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 698 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 699 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 700 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 701 -#define _CHECK_METHOD_VERSION_r00 702 -#define _CHECK_METHOD_VERSION_KW_r11 703 -#define _CHECK_PEP_523_r00 704 -#define _CHECK_PEP_523_r11 705 -#define _CHECK_PEP_523_r22 706 -#define _CHECK_PEP_523_r33 707 -#define _CHECK_PERIODIC_r00 708 -#define _CHECK_PERIODIC_AT_END_r00 709 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 710 -#define _CHECK_RECURSION_REMAINING_r00 711 -#define _CHECK_RECURSION_REMAINING_r11 712 -#define _CHECK_RECURSION_REMAINING_r22 713 -#define _CHECK_RECURSION_REMAINING_r33 714 -#define _CHECK_STACK_SPACE_r00 715 -#define _CHECK_STACK_SPACE_OPERAND_r00 716 -#define _CHECK_STACK_SPACE_OPERAND_r11 717 -#define _CHECK_STACK_SPACE_OPERAND_r22 718 -#define _CHECK_STACK_SPACE_OPERAND_r33 719 -#define _CHECK_VALIDITY_r00 720 -#define _CHECK_VALIDITY_r11 721 -#define _CHECK_VALIDITY_r22 722 -#define _CHECK_VALIDITY_r33 723 -#define _COLD_DYNAMIC_EXIT_r00 724 -#define _COLD_EXIT_r00 725 -#define _COMPARE_OP_r21 726 -#define _COMPARE_OP_FLOAT_r03 727 -#define _COMPARE_OP_FLOAT_r13 728 -#define _COMPARE_OP_FLOAT_r23 729 -#define _COMPARE_OP_INT_r23 730 -#define _COMPARE_OP_STR_r23 731 -#define _CONTAINS_OP_r23 732 -#define _CONTAINS_OP_DICT_r23 733 -#define _CONTAINS_OP_SET_r23 734 -#define _CONVERT_VALUE_r11 735 -#define _COPY_r01 736 -#define _COPY_1_r02 737 -#define _COPY_1_r12 738 -#define _COPY_1_r23 739 -#define _COPY_2_r03 740 -#define _COPY_2_r13 741 -#define _COPY_2_r23 742 -#define _COPY_3_r03 743 -#define _COPY_3_r13 744 -#define _COPY_3_r23 745 -#define _COPY_3_r33 746 -#define _COPY_FREE_VARS_r00 747 -#define _COPY_FREE_VARS_r11 748 -#define _COPY_FREE_VARS_r22 749 -#define _COPY_FREE_VARS_r33 750 -#define _CREATE_INIT_FRAME_r01 751 -#define _DELETE_ATTR_r10 752 -#define _DELETE_DEREF_r00 753 -#define _DELETE_FAST_r00 754 -#define _DELETE_GLOBAL_r00 755 -#define _DELETE_NAME_r00 756 -#define _DELETE_SUBSCR_r20 757 -#define _DEOPT_r00 758 -#define _DEOPT_r10 759 -#define _DEOPT_r20 760 -#define _DEOPT_r30 761 -#define _DICT_MERGE_r10 762 -#define _DICT_UPDATE_r10 763 -#define _DO_CALL_r01 764 -#define _DO_CALL_FUNCTION_EX_r31 765 -#define _DO_CALL_KW_r11 766 -#define _DYNAMIC_EXIT_r00 767 -#define _DYNAMIC_EXIT_r10 768 -#define _DYNAMIC_EXIT_r20 769 -#define _DYNAMIC_EXIT_r30 770 -#define _END_FOR_r10 771 -#define _END_SEND_r21 772 -#define _ERROR_POP_N_r00 773 -#define _EXIT_INIT_CHECK_r10 774 -#define _EXIT_TRACE_r00 775 -#define _EXIT_TRACE_r10 776 -#define _EXIT_TRACE_r20 777 -#define _EXIT_TRACE_r30 778 -#define _EXPAND_METHOD_r00 779 -#define _EXPAND_METHOD_KW_r11 780 -#define _FATAL_ERROR_r00 781 -#define _FATAL_ERROR_r11 782 -#define _FATAL_ERROR_r22 783 -#define _FATAL_ERROR_r33 784 -#define _FORMAT_SIMPLE_r11 785 -#define _FORMAT_WITH_SPEC_r21 786 -#define _FOR_ITER_r23 787 -#define _FOR_ITER_GEN_FRAME_r03 788 -#define _FOR_ITER_GEN_FRAME_r13 789 -#define _FOR_ITER_GEN_FRAME_r23 790 -#define _FOR_ITER_TIER_TWO_r23 791 -#define _GET_AITER_r11 792 -#define _GET_ANEXT_r12 793 -#define _GET_AWAITABLE_r11 794 -#define _GET_ITER_r12 795 -#define _GET_LEN_r12 796 -#define _GET_YIELD_FROM_ITER_r11 797 -#define _GUARD_BINARY_OP_EXTEND_r22 798 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 799 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 800 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 801 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 802 -#define _GUARD_BIT_IS_SET_POP_r00 803 -#define _GUARD_BIT_IS_SET_POP_r10 804 -#define _GUARD_BIT_IS_SET_POP_r21 805 -#define _GUARD_BIT_IS_SET_POP_r32 806 -#define _GUARD_BIT_IS_SET_POP_4_r00 807 -#define _GUARD_BIT_IS_SET_POP_4_r10 808 -#define _GUARD_BIT_IS_SET_POP_4_r21 809 -#define _GUARD_BIT_IS_SET_POP_4_r32 810 -#define _GUARD_BIT_IS_SET_POP_5_r00 811 -#define _GUARD_BIT_IS_SET_POP_5_r10 812 -#define _GUARD_BIT_IS_SET_POP_5_r21 813 -#define _GUARD_BIT_IS_SET_POP_5_r32 814 -#define _GUARD_BIT_IS_SET_POP_6_r00 815 -#define _GUARD_BIT_IS_SET_POP_6_r10 816 -#define _GUARD_BIT_IS_SET_POP_6_r21 817 -#define _GUARD_BIT_IS_SET_POP_6_r32 818 -#define _GUARD_BIT_IS_SET_POP_7_r00 819 -#define _GUARD_BIT_IS_SET_POP_7_r10 820 -#define _GUARD_BIT_IS_SET_POP_7_r21 821 -#define _GUARD_BIT_IS_SET_POP_7_r32 822 -#define _GUARD_BIT_IS_UNSET_POP_r00 823 -#define _GUARD_BIT_IS_UNSET_POP_r10 824 -#define _GUARD_BIT_IS_UNSET_POP_r21 825 -#define _GUARD_BIT_IS_UNSET_POP_r32 826 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 827 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 828 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 829 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 830 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 831 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 832 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 833 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 834 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 835 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 836 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 837 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 838 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 839 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 840 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 841 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 842 -#define _GUARD_CALLABLE_ISINSTANCE_r03 843 -#define _GUARD_CALLABLE_ISINSTANCE_r13 844 -#define _GUARD_CALLABLE_ISINSTANCE_r23 845 -#define _GUARD_CALLABLE_ISINSTANCE_r33 846 -#define _GUARD_CALLABLE_LEN_r03 847 -#define _GUARD_CALLABLE_LEN_r13 848 -#define _GUARD_CALLABLE_LEN_r23 849 -#define _GUARD_CALLABLE_LEN_r33 850 -#define _GUARD_CALLABLE_LIST_APPEND_r03 851 -#define _GUARD_CALLABLE_LIST_APPEND_r13 852 -#define _GUARD_CALLABLE_LIST_APPEND_r23 853 -#define _GUARD_CALLABLE_LIST_APPEND_r33 854 -#define _GUARD_CALLABLE_STR_1_r03 855 -#define _GUARD_CALLABLE_STR_1_r13 856 -#define _GUARD_CALLABLE_STR_1_r23 857 -#define _GUARD_CALLABLE_STR_1_r33 858 -#define _GUARD_CALLABLE_TUPLE_1_r03 859 -#define _GUARD_CALLABLE_TUPLE_1_r13 860 -#define _GUARD_CALLABLE_TUPLE_1_r23 861 -#define _GUARD_CALLABLE_TUPLE_1_r33 862 -#define _GUARD_CALLABLE_TYPE_1_r03 863 -#define _GUARD_CALLABLE_TYPE_1_r13 864 -#define _GUARD_CALLABLE_TYPE_1_r23 865 -#define _GUARD_CALLABLE_TYPE_1_r33 866 -#define _GUARD_CODE_VERSION_r00 867 -#define _GUARD_CODE_VERSION_r11 868 -#define _GUARD_CODE_VERSION_r22 869 -#define _GUARD_CODE_VERSION_r33 870 -#define _GUARD_DORV_NO_DICT_r01 871 -#define _GUARD_DORV_NO_DICT_r11 872 -#define _GUARD_DORV_NO_DICT_r22 873 -#define _GUARD_DORV_NO_DICT_r33 874 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 875 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 876 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 877 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 878 -#define _GUARD_GLOBALS_VERSION_r00 879 -#define _GUARD_GLOBALS_VERSION_r11 880 -#define _GUARD_GLOBALS_VERSION_r22 881 -#define _GUARD_GLOBALS_VERSION_r33 882 -#define _GUARD_IP_RETURN_GENERATOR_r00 883 -#define _GUARD_IP_RETURN_GENERATOR_r11 884 -#define _GUARD_IP_RETURN_GENERATOR_r22 885 -#define _GUARD_IP_RETURN_GENERATOR_r33 886 -#define _GUARD_IP_RETURN_VALUE_r00 887 -#define _GUARD_IP_RETURN_VALUE_r11 888 -#define _GUARD_IP_RETURN_VALUE_r22 889 -#define _GUARD_IP_RETURN_VALUE_r33 890 -#define _GUARD_IP_YIELD_VALUE_r00 891 -#define _GUARD_IP_YIELD_VALUE_r11 892 -#define _GUARD_IP_YIELD_VALUE_r22 893 -#define _GUARD_IP_YIELD_VALUE_r33 894 -#define _GUARD_IP__PUSH_FRAME_r00 895 -#define _GUARD_IP__PUSH_FRAME_r11 896 -#define _GUARD_IP__PUSH_FRAME_r22 897 -#define _GUARD_IP__PUSH_FRAME_r33 898 -#define _GUARD_IS_FALSE_POP_r00 899 -#define _GUARD_IS_FALSE_POP_r10 900 -#define _GUARD_IS_FALSE_POP_r21 901 -#define _GUARD_IS_FALSE_POP_r32 902 -#define _GUARD_IS_NONE_POP_r00 903 -#define _GUARD_IS_NONE_POP_r10 904 -#define _GUARD_IS_NONE_POP_r21 905 -#define _GUARD_IS_NONE_POP_r32 906 -#define _GUARD_IS_NOT_NONE_POP_r10 907 -#define _GUARD_IS_TRUE_POP_r00 908 -#define _GUARD_IS_TRUE_POP_r10 909 -#define _GUARD_IS_TRUE_POP_r21 910 -#define _GUARD_IS_TRUE_POP_r32 911 -#define _GUARD_KEYS_VERSION_r01 912 -#define _GUARD_KEYS_VERSION_r11 913 -#define _GUARD_KEYS_VERSION_r22 914 -#define _GUARD_KEYS_VERSION_r33 915 -#define _GUARD_NOS_ANY_DICT_r02 916 -#define _GUARD_NOS_ANY_DICT_r12 917 -#define _GUARD_NOS_ANY_DICT_r22 918 -#define _GUARD_NOS_ANY_DICT_r33 919 -#define _GUARD_NOS_COMPACT_ASCII_r02 920 -#define _GUARD_NOS_COMPACT_ASCII_r12 921 -#define _GUARD_NOS_COMPACT_ASCII_r22 922 -#define _GUARD_NOS_COMPACT_ASCII_r33 923 -#define _GUARD_NOS_DICT_r02 924 -#define _GUARD_NOS_DICT_r12 925 -#define _GUARD_NOS_DICT_r22 926 -#define _GUARD_NOS_DICT_r33 927 -#define _GUARD_NOS_FLOAT_r02 928 -#define _GUARD_NOS_FLOAT_r12 929 -#define _GUARD_NOS_FLOAT_r22 930 -#define _GUARD_NOS_FLOAT_r33 931 -#define _GUARD_NOS_INT_r02 932 -#define _GUARD_NOS_INT_r12 933 -#define _GUARD_NOS_INT_r22 934 -#define _GUARD_NOS_INT_r33 935 -#define _GUARD_NOS_LIST_r02 936 -#define _GUARD_NOS_LIST_r12 937 -#define _GUARD_NOS_LIST_r22 938 -#define _GUARD_NOS_LIST_r33 939 -#define _GUARD_NOS_NOT_NULL_r02 940 -#define _GUARD_NOS_NOT_NULL_r12 941 -#define _GUARD_NOS_NOT_NULL_r22 942 -#define _GUARD_NOS_NOT_NULL_r33 943 -#define _GUARD_NOS_NULL_r02 944 -#define _GUARD_NOS_NULL_r12 945 -#define _GUARD_NOS_NULL_r22 946 -#define _GUARD_NOS_NULL_r33 947 -#define _GUARD_NOS_OVERFLOWED_r02 948 -#define _GUARD_NOS_OVERFLOWED_r12 949 -#define _GUARD_NOS_OVERFLOWED_r22 950 -#define _GUARD_NOS_OVERFLOWED_r33 951 -#define _GUARD_NOS_TUPLE_r02 952 -#define _GUARD_NOS_TUPLE_r12 953 -#define _GUARD_NOS_TUPLE_r22 954 -#define _GUARD_NOS_TUPLE_r33 955 -#define _GUARD_NOS_UNICODE_r02 956 -#define _GUARD_NOS_UNICODE_r12 957 -#define _GUARD_NOS_UNICODE_r22 958 -#define _GUARD_NOS_UNICODE_r33 959 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 960 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 961 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 962 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 963 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 964 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 965 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 966 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 967 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 968 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 969 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 970 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 971 -#define _GUARD_THIRD_NULL_r03 972 -#define _GUARD_THIRD_NULL_r13 973 -#define _GUARD_THIRD_NULL_r23 974 -#define _GUARD_THIRD_NULL_r33 975 -#define _GUARD_TOS_ANY_DICT_r01 976 -#define _GUARD_TOS_ANY_DICT_r11 977 -#define _GUARD_TOS_ANY_DICT_r22 978 -#define _GUARD_TOS_ANY_DICT_r33 979 -#define _GUARD_TOS_ANY_SET_r01 980 -#define _GUARD_TOS_ANY_SET_r11 981 -#define _GUARD_TOS_ANY_SET_r22 982 -#define _GUARD_TOS_ANY_SET_r33 983 -#define _GUARD_TOS_DICT_r01 984 -#define _GUARD_TOS_DICT_r11 985 -#define _GUARD_TOS_DICT_r22 986 -#define _GUARD_TOS_DICT_r33 987 -#define _GUARD_TOS_FLOAT_r01 988 -#define _GUARD_TOS_FLOAT_r11 989 -#define _GUARD_TOS_FLOAT_r22 990 -#define _GUARD_TOS_FLOAT_r33 991 -#define _GUARD_TOS_FROZENDICT_r01 992 -#define _GUARD_TOS_FROZENDICT_r11 993 -#define _GUARD_TOS_FROZENDICT_r22 994 -#define _GUARD_TOS_FROZENDICT_r33 995 -#define _GUARD_TOS_FROZENSET_r01 996 -#define _GUARD_TOS_FROZENSET_r11 997 -#define _GUARD_TOS_FROZENSET_r22 998 -#define _GUARD_TOS_FROZENSET_r33 999 -#define _GUARD_TOS_INT_r01 1000 -#define _GUARD_TOS_INT_r11 1001 -#define _GUARD_TOS_INT_r22 1002 -#define _GUARD_TOS_INT_r33 1003 -#define _GUARD_TOS_LIST_r01 1004 -#define _GUARD_TOS_LIST_r11 1005 -#define _GUARD_TOS_LIST_r22 1006 -#define _GUARD_TOS_LIST_r33 1007 -#define _GUARD_TOS_OVERFLOWED_r01 1008 -#define _GUARD_TOS_OVERFLOWED_r11 1009 -#define _GUARD_TOS_OVERFLOWED_r22 1010 -#define _GUARD_TOS_OVERFLOWED_r33 1011 -#define _GUARD_TOS_SET_r01 1012 -#define _GUARD_TOS_SET_r11 1013 -#define _GUARD_TOS_SET_r22 1014 -#define _GUARD_TOS_SET_r33 1015 -#define _GUARD_TOS_SLICE_r01 1016 -#define _GUARD_TOS_SLICE_r11 1017 -#define _GUARD_TOS_SLICE_r22 1018 -#define _GUARD_TOS_SLICE_r33 1019 -#define _GUARD_TOS_TUPLE_r01 1020 -#define _GUARD_TOS_TUPLE_r11 1021 -#define _GUARD_TOS_TUPLE_r22 1022 -#define _GUARD_TOS_TUPLE_r33 1023 -#define _GUARD_TOS_UNICODE_r01 1024 -#define _GUARD_TOS_UNICODE_r11 1025 -#define _GUARD_TOS_UNICODE_r22 1026 -#define _GUARD_TOS_UNICODE_r33 1027 -#define _GUARD_TYPE_VERSION_r01 1028 -#define _GUARD_TYPE_VERSION_r11 1029 -#define _GUARD_TYPE_VERSION_r22 1030 -#define _GUARD_TYPE_VERSION_r33 1031 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1032 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1033 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1034 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1035 -#define _HANDLE_PENDING_AND_DEOPT_r00 1036 -#define _HANDLE_PENDING_AND_DEOPT_r10 1037 -#define _HANDLE_PENDING_AND_DEOPT_r20 1038 -#define _HANDLE_PENDING_AND_DEOPT_r30 1039 -#define _IMPORT_FROM_r12 1040 -#define _IMPORT_NAME_r21 1041 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1042 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1043 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1044 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1045 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1046 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1047 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1048 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1049 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1050 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1051 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1052 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1053 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1054 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1055 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1056 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1057 -#define _INSERT_NULL_r10 1058 -#define _INSTRUMENTED_FOR_ITER_r23 1059 -#define _INSTRUMENTED_INSTRUCTION_r00 1060 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1061 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1062 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1063 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1064 -#define _INSTRUMENTED_LINE_r00 1065 -#define _INSTRUMENTED_NOT_TAKEN_r00 1066 -#define _INSTRUMENTED_NOT_TAKEN_r11 1067 -#define _INSTRUMENTED_NOT_TAKEN_r22 1068 -#define _INSTRUMENTED_NOT_TAKEN_r33 1069 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1070 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1071 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1072 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1073 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1074 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1075 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1076 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1077 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1078 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1079 -#define _IS_NONE_r11 1080 -#define _IS_OP_r03 1081 -#define _IS_OP_r13 1082 -#define _IS_OP_r23 1083 -#define _ITER_CHECK_LIST_r02 1084 -#define _ITER_CHECK_LIST_r12 1085 -#define _ITER_CHECK_LIST_r22 1086 -#define _ITER_CHECK_LIST_r33 1087 -#define _ITER_CHECK_RANGE_r02 1088 -#define _ITER_CHECK_RANGE_r12 1089 -#define _ITER_CHECK_RANGE_r22 1090 -#define _ITER_CHECK_RANGE_r33 1091 -#define _ITER_CHECK_TUPLE_r02 1092 -#define _ITER_CHECK_TUPLE_r12 1093 -#define _ITER_CHECK_TUPLE_r22 1094 -#define _ITER_CHECK_TUPLE_r33 1095 -#define _ITER_JUMP_LIST_r02 1096 -#define _ITER_JUMP_LIST_r12 1097 -#define _ITER_JUMP_LIST_r22 1098 -#define _ITER_JUMP_LIST_r33 1099 -#define _ITER_JUMP_RANGE_r02 1100 -#define _ITER_JUMP_RANGE_r12 1101 -#define _ITER_JUMP_RANGE_r22 1102 -#define _ITER_JUMP_RANGE_r33 1103 -#define _ITER_JUMP_TUPLE_r02 1104 -#define _ITER_JUMP_TUPLE_r12 1105 -#define _ITER_JUMP_TUPLE_r22 1106 -#define _ITER_JUMP_TUPLE_r33 1107 -#define _ITER_NEXT_LIST_r23 1108 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1109 -#define _ITER_NEXT_RANGE_r03 1110 -#define _ITER_NEXT_RANGE_r13 1111 -#define _ITER_NEXT_RANGE_r23 1112 -#define _ITER_NEXT_TUPLE_r03 1113 -#define _ITER_NEXT_TUPLE_r13 1114 -#define _ITER_NEXT_TUPLE_r23 1115 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1116 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1117 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1118 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1119 -#define _JUMP_TO_TOP_r00 1120 -#define _LIST_APPEND_r10 1121 -#define _LIST_EXTEND_r10 1122 -#define _LOAD_ATTR_r10 1123 -#define _LOAD_ATTR_CLASS_r11 1124 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1125 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1126 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1127 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1128 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1129 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1130 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1131 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1132 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1133 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1134 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1135 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1136 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1137 -#define _LOAD_ATTR_MODULE_r12 1138 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1139 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1140 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1141 -#define _LOAD_ATTR_SLOT_r02 1142 -#define _LOAD_ATTR_SLOT_r12 1143 -#define _LOAD_ATTR_SLOT_r23 1144 -#define _LOAD_ATTR_WITH_HINT_r12 1145 -#define _LOAD_BUILD_CLASS_r01 1146 -#define _LOAD_BYTECODE_r00 1147 -#define _LOAD_COMMON_CONSTANT_r01 1148 -#define _LOAD_COMMON_CONSTANT_r12 1149 -#define _LOAD_COMMON_CONSTANT_r23 1150 -#define _LOAD_CONST_r01 1151 -#define _LOAD_CONST_r12 1152 -#define _LOAD_CONST_r23 1153 -#define _LOAD_CONST_INLINE_r01 1154 -#define _LOAD_CONST_INLINE_r12 1155 -#define _LOAD_CONST_INLINE_r23 1156 -#define _LOAD_CONST_INLINE_BORROW_r01 1157 -#define _LOAD_CONST_INLINE_BORROW_r12 1158 -#define _LOAD_CONST_INLINE_BORROW_r23 1159 -#define _LOAD_CONST_UNDER_INLINE_r02 1160 -#define _LOAD_CONST_UNDER_INLINE_r12 1161 -#define _LOAD_CONST_UNDER_INLINE_r23 1162 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1163 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1164 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1165 -#define _LOAD_DEREF_r01 1166 -#define _LOAD_FAST_r01 1167 -#define _LOAD_FAST_r12 1168 -#define _LOAD_FAST_r23 1169 -#define _LOAD_FAST_0_r01 1170 -#define _LOAD_FAST_0_r12 1171 -#define _LOAD_FAST_0_r23 1172 -#define _LOAD_FAST_1_r01 1173 -#define _LOAD_FAST_1_r12 1174 -#define _LOAD_FAST_1_r23 1175 -#define _LOAD_FAST_2_r01 1176 -#define _LOAD_FAST_2_r12 1177 -#define _LOAD_FAST_2_r23 1178 -#define _LOAD_FAST_3_r01 1179 -#define _LOAD_FAST_3_r12 1180 -#define _LOAD_FAST_3_r23 1181 -#define _LOAD_FAST_4_r01 1182 -#define _LOAD_FAST_4_r12 1183 -#define _LOAD_FAST_4_r23 1184 -#define _LOAD_FAST_5_r01 1185 -#define _LOAD_FAST_5_r12 1186 -#define _LOAD_FAST_5_r23 1187 -#define _LOAD_FAST_6_r01 1188 -#define _LOAD_FAST_6_r12 1189 -#define _LOAD_FAST_6_r23 1190 -#define _LOAD_FAST_7_r01 1191 -#define _LOAD_FAST_7_r12 1192 -#define _LOAD_FAST_7_r23 1193 -#define _LOAD_FAST_AND_CLEAR_r01 1194 -#define _LOAD_FAST_AND_CLEAR_r12 1195 -#define _LOAD_FAST_AND_CLEAR_r23 1196 -#define _LOAD_FAST_BORROW_r01 1197 -#define _LOAD_FAST_BORROW_r12 1198 -#define _LOAD_FAST_BORROW_r23 1199 -#define _LOAD_FAST_BORROW_0_r01 1200 -#define _LOAD_FAST_BORROW_0_r12 1201 -#define _LOAD_FAST_BORROW_0_r23 1202 -#define _LOAD_FAST_BORROW_1_r01 1203 -#define _LOAD_FAST_BORROW_1_r12 1204 -#define _LOAD_FAST_BORROW_1_r23 1205 -#define _LOAD_FAST_BORROW_2_r01 1206 -#define _LOAD_FAST_BORROW_2_r12 1207 -#define _LOAD_FAST_BORROW_2_r23 1208 -#define _LOAD_FAST_BORROW_3_r01 1209 -#define _LOAD_FAST_BORROW_3_r12 1210 -#define _LOAD_FAST_BORROW_3_r23 1211 -#define _LOAD_FAST_BORROW_4_r01 1212 -#define _LOAD_FAST_BORROW_4_r12 1213 -#define _LOAD_FAST_BORROW_4_r23 1214 -#define _LOAD_FAST_BORROW_5_r01 1215 -#define _LOAD_FAST_BORROW_5_r12 1216 -#define _LOAD_FAST_BORROW_5_r23 1217 -#define _LOAD_FAST_BORROW_6_r01 1218 -#define _LOAD_FAST_BORROW_6_r12 1219 -#define _LOAD_FAST_BORROW_6_r23 1220 -#define _LOAD_FAST_BORROW_7_r01 1221 -#define _LOAD_FAST_BORROW_7_r12 1222 -#define _LOAD_FAST_BORROW_7_r23 1223 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1224 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1225 -#define _LOAD_FAST_CHECK_r01 1226 -#define _LOAD_FAST_CHECK_r12 1227 -#define _LOAD_FAST_CHECK_r23 1228 -#define _LOAD_FAST_LOAD_FAST_r02 1229 -#define _LOAD_FAST_LOAD_FAST_r13 1230 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1231 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1232 -#define _LOAD_GLOBAL_r00 1233 -#define _LOAD_GLOBAL_BUILTINS_r01 1234 -#define _LOAD_GLOBAL_MODULE_r01 1235 -#define _LOAD_LOCALS_r01 1236 -#define _LOAD_LOCALS_r12 1237 -#define _LOAD_LOCALS_r23 1238 -#define _LOAD_NAME_r01 1239 -#define _LOAD_SMALL_INT_r01 1240 -#define _LOAD_SMALL_INT_r12 1241 -#define _LOAD_SMALL_INT_r23 1242 -#define _LOAD_SMALL_INT_0_r01 1243 -#define _LOAD_SMALL_INT_0_r12 1244 -#define _LOAD_SMALL_INT_0_r23 1245 -#define _LOAD_SMALL_INT_1_r01 1246 -#define _LOAD_SMALL_INT_1_r12 1247 -#define _LOAD_SMALL_INT_1_r23 1248 -#define _LOAD_SMALL_INT_2_r01 1249 -#define _LOAD_SMALL_INT_2_r12 1250 -#define _LOAD_SMALL_INT_2_r23 1251 -#define _LOAD_SMALL_INT_3_r01 1252 -#define _LOAD_SMALL_INT_3_r12 1253 -#define _LOAD_SMALL_INT_3_r23 1254 -#define _LOAD_SPECIAL_r00 1255 -#define _LOAD_SUPER_ATTR_ATTR_r31 1256 -#define _LOAD_SUPER_ATTR_METHOD_r32 1257 -#define _LOCK_OBJECT_r01 1258 -#define _LOCK_OBJECT_r11 1259 -#define _LOCK_OBJECT_r22 1260 -#define _LOCK_OBJECT_r33 1261 -#define _MAKE_CALLARGS_A_TUPLE_r33 1262 -#define _MAKE_CELL_r00 1263 -#define _MAKE_FUNCTION_r11 1264 -#define _MAKE_HEAP_SAFE_r01 1265 -#define _MAKE_HEAP_SAFE_r11 1266 -#define _MAKE_HEAP_SAFE_r22 1267 -#define _MAKE_HEAP_SAFE_r33 1268 -#define _MAKE_WARM_r00 1269 -#define _MAKE_WARM_r11 1270 -#define _MAKE_WARM_r22 1271 -#define _MAKE_WARM_r33 1272 -#define _MAP_ADD_r20 1273 -#define _MATCH_CLASS_r31 1274 -#define _MATCH_KEYS_r23 1275 -#define _MATCH_MAPPING_r02 1276 -#define _MATCH_MAPPING_r12 1277 -#define _MATCH_MAPPING_r23 1278 -#define _MATCH_SEQUENCE_r02 1279 -#define _MATCH_SEQUENCE_r12 1280 -#define _MATCH_SEQUENCE_r23 1281 -#define _MAYBE_EXPAND_METHOD_r00 1282 -#define _MAYBE_EXPAND_METHOD_KW_r11 1283 -#define _MONITOR_CALL_r00 1284 -#define _MONITOR_CALL_KW_r11 1285 -#define _MONITOR_JUMP_BACKWARD_r00 1286 -#define _MONITOR_JUMP_BACKWARD_r11 1287 -#define _MONITOR_JUMP_BACKWARD_r22 1288 -#define _MONITOR_JUMP_BACKWARD_r33 1289 -#define _MONITOR_RESUME_r00 1290 -#define _NOP_r00 1291 -#define _NOP_r11 1292 -#define _NOP_r22 1293 -#define _NOP_r33 1294 -#define _POP_CALL_r20 1295 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1296 -#define _POP_CALL_ONE_r30 1297 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1298 -#define _POP_CALL_TWO_r30 1299 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1300 -#define _POP_EXCEPT_r10 1301 -#define _POP_ITER_r20 1302 -#define _POP_JUMP_IF_FALSE_r00 1303 -#define _POP_JUMP_IF_FALSE_r10 1304 -#define _POP_JUMP_IF_FALSE_r21 1305 -#define _POP_JUMP_IF_FALSE_r32 1306 -#define _POP_JUMP_IF_TRUE_r00 1307 -#define _POP_JUMP_IF_TRUE_r10 1308 -#define _POP_JUMP_IF_TRUE_r21 1309 -#define _POP_JUMP_IF_TRUE_r32 1310 -#define _POP_TOP_r10 1311 -#define _POP_TOP_FLOAT_r00 1312 -#define _POP_TOP_FLOAT_r10 1313 -#define _POP_TOP_FLOAT_r21 1314 -#define _POP_TOP_FLOAT_r32 1315 -#define _POP_TOP_INT_r00 1316 -#define _POP_TOP_INT_r10 1317 -#define _POP_TOP_INT_r21 1318 -#define _POP_TOP_INT_r32 1319 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1320 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1321 -#define _POP_TOP_NOP_r00 1322 -#define _POP_TOP_NOP_r10 1323 -#define _POP_TOP_NOP_r21 1324 -#define _POP_TOP_NOP_r32 1325 -#define _POP_TOP_UNICODE_r00 1326 -#define _POP_TOP_UNICODE_r10 1327 -#define _POP_TOP_UNICODE_r21 1328 -#define _POP_TOP_UNICODE_r32 1329 -#define _POP_TWO_r20 1330 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1331 -#define _PUSH_EXC_INFO_r02 1332 -#define _PUSH_EXC_INFO_r12 1333 -#define _PUSH_EXC_INFO_r23 1334 -#define _PUSH_FRAME_r10 1335 -#define _PUSH_NULL_r01 1336 -#define _PUSH_NULL_r12 1337 -#define _PUSH_NULL_r23 1338 -#define _PUSH_NULL_CONDITIONAL_r00 1339 -#define _PY_FRAME_EX_r31 1340 -#define _PY_FRAME_GENERAL_r01 1341 -#define _PY_FRAME_KW_r11 1342 -#define _QUICKEN_RESUME_r00 1343 -#define _QUICKEN_RESUME_r11 1344 -#define _QUICKEN_RESUME_r22 1345 -#define _QUICKEN_RESUME_r33 1346 -#define _REPLACE_WITH_TRUE_r02 1347 -#define _REPLACE_WITH_TRUE_r12 1348 -#define _REPLACE_WITH_TRUE_r23 1349 -#define _RESUME_CHECK_r00 1350 -#define _RESUME_CHECK_r11 1351 -#define _RESUME_CHECK_r22 1352 -#define _RESUME_CHECK_r33 1353 -#define _RETURN_GENERATOR_r01 1354 -#define _RETURN_VALUE_r11 1355 -#define _SAVE_RETURN_OFFSET_r00 1356 -#define _SAVE_RETURN_OFFSET_r11 1357 -#define _SAVE_RETURN_OFFSET_r22 1358 -#define _SAVE_RETURN_OFFSET_r33 1359 -#define _SEND_r22 1360 -#define _SEND_GEN_FRAME_r22 1361 -#define _SETUP_ANNOTATIONS_r00 1362 -#define _SET_ADD_r10 1363 -#define _SET_FUNCTION_ATTRIBUTE_r01 1364 -#define _SET_FUNCTION_ATTRIBUTE_r11 1365 -#define _SET_FUNCTION_ATTRIBUTE_r21 1366 -#define _SET_FUNCTION_ATTRIBUTE_r32 1367 -#define _SET_IP_r00 1368 -#define _SET_IP_r11 1369 -#define _SET_IP_r22 1370 -#define _SET_IP_r33 1371 -#define _SET_UPDATE_r10 1372 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1373 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1374 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1375 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1376 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1377 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1378 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1379 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1380 -#define _SPILL_OR_RELOAD_r01 1381 -#define _SPILL_OR_RELOAD_r02 1382 -#define _SPILL_OR_RELOAD_r03 1383 -#define _SPILL_OR_RELOAD_r10 1384 -#define _SPILL_OR_RELOAD_r12 1385 -#define _SPILL_OR_RELOAD_r13 1386 -#define _SPILL_OR_RELOAD_r20 1387 -#define _SPILL_OR_RELOAD_r21 1388 -#define _SPILL_OR_RELOAD_r23 1389 -#define _SPILL_OR_RELOAD_r30 1390 -#define _SPILL_OR_RELOAD_r31 1391 -#define _SPILL_OR_RELOAD_r32 1392 -#define _START_EXECUTOR_r00 1393 -#define _STORE_ATTR_r20 1394 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1395 -#define _STORE_ATTR_SLOT_r21 1396 -#define _STORE_ATTR_WITH_HINT_r21 1397 -#define _STORE_DEREF_r10 1398 -#define _STORE_FAST_LOAD_FAST_r11 1399 -#define _STORE_FAST_STORE_FAST_r20 1400 -#define _STORE_GLOBAL_r10 1401 -#define _STORE_NAME_r10 1402 -#define _STORE_SLICE_r30 1403 -#define _STORE_SUBSCR_r30 1404 -#define _STORE_SUBSCR_DICT_r31 1405 -#define _STORE_SUBSCR_LIST_INT_r32 1406 -#define _SWAP_r11 1407 -#define _SWAP_2_r02 1408 -#define _SWAP_2_r12 1409 -#define _SWAP_2_r22 1410 -#define _SWAP_2_r33 1411 -#define _SWAP_3_r03 1412 -#define _SWAP_3_r13 1413 -#define _SWAP_3_r23 1414 -#define _SWAP_3_r33 1415 -#define _SWAP_FAST_r01 1416 -#define _SWAP_FAST_r11 1417 -#define _SWAP_FAST_r22 1418 -#define _SWAP_FAST_r33 1419 -#define _SWAP_FAST_0_r01 1420 -#define _SWAP_FAST_0_r11 1421 -#define _SWAP_FAST_0_r22 1422 -#define _SWAP_FAST_0_r33 1423 -#define _SWAP_FAST_1_r01 1424 -#define _SWAP_FAST_1_r11 1425 -#define _SWAP_FAST_1_r22 1426 -#define _SWAP_FAST_1_r33 1427 -#define _SWAP_FAST_2_r01 1428 -#define _SWAP_FAST_2_r11 1429 -#define _SWAP_FAST_2_r22 1430 -#define _SWAP_FAST_2_r33 1431 -#define _SWAP_FAST_3_r01 1432 -#define _SWAP_FAST_3_r11 1433 -#define _SWAP_FAST_3_r22 1434 -#define _SWAP_FAST_3_r33 1435 -#define _SWAP_FAST_4_r01 1436 -#define _SWAP_FAST_4_r11 1437 -#define _SWAP_FAST_4_r22 1438 -#define _SWAP_FAST_4_r33 1439 -#define _SWAP_FAST_5_r01 1440 -#define _SWAP_FAST_5_r11 1441 -#define _SWAP_FAST_5_r22 1442 -#define _SWAP_FAST_5_r33 1443 -#define _SWAP_FAST_6_r01 1444 -#define _SWAP_FAST_6_r11 1445 -#define _SWAP_FAST_6_r22 1446 -#define _SWAP_FAST_6_r33 1447 -#define _SWAP_FAST_7_r01 1448 -#define _SWAP_FAST_7_r11 1449 -#define _SWAP_FAST_7_r22 1450 -#define _SWAP_FAST_7_r33 1451 -#define _TIER2_RESUME_CHECK_r00 1452 -#define _TIER2_RESUME_CHECK_r11 1453 -#define _TIER2_RESUME_CHECK_r22 1454 -#define _TIER2_RESUME_CHECK_r33 1455 -#define _TO_BOOL_r11 1456 -#define _TO_BOOL_BOOL_r01 1457 -#define _TO_BOOL_BOOL_r11 1458 -#define _TO_BOOL_BOOL_r22 1459 -#define _TO_BOOL_BOOL_r33 1460 -#define _TO_BOOL_INT_r02 1461 -#define _TO_BOOL_INT_r12 1462 -#define _TO_BOOL_INT_r23 1463 -#define _TO_BOOL_LIST_r02 1464 -#define _TO_BOOL_LIST_r12 1465 -#define _TO_BOOL_LIST_r23 1466 -#define _TO_BOOL_NONE_r01 1467 -#define _TO_BOOL_NONE_r11 1468 -#define _TO_BOOL_NONE_r22 1469 -#define _TO_BOOL_NONE_r33 1470 -#define _TO_BOOL_STR_r02 1471 -#define _TO_BOOL_STR_r12 1472 -#define _TO_BOOL_STR_r23 1473 -#define _TRACE_RECORD_r00 1474 -#define _UNARY_INVERT_r12 1475 -#define _UNARY_NEGATIVE_r12 1476 -#define _UNARY_NOT_r01 1477 -#define _UNARY_NOT_r11 1478 -#define _UNARY_NOT_r22 1479 -#define _UNARY_NOT_r33 1480 -#define _UNPACK_EX_r10 1481 -#define _UNPACK_SEQUENCE_r10 1482 -#define _UNPACK_SEQUENCE_LIST_r10 1483 -#define _UNPACK_SEQUENCE_TUPLE_r10 1484 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1485 -#define _WITH_EXCEPT_START_r33 1486 -#define _YIELD_VALUE_r11 1487 -#define MAX_UOP_REGS_ID 1487 +#define _YIELD_VALUE 598 +#define MAX_UOP_ID 598 +#define _BINARY_OP_r23 599 +#define _BINARY_OP_ADD_FLOAT_r03 600 +#define _BINARY_OP_ADD_FLOAT_r13 601 +#define _BINARY_OP_ADD_FLOAT_r23 602 +#define _BINARY_OP_ADD_INT_r03 603 +#define _BINARY_OP_ADD_INT_r13 604 +#define _BINARY_OP_ADD_INT_r23 605 +#define _BINARY_OP_ADD_UNICODE_r03 606 +#define _BINARY_OP_ADD_UNICODE_r13 607 +#define _BINARY_OP_ADD_UNICODE_r23 608 +#define _BINARY_OP_EXTEND_r23 609 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 610 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 611 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 612 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 613 +#define _BINARY_OP_MULTIPLY_INT_r03 614 +#define _BINARY_OP_MULTIPLY_INT_r13 615 +#define _BINARY_OP_MULTIPLY_INT_r23 616 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 617 +#define _BINARY_OP_SUBSCR_DICT_r23 618 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 619 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 620 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 621 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 622 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 623 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 624 +#define _BINARY_OP_SUBSCR_STR_INT_r23 625 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 626 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 627 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 628 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 629 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 630 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 631 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 632 +#define _BINARY_OP_SUBTRACT_INT_r03 633 +#define _BINARY_OP_SUBTRACT_INT_r13 634 +#define _BINARY_OP_SUBTRACT_INT_r23 635 +#define _BINARY_SLICE_r31 636 +#define _BUILD_INTERPOLATION_r01 637 +#define _BUILD_LIST_r01 638 +#define _BUILD_MAP_r01 639 +#define _BUILD_SET_r01 640 +#define _BUILD_SLICE_r01 641 +#define _BUILD_STRING_r01 642 +#define _BUILD_TEMPLATE_r21 643 +#define _BUILD_TUPLE_r01 644 +#define _CALL_BUILTIN_CLASS_r01 645 +#define _CALL_BUILTIN_FAST_r01 646 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 647 +#define _CALL_BUILTIN_O_r03 648 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 649 +#define _CALL_INTRINSIC_1_r11 650 +#define _CALL_INTRINSIC_2_r21 651 +#define _CALL_ISINSTANCE_r31 652 +#define _CALL_KW_NON_PY_r11 653 +#define _CALL_LEN_r33 654 +#define _CALL_LIST_APPEND_r03 655 +#define _CALL_LIST_APPEND_r13 656 +#define _CALL_LIST_APPEND_r23 657 +#define _CALL_LIST_APPEND_r33 658 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 659 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 660 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 661 +#define _CALL_METHOD_DESCRIPTOR_O_r03 662 +#define _CALL_NON_PY_GENERAL_r01 663 +#define _CALL_STR_1_r32 664 +#define _CALL_TUPLE_1_r32 665 +#define _CALL_TYPE_1_r02 666 +#define _CALL_TYPE_1_r12 667 +#define _CALL_TYPE_1_r22 668 +#define _CALL_TYPE_1_r32 669 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 670 +#define _CHECK_ATTR_CLASS_r01 671 +#define _CHECK_ATTR_CLASS_r11 672 +#define _CHECK_ATTR_CLASS_r22 673 +#define _CHECK_ATTR_CLASS_r33 674 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 675 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 676 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 677 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 678 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 679 +#define _CHECK_EG_MATCH_r22 680 +#define _CHECK_EXC_MATCH_r22 681 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 682 +#define _CHECK_FUNCTION_VERSION_r00 683 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 684 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 685 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 686 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 687 +#define _CHECK_FUNCTION_VERSION_KW_r11 688 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 689 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 690 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 691 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 692 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 693 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 694 +#define _CHECK_IS_PY_CALLABLE_EX_r03 695 +#define _CHECK_IS_PY_CALLABLE_EX_r13 696 +#define _CHECK_IS_PY_CALLABLE_EX_r23 697 +#define _CHECK_IS_PY_CALLABLE_EX_r33 698 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 699 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 700 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 701 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 702 +#define _CHECK_METHOD_VERSION_r00 703 +#define _CHECK_METHOD_VERSION_KW_r11 704 +#define _CHECK_PEP_523_r00 705 +#define _CHECK_PEP_523_r11 706 +#define _CHECK_PEP_523_r22 707 +#define _CHECK_PEP_523_r33 708 +#define _CHECK_PERIODIC_r00 709 +#define _CHECK_PERIODIC_AT_END_r00 710 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 711 +#define _CHECK_RECURSION_REMAINING_r00 712 +#define _CHECK_RECURSION_REMAINING_r11 713 +#define _CHECK_RECURSION_REMAINING_r22 714 +#define _CHECK_RECURSION_REMAINING_r33 715 +#define _CHECK_STACK_SPACE_r00 716 +#define _CHECK_STACK_SPACE_OPERAND_r00 717 +#define _CHECK_STACK_SPACE_OPERAND_r11 718 +#define _CHECK_STACK_SPACE_OPERAND_r22 719 +#define _CHECK_STACK_SPACE_OPERAND_r33 720 +#define _CHECK_VALIDITY_r00 721 +#define _CHECK_VALIDITY_r11 722 +#define _CHECK_VALIDITY_r22 723 +#define _CHECK_VALIDITY_r33 724 +#define _COLD_DYNAMIC_EXIT_r00 725 +#define _COLD_EXIT_r00 726 +#define _COMPARE_OP_r21 727 +#define _COMPARE_OP_FLOAT_r03 728 +#define _COMPARE_OP_FLOAT_r13 729 +#define _COMPARE_OP_FLOAT_r23 730 +#define _COMPARE_OP_INT_r23 731 +#define _COMPARE_OP_STR_r23 732 +#define _CONTAINS_OP_r23 733 +#define _CONTAINS_OP_DICT_r23 734 +#define _CONTAINS_OP_SET_r23 735 +#define _CONVERT_VALUE_r11 736 +#define _COPY_r01 737 +#define _COPY_1_r02 738 +#define _COPY_1_r12 739 +#define _COPY_1_r23 740 +#define _COPY_2_r03 741 +#define _COPY_2_r13 742 +#define _COPY_2_r23 743 +#define _COPY_3_r03 744 +#define _COPY_3_r13 745 +#define _COPY_3_r23 746 +#define _COPY_3_r33 747 +#define _COPY_FREE_VARS_r00 748 +#define _COPY_FREE_VARS_r11 749 +#define _COPY_FREE_VARS_r22 750 +#define _COPY_FREE_VARS_r33 751 +#define _CREATE_INIT_FRAME_r01 752 +#define _DELETE_ATTR_r10 753 +#define _DELETE_DEREF_r00 754 +#define _DELETE_FAST_r00 755 +#define _DELETE_GLOBAL_r00 756 +#define _DELETE_NAME_r00 757 +#define _DELETE_SUBSCR_r20 758 +#define _DEOPT_r00 759 +#define _DEOPT_r10 760 +#define _DEOPT_r20 761 +#define _DEOPT_r30 762 +#define _DICT_MERGE_r10 763 +#define _DICT_UPDATE_r10 764 +#define _DO_CALL_r01 765 +#define _DO_CALL_FUNCTION_EX_r31 766 +#define _DO_CALL_KW_r11 767 +#define _DYNAMIC_EXIT_r00 768 +#define _DYNAMIC_EXIT_r10 769 +#define _DYNAMIC_EXIT_r20 770 +#define _DYNAMIC_EXIT_r30 771 +#define _END_FOR_r10 772 +#define _END_SEND_r21 773 +#define _ERROR_POP_N_r00 774 +#define _EXIT_INIT_CHECK_r10 775 +#define _EXIT_TRACE_r00 776 +#define _EXIT_TRACE_r10 777 +#define _EXIT_TRACE_r20 778 +#define _EXIT_TRACE_r30 779 +#define _EXPAND_METHOD_r00 780 +#define _EXPAND_METHOD_KW_r11 781 +#define _FATAL_ERROR_r00 782 +#define _FATAL_ERROR_r11 783 +#define _FATAL_ERROR_r22 784 +#define _FATAL_ERROR_r33 785 +#define _FORMAT_SIMPLE_r11 786 +#define _FORMAT_WITH_SPEC_r21 787 +#define _FOR_ITER_r23 788 +#define _FOR_ITER_GEN_FRAME_r03 789 +#define _FOR_ITER_GEN_FRAME_r13 790 +#define _FOR_ITER_GEN_FRAME_r23 791 +#define _FOR_ITER_TIER_TWO_r23 792 +#define _GET_AITER_r11 793 +#define _GET_ANEXT_r12 794 +#define _GET_AWAITABLE_r11 795 +#define _GET_ITER_r12 796 +#define _GET_LEN_r12 797 +#define _GET_YIELD_FROM_ITER_r11 798 +#define _GUARD_BINARY_OP_EXTEND_r22 799 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 800 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 801 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 802 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 803 +#define _GUARD_BIT_IS_SET_POP_r00 804 +#define _GUARD_BIT_IS_SET_POP_r10 805 +#define _GUARD_BIT_IS_SET_POP_r21 806 +#define _GUARD_BIT_IS_SET_POP_r32 807 +#define _GUARD_BIT_IS_SET_POP_4_r00 808 +#define _GUARD_BIT_IS_SET_POP_4_r10 809 +#define _GUARD_BIT_IS_SET_POP_4_r21 810 +#define _GUARD_BIT_IS_SET_POP_4_r32 811 +#define _GUARD_BIT_IS_SET_POP_5_r00 812 +#define _GUARD_BIT_IS_SET_POP_5_r10 813 +#define _GUARD_BIT_IS_SET_POP_5_r21 814 +#define _GUARD_BIT_IS_SET_POP_5_r32 815 +#define _GUARD_BIT_IS_SET_POP_6_r00 816 +#define _GUARD_BIT_IS_SET_POP_6_r10 817 +#define _GUARD_BIT_IS_SET_POP_6_r21 818 +#define _GUARD_BIT_IS_SET_POP_6_r32 819 +#define _GUARD_BIT_IS_SET_POP_7_r00 820 +#define _GUARD_BIT_IS_SET_POP_7_r10 821 +#define _GUARD_BIT_IS_SET_POP_7_r21 822 +#define _GUARD_BIT_IS_SET_POP_7_r32 823 +#define _GUARD_BIT_IS_UNSET_POP_r00 824 +#define _GUARD_BIT_IS_UNSET_POP_r10 825 +#define _GUARD_BIT_IS_UNSET_POP_r21 826 +#define _GUARD_BIT_IS_UNSET_POP_r32 827 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 828 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 829 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 830 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 831 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 832 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 833 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 834 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 835 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 836 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 837 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 838 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 839 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 840 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 841 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 842 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 843 +#define _GUARD_CALLABLE_ISINSTANCE_r03 844 +#define _GUARD_CALLABLE_ISINSTANCE_r13 845 +#define _GUARD_CALLABLE_ISINSTANCE_r23 846 +#define _GUARD_CALLABLE_ISINSTANCE_r33 847 +#define _GUARD_CALLABLE_LEN_r03 848 +#define _GUARD_CALLABLE_LEN_r13 849 +#define _GUARD_CALLABLE_LEN_r23 850 +#define _GUARD_CALLABLE_LEN_r33 851 +#define _GUARD_CALLABLE_LIST_APPEND_r03 852 +#define _GUARD_CALLABLE_LIST_APPEND_r13 853 +#define _GUARD_CALLABLE_LIST_APPEND_r23 854 +#define _GUARD_CALLABLE_LIST_APPEND_r33 855 +#define _GUARD_CALLABLE_STR_1_r03 856 +#define _GUARD_CALLABLE_STR_1_r13 857 +#define _GUARD_CALLABLE_STR_1_r23 858 +#define _GUARD_CALLABLE_STR_1_r33 859 +#define _GUARD_CALLABLE_TUPLE_1_r03 860 +#define _GUARD_CALLABLE_TUPLE_1_r13 861 +#define _GUARD_CALLABLE_TUPLE_1_r23 862 +#define _GUARD_CALLABLE_TUPLE_1_r33 863 +#define _GUARD_CALLABLE_TYPE_1_r03 864 +#define _GUARD_CALLABLE_TYPE_1_r13 865 +#define _GUARD_CALLABLE_TYPE_1_r23 866 +#define _GUARD_CALLABLE_TYPE_1_r33 867 +#define _GUARD_CODE_VERSION_r00 868 +#define _GUARD_CODE_VERSION_r11 869 +#define _GUARD_CODE_VERSION_r22 870 +#define _GUARD_CODE_VERSION_r33 871 +#define _GUARD_DORV_NO_DICT_r01 872 +#define _GUARD_DORV_NO_DICT_r11 873 +#define _GUARD_DORV_NO_DICT_r22 874 +#define _GUARD_DORV_NO_DICT_r33 875 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 876 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 877 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 878 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 879 +#define _GUARD_GLOBALS_VERSION_r00 880 +#define _GUARD_GLOBALS_VERSION_r11 881 +#define _GUARD_GLOBALS_VERSION_r22 882 +#define _GUARD_GLOBALS_VERSION_r33 883 +#define _GUARD_IP_RETURN_GENERATOR_r00 884 +#define _GUARD_IP_RETURN_GENERATOR_r11 885 +#define _GUARD_IP_RETURN_GENERATOR_r22 886 +#define _GUARD_IP_RETURN_GENERATOR_r33 887 +#define _GUARD_IP_RETURN_VALUE_r00 888 +#define _GUARD_IP_RETURN_VALUE_r11 889 +#define _GUARD_IP_RETURN_VALUE_r22 890 +#define _GUARD_IP_RETURN_VALUE_r33 891 +#define _GUARD_IP_YIELD_VALUE_r00 892 +#define _GUARD_IP_YIELD_VALUE_r11 893 +#define _GUARD_IP_YIELD_VALUE_r22 894 +#define _GUARD_IP_YIELD_VALUE_r33 895 +#define _GUARD_IP__PUSH_FRAME_r00 896 +#define _GUARD_IP__PUSH_FRAME_r11 897 +#define _GUARD_IP__PUSH_FRAME_r22 898 +#define _GUARD_IP__PUSH_FRAME_r33 899 +#define _GUARD_IS_FALSE_POP_r00 900 +#define _GUARD_IS_FALSE_POP_r10 901 +#define _GUARD_IS_FALSE_POP_r21 902 +#define _GUARD_IS_FALSE_POP_r32 903 +#define _GUARD_IS_NONE_POP_r00 904 +#define _GUARD_IS_NONE_POP_r10 905 +#define _GUARD_IS_NONE_POP_r21 906 +#define _GUARD_IS_NONE_POP_r32 907 +#define _GUARD_IS_NOT_NONE_POP_r10 908 +#define _GUARD_IS_TRUE_POP_r00 909 +#define _GUARD_IS_TRUE_POP_r10 910 +#define _GUARD_IS_TRUE_POP_r21 911 +#define _GUARD_IS_TRUE_POP_r32 912 +#define _GUARD_KEYS_VERSION_r01 913 +#define _GUARD_KEYS_VERSION_r11 914 +#define _GUARD_KEYS_VERSION_r22 915 +#define _GUARD_KEYS_VERSION_r33 916 +#define _GUARD_NOS_ANY_DICT_r02 917 +#define _GUARD_NOS_ANY_DICT_r12 918 +#define _GUARD_NOS_ANY_DICT_r22 919 +#define _GUARD_NOS_ANY_DICT_r33 920 +#define _GUARD_NOS_COMPACT_ASCII_r02 921 +#define _GUARD_NOS_COMPACT_ASCII_r12 922 +#define _GUARD_NOS_COMPACT_ASCII_r22 923 +#define _GUARD_NOS_COMPACT_ASCII_r33 924 +#define _GUARD_NOS_DICT_r02 925 +#define _GUARD_NOS_DICT_r12 926 +#define _GUARD_NOS_DICT_r22 927 +#define _GUARD_NOS_DICT_r33 928 +#define _GUARD_NOS_FLOAT_r02 929 +#define _GUARD_NOS_FLOAT_r12 930 +#define _GUARD_NOS_FLOAT_r22 931 +#define _GUARD_NOS_FLOAT_r33 932 +#define _GUARD_NOS_INT_r02 933 +#define _GUARD_NOS_INT_r12 934 +#define _GUARD_NOS_INT_r22 935 +#define _GUARD_NOS_INT_r33 936 +#define _GUARD_NOS_LIST_r02 937 +#define _GUARD_NOS_LIST_r12 938 +#define _GUARD_NOS_LIST_r22 939 +#define _GUARD_NOS_LIST_r33 940 +#define _GUARD_NOS_NOT_NULL_r02 941 +#define _GUARD_NOS_NOT_NULL_r12 942 +#define _GUARD_NOS_NOT_NULL_r22 943 +#define _GUARD_NOS_NOT_NULL_r33 944 +#define _GUARD_NOS_NULL_r02 945 +#define _GUARD_NOS_NULL_r12 946 +#define _GUARD_NOS_NULL_r22 947 +#define _GUARD_NOS_NULL_r33 948 +#define _GUARD_NOS_OVERFLOWED_r02 949 +#define _GUARD_NOS_OVERFLOWED_r12 950 +#define _GUARD_NOS_OVERFLOWED_r22 951 +#define _GUARD_NOS_OVERFLOWED_r33 952 +#define _GUARD_NOS_TUPLE_r02 953 +#define _GUARD_NOS_TUPLE_r12 954 +#define _GUARD_NOS_TUPLE_r22 955 +#define _GUARD_NOS_TUPLE_r33 956 +#define _GUARD_NOS_UNICODE_r02 957 +#define _GUARD_NOS_UNICODE_r12 958 +#define _GUARD_NOS_UNICODE_r22 959 +#define _GUARD_NOS_UNICODE_r33 960 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 961 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 962 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 963 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 964 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 965 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 966 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 967 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 968 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 969 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 970 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 971 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 972 +#define _GUARD_THIRD_NULL_r03 973 +#define _GUARD_THIRD_NULL_r13 974 +#define _GUARD_THIRD_NULL_r23 975 +#define _GUARD_THIRD_NULL_r33 976 +#define _GUARD_TOS_ANY_DICT_r01 977 +#define _GUARD_TOS_ANY_DICT_r11 978 +#define _GUARD_TOS_ANY_DICT_r22 979 +#define _GUARD_TOS_ANY_DICT_r33 980 +#define _GUARD_TOS_ANY_SET_r01 981 +#define _GUARD_TOS_ANY_SET_r11 982 +#define _GUARD_TOS_ANY_SET_r22 983 +#define _GUARD_TOS_ANY_SET_r33 984 +#define _GUARD_TOS_DICT_r01 985 +#define _GUARD_TOS_DICT_r11 986 +#define _GUARD_TOS_DICT_r22 987 +#define _GUARD_TOS_DICT_r33 988 +#define _GUARD_TOS_FLOAT_r01 989 +#define _GUARD_TOS_FLOAT_r11 990 +#define _GUARD_TOS_FLOAT_r22 991 +#define _GUARD_TOS_FLOAT_r33 992 +#define _GUARD_TOS_FROZENDICT_r01 993 +#define _GUARD_TOS_FROZENDICT_r11 994 +#define _GUARD_TOS_FROZENDICT_r22 995 +#define _GUARD_TOS_FROZENDICT_r33 996 +#define _GUARD_TOS_FROZENSET_r01 997 +#define _GUARD_TOS_FROZENSET_r11 998 +#define _GUARD_TOS_FROZENSET_r22 999 +#define _GUARD_TOS_FROZENSET_r33 1000 +#define _GUARD_TOS_INT_r01 1001 +#define _GUARD_TOS_INT_r11 1002 +#define _GUARD_TOS_INT_r22 1003 +#define _GUARD_TOS_INT_r33 1004 +#define _GUARD_TOS_LIST_r01 1005 +#define _GUARD_TOS_LIST_r11 1006 +#define _GUARD_TOS_LIST_r22 1007 +#define _GUARD_TOS_LIST_r33 1008 +#define _GUARD_TOS_OVERFLOWED_r01 1009 +#define _GUARD_TOS_OVERFLOWED_r11 1010 +#define _GUARD_TOS_OVERFLOWED_r22 1011 +#define _GUARD_TOS_OVERFLOWED_r33 1012 +#define _GUARD_TOS_SET_r01 1013 +#define _GUARD_TOS_SET_r11 1014 +#define _GUARD_TOS_SET_r22 1015 +#define _GUARD_TOS_SET_r33 1016 +#define _GUARD_TOS_SLICE_r01 1017 +#define _GUARD_TOS_SLICE_r11 1018 +#define _GUARD_TOS_SLICE_r22 1019 +#define _GUARD_TOS_SLICE_r33 1020 +#define _GUARD_TOS_TUPLE_r01 1021 +#define _GUARD_TOS_TUPLE_r11 1022 +#define _GUARD_TOS_TUPLE_r22 1023 +#define _GUARD_TOS_TUPLE_r33 1024 +#define _GUARD_TOS_UNICODE_r01 1025 +#define _GUARD_TOS_UNICODE_r11 1026 +#define _GUARD_TOS_UNICODE_r22 1027 +#define _GUARD_TOS_UNICODE_r33 1028 +#define _GUARD_TYPE_VERSION_r01 1029 +#define _GUARD_TYPE_VERSION_r11 1030 +#define _GUARD_TYPE_VERSION_r22 1031 +#define _GUARD_TYPE_VERSION_r33 1032 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1033 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1034 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1035 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1036 +#define _HANDLE_PENDING_AND_DEOPT_r00 1037 +#define _HANDLE_PENDING_AND_DEOPT_r10 1038 +#define _HANDLE_PENDING_AND_DEOPT_r20 1039 +#define _HANDLE_PENDING_AND_DEOPT_r30 1040 +#define _IMPORT_FROM_r12 1041 +#define _IMPORT_NAME_r21 1042 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1043 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1044 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1045 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1046 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1047 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1048 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1049 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1050 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1051 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1052 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1053 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1054 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1055 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1056 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1057 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1058 +#define _INSERT_NULL_r10 1059 +#define _INSTRUMENTED_FOR_ITER_r23 1060 +#define _INSTRUMENTED_INSTRUCTION_r00 1061 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1062 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1063 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1064 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1065 +#define _INSTRUMENTED_LINE_r00 1066 +#define _INSTRUMENTED_NOT_TAKEN_r00 1067 +#define _INSTRUMENTED_NOT_TAKEN_r11 1068 +#define _INSTRUMENTED_NOT_TAKEN_r22 1069 +#define _INSTRUMENTED_NOT_TAKEN_r33 1070 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1071 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1072 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1073 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1074 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1075 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1076 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1077 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1078 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1079 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1080 +#define _IS_NONE_r11 1081 +#define _IS_OP_r03 1082 +#define _IS_OP_r13 1083 +#define _IS_OP_r23 1084 +#define _ITER_CHECK_LIST_r02 1085 +#define _ITER_CHECK_LIST_r12 1086 +#define _ITER_CHECK_LIST_r22 1087 +#define _ITER_CHECK_LIST_r33 1088 +#define _ITER_CHECK_RANGE_r02 1089 +#define _ITER_CHECK_RANGE_r12 1090 +#define _ITER_CHECK_RANGE_r22 1091 +#define _ITER_CHECK_RANGE_r33 1092 +#define _ITER_CHECK_TUPLE_r02 1093 +#define _ITER_CHECK_TUPLE_r12 1094 +#define _ITER_CHECK_TUPLE_r22 1095 +#define _ITER_CHECK_TUPLE_r33 1096 +#define _ITER_JUMP_LIST_r02 1097 +#define _ITER_JUMP_LIST_r12 1098 +#define _ITER_JUMP_LIST_r22 1099 +#define _ITER_JUMP_LIST_r33 1100 +#define _ITER_JUMP_RANGE_r02 1101 +#define _ITER_JUMP_RANGE_r12 1102 +#define _ITER_JUMP_RANGE_r22 1103 +#define _ITER_JUMP_RANGE_r33 1104 +#define _ITER_JUMP_TUPLE_r02 1105 +#define _ITER_JUMP_TUPLE_r12 1106 +#define _ITER_JUMP_TUPLE_r22 1107 +#define _ITER_JUMP_TUPLE_r33 1108 +#define _ITER_NEXT_LIST_r23 1109 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1110 +#define _ITER_NEXT_RANGE_r03 1111 +#define _ITER_NEXT_RANGE_r13 1112 +#define _ITER_NEXT_RANGE_r23 1113 +#define _ITER_NEXT_TUPLE_r03 1114 +#define _ITER_NEXT_TUPLE_r13 1115 +#define _ITER_NEXT_TUPLE_r23 1116 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1117 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1118 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1119 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1120 +#define _JUMP_TO_TOP_r00 1121 +#define _LIST_APPEND_r10 1122 +#define _LIST_EXTEND_r10 1123 +#define _LOAD_ATTR_r10 1124 +#define _LOAD_ATTR_CLASS_r11 1125 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1126 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1127 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1128 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1129 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1130 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1131 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1132 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1133 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1134 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1135 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1136 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1137 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1138 +#define _LOAD_ATTR_MODULE_r12 1139 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1140 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1141 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1142 +#define _LOAD_ATTR_SLOT_r02 1143 +#define _LOAD_ATTR_SLOT_r12 1144 +#define _LOAD_ATTR_SLOT_r23 1145 +#define _LOAD_ATTR_WITH_HINT_r12 1146 +#define _LOAD_BUILD_CLASS_r01 1147 +#define _LOAD_BYTECODE_r00 1148 +#define _LOAD_COMMON_CONSTANT_r01 1149 +#define _LOAD_COMMON_CONSTANT_r12 1150 +#define _LOAD_COMMON_CONSTANT_r23 1151 +#define _LOAD_CONST_r01 1152 +#define _LOAD_CONST_r12 1153 +#define _LOAD_CONST_r23 1154 +#define _LOAD_CONST_INLINE_r01 1155 +#define _LOAD_CONST_INLINE_r12 1156 +#define _LOAD_CONST_INLINE_r23 1157 +#define _LOAD_CONST_INLINE_BORROW_r01 1158 +#define _LOAD_CONST_INLINE_BORROW_r12 1159 +#define _LOAD_CONST_INLINE_BORROW_r23 1160 +#define _LOAD_CONST_UNDER_INLINE_r02 1161 +#define _LOAD_CONST_UNDER_INLINE_r12 1162 +#define _LOAD_CONST_UNDER_INLINE_r23 1163 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1164 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1165 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1166 +#define _LOAD_DEREF_r01 1167 +#define _LOAD_FAST_r01 1168 +#define _LOAD_FAST_r12 1169 +#define _LOAD_FAST_r23 1170 +#define _LOAD_FAST_0_r01 1171 +#define _LOAD_FAST_0_r12 1172 +#define _LOAD_FAST_0_r23 1173 +#define _LOAD_FAST_1_r01 1174 +#define _LOAD_FAST_1_r12 1175 +#define _LOAD_FAST_1_r23 1176 +#define _LOAD_FAST_2_r01 1177 +#define _LOAD_FAST_2_r12 1178 +#define _LOAD_FAST_2_r23 1179 +#define _LOAD_FAST_3_r01 1180 +#define _LOAD_FAST_3_r12 1181 +#define _LOAD_FAST_3_r23 1182 +#define _LOAD_FAST_4_r01 1183 +#define _LOAD_FAST_4_r12 1184 +#define _LOAD_FAST_4_r23 1185 +#define _LOAD_FAST_5_r01 1186 +#define _LOAD_FAST_5_r12 1187 +#define _LOAD_FAST_5_r23 1188 +#define _LOAD_FAST_6_r01 1189 +#define _LOAD_FAST_6_r12 1190 +#define _LOAD_FAST_6_r23 1191 +#define _LOAD_FAST_7_r01 1192 +#define _LOAD_FAST_7_r12 1193 +#define _LOAD_FAST_7_r23 1194 +#define _LOAD_FAST_AND_CLEAR_r01 1195 +#define _LOAD_FAST_AND_CLEAR_r12 1196 +#define _LOAD_FAST_AND_CLEAR_r23 1197 +#define _LOAD_FAST_BORROW_r01 1198 +#define _LOAD_FAST_BORROW_r12 1199 +#define _LOAD_FAST_BORROW_r23 1200 +#define _LOAD_FAST_BORROW_0_r01 1201 +#define _LOAD_FAST_BORROW_0_r12 1202 +#define _LOAD_FAST_BORROW_0_r23 1203 +#define _LOAD_FAST_BORROW_1_r01 1204 +#define _LOAD_FAST_BORROW_1_r12 1205 +#define _LOAD_FAST_BORROW_1_r23 1206 +#define _LOAD_FAST_BORROW_2_r01 1207 +#define _LOAD_FAST_BORROW_2_r12 1208 +#define _LOAD_FAST_BORROW_2_r23 1209 +#define _LOAD_FAST_BORROW_3_r01 1210 +#define _LOAD_FAST_BORROW_3_r12 1211 +#define _LOAD_FAST_BORROW_3_r23 1212 +#define _LOAD_FAST_BORROW_4_r01 1213 +#define _LOAD_FAST_BORROW_4_r12 1214 +#define _LOAD_FAST_BORROW_4_r23 1215 +#define _LOAD_FAST_BORROW_5_r01 1216 +#define _LOAD_FAST_BORROW_5_r12 1217 +#define _LOAD_FAST_BORROW_5_r23 1218 +#define _LOAD_FAST_BORROW_6_r01 1219 +#define _LOAD_FAST_BORROW_6_r12 1220 +#define _LOAD_FAST_BORROW_6_r23 1221 +#define _LOAD_FAST_BORROW_7_r01 1222 +#define _LOAD_FAST_BORROW_7_r12 1223 +#define _LOAD_FAST_BORROW_7_r23 1224 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1225 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1226 +#define _LOAD_FAST_CHECK_r01 1227 +#define _LOAD_FAST_CHECK_r12 1228 +#define _LOAD_FAST_CHECK_r23 1229 +#define _LOAD_FAST_LOAD_FAST_r02 1230 +#define _LOAD_FAST_LOAD_FAST_r13 1231 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1232 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1233 +#define _LOAD_GLOBAL_r00 1234 +#define _LOAD_GLOBAL_BUILTINS_r01 1235 +#define _LOAD_GLOBAL_MODULE_r01 1236 +#define _LOAD_LOCALS_r01 1237 +#define _LOAD_LOCALS_r12 1238 +#define _LOAD_LOCALS_r23 1239 +#define _LOAD_NAME_r01 1240 +#define _LOAD_SMALL_INT_r01 1241 +#define _LOAD_SMALL_INT_r12 1242 +#define _LOAD_SMALL_INT_r23 1243 +#define _LOAD_SMALL_INT_0_r01 1244 +#define _LOAD_SMALL_INT_0_r12 1245 +#define _LOAD_SMALL_INT_0_r23 1246 +#define _LOAD_SMALL_INT_1_r01 1247 +#define _LOAD_SMALL_INT_1_r12 1248 +#define _LOAD_SMALL_INT_1_r23 1249 +#define _LOAD_SMALL_INT_2_r01 1250 +#define _LOAD_SMALL_INT_2_r12 1251 +#define _LOAD_SMALL_INT_2_r23 1252 +#define _LOAD_SMALL_INT_3_r01 1253 +#define _LOAD_SMALL_INT_3_r12 1254 +#define _LOAD_SMALL_INT_3_r23 1255 +#define _LOAD_SPECIAL_r00 1256 +#define _LOAD_SUPER_ATTR_ATTR_r31 1257 +#define _LOAD_SUPER_ATTR_METHOD_r32 1258 +#define _LOCK_OBJECT_r01 1259 +#define _LOCK_OBJECT_r11 1260 +#define _LOCK_OBJECT_r22 1261 +#define _LOCK_OBJECT_r33 1262 +#define _MAKE_CALLARGS_A_TUPLE_r33 1263 +#define _MAKE_CELL_r00 1264 +#define _MAKE_FUNCTION_r11 1265 +#define _MAKE_HEAP_SAFE_r01 1266 +#define _MAKE_HEAP_SAFE_r11 1267 +#define _MAKE_HEAP_SAFE_r22 1268 +#define _MAKE_HEAP_SAFE_r33 1269 +#define _MAKE_WARM_r00 1270 +#define _MAKE_WARM_r11 1271 +#define _MAKE_WARM_r22 1272 +#define _MAKE_WARM_r33 1273 +#define _MAP_ADD_r20 1274 +#define _MATCH_CLASS_r33 1275 +#define _MATCH_KEYS_r23 1276 +#define _MATCH_MAPPING_r02 1277 +#define _MATCH_MAPPING_r12 1278 +#define _MATCH_MAPPING_r23 1279 +#define _MATCH_SEQUENCE_r02 1280 +#define _MATCH_SEQUENCE_r12 1281 +#define _MATCH_SEQUENCE_r23 1282 +#define _MAYBE_EXPAND_METHOD_r00 1283 +#define _MAYBE_EXPAND_METHOD_KW_r11 1284 +#define _MONITOR_CALL_r00 1285 +#define _MONITOR_CALL_KW_r11 1286 +#define _MONITOR_JUMP_BACKWARD_r00 1287 +#define _MONITOR_JUMP_BACKWARD_r11 1288 +#define _MONITOR_JUMP_BACKWARD_r22 1289 +#define _MONITOR_JUMP_BACKWARD_r33 1290 +#define _MONITOR_RESUME_r00 1291 +#define _NOP_r00 1292 +#define _NOP_r11 1293 +#define _NOP_r22 1294 +#define _NOP_r33 1295 +#define _POP_CALL_r20 1296 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1297 +#define _POP_CALL_ONE_r30 1298 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1299 +#define _POP_CALL_TWO_r30 1300 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1301 +#define _POP_EXCEPT_r10 1302 +#define _POP_ITER_r20 1303 +#define _POP_JUMP_IF_FALSE_r00 1304 +#define _POP_JUMP_IF_FALSE_r10 1305 +#define _POP_JUMP_IF_FALSE_r21 1306 +#define _POP_JUMP_IF_FALSE_r32 1307 +#define _POP_JUMP_IF_TRUE_r00 1308 +#define _POP_JUMP_IF_TRUE_r10 1309 +#define _POP_JUMP_IF_TRUE_r21 1310 +#define _POP_JUMP_IF_TRUE_r32 1311 +#define _POP_TOP_r10 1312 +#define _POP_TOP_FLOAT_r00 1313 +#define _POP_TOP_FLOAT_r10 1314 +#define _POP_TOP_FLOAT_r21 1315 +#define _POP_TOP_FLOAT_r32 1316 +#define _POP_TOP_INT_r00 1317 +#define _POP_TOP_INT_r10 1318 +#define _POP_TOP_INT_r21 1319 +#define _POP_TOP_INT_r32 1320 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1321 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1322 +#define _POP_TOP_NOP_r00 1323 +#define _POP_TOP_NOP_r10 1324 +#define _POP_TOP_NOP_r21 1325 +#define _POP_TOP_NOP_r32 1326 +#define _POP_TOP_UNICODE_r00 1327 +#define _POP_TOP_UNICODE_r10 1328 +#define _POP_TOP_UNICODE_r21 1329 +#define _POP_TOP_UNICODE_r32 1330 +#define _POP_TWO_r20 1331 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1332 +#define _PUSH_EXC_INFO_r02 1333 +#define _PUSH_EXC_INFO_r12 1334 +#define _PUSH_EXC_INFO_r23 1335 +#define _PUSH_FRAME_r10 1336 +#define _PUSH_NULL_r01 1337 +#define _PUSH_NULL_r12 1338 +#define _PUSH_NULL_r23 1339 +#define _PUSH_NULL_CONDITIONAL_r00 1340 +#define _PY_FRAME_EX_r31 1341 +#define _PY_FRAME_GENERAL_r01 1342 +#define _PY_FRAME_KW_r11 1343 +#define _QUICKEN_RESUME_r00 1344 +#define _QUICKEN_RESUME_r11 1345 +#define _QUICKEN_RESUME_r22 1346 +#define _QUICKEN_RESUME_r33 1347 +#define _REPLACE_WITH_TRUE_r02 1348 +#define _REPLACE_WITH_TRUE_r12 1349 +#define _REPLACE_WITH_TRUE_r23 1350 +#define _RESUME_CHECK_r00 1351 +#define _RESUME_CHECK_r11 1352 +#define _RESUME_CHECK_r22 1353 +#define _RESUME_CHECK_r33 1354 +#define _RETURN_GENERATOR_r01 1355 +#define _RETURN_VALUE_r11 1356 +#define _SAVE_RETURN_OFFSET_r00 1357 +#define _SAVE_RETURN_OFFSET_r11 1358 +#define _SAVE_RETURN_OFFSET_r22 1359 +#define _SAVE_RETURN_OFFSET_r33 1360 +#define _SEND_r22 1361 +#define _SEND_GEN_FRAME_r22 1362 +#define _SETUP_ANNOTATIONS_r00 1363 +#define _SET_ADD_r10 1364 +#define _SET_FUNCTION_ATTRIBUTE_r01 1365 +#define _SET_FUNCTION_ATTRIBUTE_r11 1366 +#define _SET_FUNCTION_ATTRIBUTE_r21 1367 +#define _SET_FUNCTION_ATTRIBUTE_r32 1368 +#define _SET_IP_r00 1369 +#define _SET_IP_r11 1370 +#define _SET_IP_r22 1371 +#define _SET_IP_r33 1372 +#define _SET_UPDATE_r10 1373 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1374 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1375 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1376 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1377 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1378 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1379 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1380 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1381 +#define _SPILL_OR_RELOAD_r01 1382 +#define _SPILL_OR_RELOAD_r02 1383 +#define _SPILL_OR_RELOAD_r03 1384 +#define _SPILL_OR_RELOAD_r10 1385 +#define _SPILL_OR_RELOAD_r12 1386 +#define _SPILL_OR_RELOAD_r13 1387 +#define _SPILL_OR_RELOAD_r20 1388 +#define _SPILL_OR_RELOAD_r21 1389 +#define _SPILL_OR_RELOAD_r23 1390 +#define _SPILL_OR_RELOAD_r30 1391 +#define _SPILL_OR_RELOAD_r31 1392 +#define _SPILL_OR_RELOAD_r32 1393 +#define _START_EXECUTOR_r00 1394 +#define _STORE_ATTR_r20 1395 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1396 +#define _STORE_ATTR_SLOT_r21 1397 +#define _STORE_ATTR_WITH_HINT_r21 1398 +#define _STORE_DEREF_r10 1399 +#define _STORE_FAST_LOAD_FAST_r11 1400 +#define _STORE_FAST_STORE_FAST_r20 1401 +#define _STORE_GLOBAL_r10 1402 +#define _STORE_NAME_r10 1403 +#define _STORE_SLICE_r30 1404 +#define _STORE_SUBSCR_r30 1405 +#define _STORE_SUBSCR_DICT_r31 1406 +#define _STORE_SUBSCR_LIST_INT_r32 1407 +#define _SWAP_r11 1408 +#define _SWAP_2_r02 1409 +#define _SWAP_2_r12 1410 +#define _SWAP_2_r22 1411 +#define _SWAP_2_r33 1412 +#define _SWAP_3_r03 1413 +#define _SWAP_3_r13 1414 +#define _SWAP_3_r23 1415 +#define _SWAP_3_r33 1416 +#define _SWAP_FAST_r01 1417 +#define _SWAP_FAST_r11 1418 +#define _SWAP_FAST_r22 1419 +#define _SWAP_FAST_r33 1420 +#define _SWAP_FAST_0_r01 1421 +#define _SWAP_FAST_0_r11 1422 +#define _SWAP_FAST_0_r22 1423 +#define _SWAP_FAST_0_r33 1424 +#define _SWAP_FAST_1_r01 1425 +#define _SWAP_FAST_1_r11 1426 +#define _SWAP_FAST_1_r22 1427 +#define _SWAP_FAST_1_r33 1428 +#define _SWAP_FAST_2_r01 1429 +#define _SWAP_FAST_2_r11 1430 +#define _SWAP_FAST_2_r22 1431 +#define _SWAP_FAST_2_r33 1432 +#define _SWAP_FAST_3_r01 1433 +#define _SWAP_FAST_3_r11 1434 +#define _SWAP_FAST_3_r22 1435 +#define _SWAP_FAST_3_r33 1436 +#define _SWAP_FAST_4_r01 1437 +#define _SWAP_FAST_4_r11 1438 +#define _SWAP_FAST_4_r22 1439 +#define _SWAP_FAST_4_r33 1440 +#define _SWAP_FAST_5_r01 1441 +#define _SWAP_FAST_5_r11 1442 +#define _SWAP_FAST_5_r22 1443 +#define _SWAP_FAST_5_r33 1444 +#define _SWAP_FAST_6_r01 1445 +#define _SWAP_FAST_6_r11 1446 +#define _SWAP_FAST_6_r22 1447 +#define _SWAP_FAST_6_r33 1448 +#define _SWAP_FAST_7_r01 1449 +#define _SWAP_FAST_7_r11 1450 +#define _SWAP_FAST_7_r22 1451 +#define _SWAP_FAST_7_r33 1452 +#define _TIER2_RESUME_CHECK_r00 1453 +#define _TIER2_RESUME_CHECK_r11 1454 +#define _TIER2_RESUME_CHECK_r22 1455 +#define _TIER2_RESUME_CHECK_r33 1456 +#define _TO_BOOL_r11 1457 +#define _TO_BOOL_BOOL_r01 1458 +#define _TO_BOOL_BOOL_r11 1459 +#define _TO_BOOL_BOOL_r22 1460 +#define _TO_BOOL_BOOL_r33 1461 +#define _TO_BOOL_INT_r02 1462 +#define _TO_BOOL_INT_r12 1463 +#define _TO_BOOL_INT_r23 1464 +#define _TO_BOOL_LIST_r02 1465 +#define _TO_BOOL_LIST_r12 1466 +#define _TO_BOOL_LIST_r23 1467 +#define _TO_BOOL_NONE_r01 1468 +#define _TO_BOOL_NONE_r11 1469 +#define _TO_BOOL_NONE_r22 1470 +#define _TO_BOOL_NONE_r33 1471 +#define _TO_BOOL_STR_r02 1472 +#define _TO_BOOL_STR_r12 1473 +#define _TO_BOOL_STR_r23 1474 +#define _TRACE_RECORD_r00 1475 +#define _UNARY_INVERT_r12 1476 +#define _UNARY_NEGATIVE_r12 1477 +#define _UNARY_NOT_r01 1478 +#define _UNARY_NOT_r11 1479 +#define _UNARY_NOT_r22 1480 +#define _UNARY_NOT_r33 1481 +#define _UNPACK_EX_r10 1482 +#define _UNPACK_SEQUENCE_r10 1483 +#define _UNPACK_SEQUENCE_LIST_r10 1484 +#define _UNPACK_SEQUENCE_TUPLE_r10 1485 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1486 +#define _WITH_EXCEPT_START_r33 1487 +#define _YIELD_VALUE_r11 1488 +#define MAX_UOP_REGS_ID 1488 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index fbcb95baf2a..9a0852f872d 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -225,7 +225,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_IMPORT_FROM] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_IS_NONE] = HAS_ESCAPES_FLAG, [_GET_LEN] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_MATCH_MAPPING] = 0, [_MATCH_SEQUENCE] = 0, [_MATCH_KEYS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -2121,7 +2121,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, { -1, -1, -1 }, { -1, -1, -1 }, - { 1, 3, _MATCH_CLASS_r31 }, + { 3, 3, _MATCH_CLASS_r33 }, }, }, [_MATCH_MAPPING] = { @@ -3955,7 +3955,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_IMPORT_FROM_r12] = _IMPORT_FROM, [_IS_NONE_r11] = _IS_NONE, [_GET_LEN_r12] = _GET_LEN, - [_MATCH_CLASS_r31] = _MATCH_CLASS, + [_MATCH_CLASS_r33] = _MATCH_CLASS, [_MATCH_MAPPING_r02] = _MATCH_MAPPING, [_MATCH_MAPPING_r12] = _MATCH_MAPPING, [_MATCH_MAPPING_r23] = _MATCH_MAPPING, @@ -5245,7 +5245,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_MAP_ADD] = "_MAP_ADD", [_MAP_ADD_r20] = "_MAP_ADD_r20", [_MATCH_CLASS] = "_MATCH_CLASS", - [_MATCH_CLASS_r31] = "_MATCH_CLASS_r31", + [_MATCH_CLASS_r33] = "_MATCH_CLASS_r33", [_MATCH_KEYS] = "_MATCH_KEYS", [_MATCH_KEYS_r23] = "_MATCH_KEYS_r23", [_MATCH_MAPPING] = "_MATCH_MAPPING", diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 4dd1140f7d8..e5fada1f40c 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3950,6 +3950,24 @@ def testfunc(n): self.assertIn("_POP_TOP_NOP", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + def test_match_class(self): + def testfunc(n): + class A: + val = 1 + x = A() + ret = 0 + for _ in range(n): + match x: + case A(): + ret += x.val + return ret + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_MATCH_CLASS", uops) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 4) def test_143026(self): # https://github.com/python/cpython/issues/143026 diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst new file mode 100644 index 00000000000..5b7293b5671 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst @@ -0,0 +1 @@ +Eliminate redundant refcounting for ``MATCH_CLASS`` in the JIT. diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index b025f7b0eb7..9e86bc42f20 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -9984,43 +9984,64 @@ _PyStackRef type; _PyStackRef names; _PyStackRef attrs; - names = stack_pointer[-1]; - type = stack_pointer[-2]; - subject = stack_pointer[-3]; - assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *attrs_o = _PyEval_MatchClass(tstate, - PyStackRef_AsPyObjectBorrow(subject), - PyStackRef_AsPyObjectBorrow(type), oparg, - PyStackRef_AsPyObjectBorrow(names)); - _PyStackRef tmp = names; - names = PyStackRef_NULL; - stack_pointer[-1] = names; - PyStackRef_CLOSE(tmp); - tmp = type; - type = PyStackRef_NULL; - stack_pointer[-2] = type; - PyStackRef_CLOSE(tmp); - tmp = subject; - subject = PyStackRef_NULL; - stack_pointer[-3] = subject; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - if (attrs_o) { - assert(PyTuple_CheckExact(attrs_o)); - attrs = PyStackRef_FromPyObjectSteal(attrs_o); - } - else { - if (_PyErr_Occurred(tstate)) { - JUMP_TO_LABEL(error); + _PyStackRef s; + _PyStackRef tp; + _PyStackRef n; + _PyStackRef value; + // _MATCH_CLASS + { + names = stack_pointer[-1]; + type = stack_pointer[-2]; + subject = stack_pointer[-3]; + assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *attrs_o = _PyEval_MatchClass(tstate, + PyStackRef_AsPyObjectBorrow(subject), + PyStackRef_AsPyObjectBorrow(type), oparg, + PyStackRef_AsPyObjectBorrow(names)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (attrs_o) { + assert(PyTuple_CheckExact(attrs_o)); + attrs = PyStackRef_FromPyObjectSteal(attrs_o); } - attrs = PyStackRef_None; + else { + if (_PyErr_Occurred(tstate)) { + JUMP_TO_LABEL(error); + } + attrs = PyStackRef_None; + } + s = subject; + tp = type; + n = names; + } + // _POP_TOP + { + value = n; + stack_pointer[-3] = attrs; + stack_pointer[-2] = s; + stack_pointer[-1] = tp; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = tp; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = s; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - stack_pointer[0] = attrs; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 0eff5f76740..43a512611fb 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3254,7 +3254,7 @@ dummy_func( len = PyStackRef_FromPyObjectSteal(len_o); } - inst(MATCH_CLASS, (subject, type, names -- attrs)) { + op(_MATCH_CLASS, (subject, type, names -- attrs, s, tp, n)) { // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); @@ -3262,17 +3262,24 @@ dummy_func( PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); - DECREF_INPUTS(); if (attrs_o) { assert(PyTuple_CheckExact(attrs_o)); // Success! attrs = PyStackRef_FromPyObjectSteal(attrs_o); } else { - ERROR_IF(_PyErr_Occurred(tstate)); // Error! + if (_PyErr_Occurred(tstate)) { // Error! + ERROR_NO_POP(); + } attrs = PyStackRef_None; // Failure! } + s = subject; + tp = type; + n = names; + INPUTS_DEAD(); } + macro(MATCH_CLASS) = _MATCH_CLASS + POP_TOP + POP_TOP + POP_TOP; + inst(MATCH_MAPPING, (subject -- subject, res)) { int match = PyStackRef_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; res = match ? PyStackRef_True : PyStackRef_False; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 032d6faeda6..7a698e422ab 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -11292,13 +11292,16 @@ break; } - case _MATCH_CLASS_r31: { + case _MATCH_CLASS_r33: { CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef names; _PyStackRef type; _PyStackRef subject; _PyStackRef attrs; + _PyStackRef s; + _PyStackRef tp; + _PyStackRef n; _PyStackRef _stack_item_0 = _tos_cache0; _PyStackRef _stack_item_1 = _tos_cache1; _PyStackRef _stack_item_2 = _tos_cache2; @@ -11317,21 +11320,7 @@ PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); - _PyStackRef tmp = names; - names = PyStackRef_NULL; - stack_pointer[-1] = names; - PyStackRef_CLOSE(tmp); - tmp = type; - type = PyStackRef_NULL; - stack_pointer[-2] = type; - PyStackRef_CLOSE(tmp); - tmp = subject; - subject = PyStackRef_NULL; - stack_pointer[-3] = subject; - PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (attrs_o) { assert(PyTuple_CheckExact(attrs_o)); attrs = PyStackRef_FromPyObjectSteal(attrs_o); @@ -11343,10 +11332,16 @@ } attrs = PyStackRef_None; } - _tos_cache0 = attrs; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + s = subject; + tp = type; + n = names; + _tos_cache2 = n; + _tos_cache1 = tp; + _tos_cache0 = s; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer[-3] = attrs; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index de036fb964b..72619fd3afa 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -9982,43 +9982,64 @@ _PyStackRef type; _PyStackRef names; _PyStackRef attrs; - names = stack_pointer[-1]; - type = stack_pointer[-2]; - subject = stack_pointer[-3]; - assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *attrs_o = _PyEval_MatchClass(tstate, - PyStackRef_AsPyObjectBorrow(subject), - PyStackRef_AsPyObjectBorrow(type), oparg, - PyStackRef_AsPyObjectBorrow(names)); - _PyStackRef tmp = names; - names = PyStackRef_NULL; - stack_pointer[-1] = names; - PyStackRef_CLOSE(tmp); - tmp = type; - type = PyStackRef_NULL; - stack_pointer[-2] = type; - PyStackRef_CLOSE(tmp); - tmp = subject; - subject = PyStackRef_NULL; - stack_pointer[-3] = subject; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - if (attrs_o) { - assert(PyTuple_CheckExact(attrs_o)); - attrs = PyStackRef_FromPyObjectSteal(attrs_o); - } - else { - if (_PyErr_Occurred(tstate)) { - JUMP_TO_LABEL(error); + _PyStackRef s; + _PyStackRef tp; + _PyStackRef n; + _PyStackRef value; + // _MATCH_CLASS + { + names = stack_pointer[-1]; + type = stack_pointer[-2]; + subject = stack_pointer[-3]; + assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *attrs_o = _PyEval_MatchClass(tstate, + PyStackRef_AsPyObjectBorrow(subject), + PyStackRef_AsPyObjectBorrow(type), oparg, + PyStackRef_AsPyObjectBorrow(names)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (attrs_o) { + assert(PyTuple_CheckExact(attrs_o)); + attrs = PyStackRef_FromPyObjectSteal(attrs_o); } - attrs = PyStackRef_None; + else { + if (_PyErr_Occurred(tstate)) { + JUMP_TO_LABEL(error); + } + attrs = PyStackRef_None; + } + s = subject; + tp = type; + n = names; + } + // _POP_TOP + { + value = n; + stack_pointer[-3] = attrs; + stack_pointer[-2] = s; + stack_pointer[-1] = tp; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = tp; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + // _POP_TOP + { + value = s; + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - stack_pointer[0] = attrs; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 2b68ba4d2cd..6092da8c04e 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1710,6 +1710,13 @@ dummy_func(void) { ss = sub_st; } + op(_MATCH_CLASS, (subject, type, names -- attrs, s, tp, n)) { + attrs = sym_new_not_null(ctx); + s = subject; + tp = type; + n = names; + } + op(_RECORD_TOS, (tos -- tos)) { sym_set_recorded_value(tos, (PyObject *)this_instr->operand0); } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index fe083411b7b..2df50ebbcaa 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2649,11 +2649,26 @@ } case _MATCH_CLASS: { + JitOptRef names; + JitOptRef type; + JitOptRef subject; JitOptRef attrs; + JitOptRef s; + JitOptRef tp; + JitOptRef n; + names = stack_pointer[-1]; + type = stack_pointer[-2]; + subject = stack_pointer[-3]; attrs = sym_new_not_null(ctx); - CHECK_STACK_BOUNDS(-2); + s = subject; + tp = type; + n = names; + CHECK_STACK_BOUNDS(1); stack_pointer[-3] = attrs; - stack_pointer += -2; + stack_pointer[-2] = s; + stack_pointer[-1] = tp; + stack_pointer[0] = n; + stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } From 9a83c02a0f5d85f6940c5ce3ad630e2e8d6c5661 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sat, 14 Mar 2026 16:00:15 +0000 Subject: [PATCH 131/775] gh-137650: Group dependabot actions updates (#145947) --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7f3376f8ddb..e68a07382d5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,6 +12,10 @@ updates: update-types: - "version-update:semver-minor" - "version-update:semver-patch" + groups: + actions: + patterns: + - "*" cooldown: # https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns # Cooldowns protect against supply chain attacks by avoiding the From 0575ce936d3f16ce2547ba17d2a22d90369779b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 16:30:26 +0000 Subject: [PATCH 132/775] build(deps): bump the actions group with 4 updates (#145952) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/reusable-check-c-api-docs.yml | 4 ++-- .github/workflows/reusable-cifuzz.yml | 2 +- .github/workflows/reusable-san.yml | 2 +- .github/workflows/stale.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c017ee04d67..2fa2ab768dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -475,7 +475,7 @@ jobs: -x test_subprocess \ -x test_signal \ -x test_sysconfig - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 if: always() with: name: hypothesis-example-db diff --git a/.github/workflows/reusable-check-c-api-docs.yml b/.github/workflows/reusable-check-c-api-docs.yml index bab1ca67d53..b95bd6a0184 100644 --- a/.github/workflows/reusable-check-c-api-docs.yml +++ b/.github/workflows/reusable-check-c-api-docs.yml @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: '3.x' - name: Check for undocumented C APIs diff --git a/.github/workflows/reusable-cifuzz.yml b/.github/workflows/reusable-cifuzz.yml index 1986f5fb2cc..6cd9c26037f 100644 --- a/.github/workflows/reusable-cifuzz.yml +++ b/.github/workflows/reusable-cifuzz.yml @@ -34,7 +34,7 @@ jobs: sanitizer: ${{ inputs.sanitizer }} - name: Upload crash if: failure() && steps.build.outcome == 'success' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: ${{ inputs.sanitizer }}-artifacts path: ./out/artifacts diff --git a/.github/workflows/reusable-san.yml b/.github/workflows/reusable-san.yml index b70f9b4b0d6..79a4ded09fc 100644 --- a/.github/workflows/reusable-san.yml +++ b/.github/workflows/reusable-san.yml @@ -96,7 +96,7 @@ jobs: run: find "${GITHUB_WORKSPACE}" -name 'san_log.*' | xargs head -n 1000 - name: Archive logs if: always() - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: >- ${{ inputs.sanitizer }}-logs-${{ diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index febb2dd823a..915b1acd33f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,7 +14,7 @@ jobs: steps: - name: "Check PRs" - uses: actions/stale@v9 + uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This PR is stale because it has been open for 30 days with no activity.' From 31c41a61f1afb7929d2698e48894264d8e2df86b Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sat, 14 Mar 2026 18:11:29 +0000 Subject: [PATCH 133/775] Fix `fuzz_builtin_int` fuzzer reproducibility (#145890) --- Modules/_xxtestfuzz/fuzzer.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index 6cb11562476..02afb01d373 100644 --- a/Modules/_xxtestfuzz/fuzzer.c +++ b/Modules/_xxtestfuzz/fuzzer.c @@ -38,23 +38,18 @@ static int fuzz_builtin_float(const char* data, size_t size) { static int fuzz_builtin_int(const char* data, size_t size) { /* Ignore test cases with very long ints to avoid timeouts int("9" * 1000000) is not a very interesting test caase */ - if (size > MAX_INT_TEST_SIZE) { + if (size < 1 || size > MAX_INT_TEST_SIZE) { return 0; } - /* Pick a random valid base. (When the fuzzed function takes extra - parameters, it's somewhat normal to hash the input to generate those - parameters. We want to exercise all code paths, so we do so here.) */ - int base = Py_HashBuffer(data, size) % 37; + // Use the first byte to pick a base + int base = ((unsigned char) data[0]) % 37; if (base == 1) { // 1 is the only number between 0 and 36 that is not a valid base. base = 0; } - if (base == -1) { - return 0; // An error occurred, bail early. - } - if (base < 0) { - base = -base; - } + + data += 1; + size -= 1; PyObject* s = PyUnicode_FromStringAndSize(data, size); if (s == NULL) { From 788c3291172b55efa7cf8b33a315e4b0fe63540c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Sat, 14 Mar 2026 11:28:49 -0700 Subject: [PATCH 134/775] gh-123720: When closing an asyncio server, stop the handlers (#124689) --- Lib/asyncio/base_events.py | 1 + Lib/test/test_asyncio/test_server.py | 32 +++++++++++++++++++ ...-03-11-10-25-32.gh-issue-123720.TauFRx.rst | 5 +++ 3 files changed, 38 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 0930ef403c6..77c70aaa7b9 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -381,6 +381,7 @@ async def serve_forever(self): except exceptions.CancelledError: try: self.close() + self.close_clients() await self.wait_closed() finally: raise diff --git a/Lib/test/test_asyncio/test_server.py b/Lib/test/test_asyncio/test_server.py index 5bd0f7e2af4..581ea47d2de 100644 --- a/Lib/test/test_asyncio/test_server.py +++ b/Lib/test/test_asyncio/test_server.py @@ -266,6 +266,38 @@ async def serve(rd, wr): await asyncio.sleep(0) self.assertTrue(task.done()) + async def test_close_with_hanging_client(self): + # Synchronize server cancellation only after the socket connection is + # accepted and this event is set + conn_event = asyncio.Event() + class Proto(asyncio.Protocol): + def connection_made(self, transport): + conn_event.set() + + loop = asyncio.get_running_loop() + srv = await loop.create_server(Proto, socket_helper.HOSTv4, 0) + + # Start the server + serve_forever_task = asyncio.create_task(srv.serve_forever()) + await asyncio.sleep(0) + + # Create a connection to server + addr = srv.sockets[0].getsockname() + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect(addr) + self.addCleanup(sock.close) + + # Send a CancelledError into the server to emulate a Ctrl+C + # KeyboardInterrupt whilst the server is handling a hanging client + await conn_event.wait() + serve_forever_task.cancel() + + # Ensure the client is closed within a timeout + async with asyncio.timeout(0.5): + await srv.wait_closed() + + self.assertFalse(srv.is_serving()) + # Test the various corner cases of Unix server socket removal class UnixServerCleanupTests(unittest.IsolatedAsyncioTestCase): diff --git a/Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst b/Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst new file mode 100644 index 00000000000..04e6a377dd8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst @@ -0,0 +1,5 @@ +asyncio: Fix :func:`asyncio.Server.serve_forever` shutdown regression. Since +3.12, cancelling ``serve_forever()`` could hang waiting for a handler blocked +on a read from a client that never closed (effectively requiring two +interrupts to stop); the shutdown sequence now ensures client streams are +closed so ``serve_forever()`` exits promptly and handlers observe EOF. From 1dfe99ae3bed6cac01732b47bf7fa637abadf51b Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 14 Mar 2026 22:58:35 -0400 Subject: [PATCH 135/775] gh-141004: Document `PyDTrace*` (GH-141856) --- Doc/howto/instrumentation.rst | 78 +++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/Doc/howto/instrumentation.rst b/Doc/howto/instrumentation.rst index b3db1189e5d..06c1ae40da5 100644 --- a/Doc/howto/instrumentation.rst +++ b/Doc/howto/instrumentation.rst @@ -341,6 +341,84 @@ Available static markers .. versionadded:: 3.8 +C Entry Points +^^^^^^^^^^^^^^ + +To simplify triggering of DTrace markers, Python's C API comes with a number +of helper functions that mirror each static marker. On builds of Python without +DTrace enabled, these do nothing. + +In general, it is not necessary to call these yourself, as Python will do +it for you. + +.. list-table:: + :widths: 50 25 25 + :header-rows: 1 + + * * C API Function + * Static Marker + * Notes + * * .. c:function:: void PyDTrace_LINE(const char *arg0, const char *arg1, int arg2) + * :c:func:`!line` + * + * * .. c:function:: void PyDTrace_FUNCTION_ENTRY(const char *arg0, const char *arg1, int arg2) + * :c:func:`!function__entry` + * + * * .. c:function:: void PyDTrace_FUNCTION_RETURN(const char *arg0, const char *arg1, int arg2) + * :c:func:`!function__return` + * + * * .. c:function:: void PyDTrace_GC_START(int arg0) + * :c:func:`!gc__start` + * + * * .. c:function:: void PyDTrace_GC_DONE(Py_ssize_t arg0) + * :c:func:`!gc__done` + * + * * .. c:function:: void PyDTrace_INSTANCE_NEW_START(int arg0) + * :c:func:`!instance__new__start` + * Not used by Python + * * .. c:function:: void PyDTrace_INSTANCE_NEW_DONE(int arg0) + * :c:func:`!instance__new__done` + * Not used by Python + * * .. c:function:: void PyDTrace_INSTANCE_DELETE_START(int arg0) + * :c:func:`!instance__delete__start` + * Not used by Python + * * .. c:function:: void PyDTrace_INSTANCE_DELETE_DONE(int arg0) + * :c:func:`!instance__delete__done` + * Not used by Python + * * .. c:function:: void PyDTrace_IMPORT_FIND_LOAD_START(const char *arg0) + * :c:func:`!import__find__load__start` + * + * * .. c:function:: void PyDTrace_IMPORT_FIND_LOAD_DONE(const char *arg0, int arg1) + * :c:func:`!import__find__load__done` + * + * * .. c:function:: void PyDTrace_AUDIT(const char *arg0, void *arg1) + * :c:func:`!audit` + * + + +C Probing Checks +^^^^^^^^^^^^^^^^ + +.. c:function:: int PyDTrace_LINE_ENABLED(void) +.. c:function:: int PyDTrace_FUNCTION_ENTRY_ENABLED(void) +.. c:function:: int PyDTrace_FUNCTION_RETURN_ENABLED(void) +.. c:function:: int PyDTrace_GC_START_ENABLED(void) +.. c:function:: int PyDTrace_GC_DONE_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_NEW_START_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_NEW_DONE_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_DELETE_START_ENABLED(void) +.. c:function:: int PyDTrace_INSTANCE_DELETE_DONE_ENABLED(void) +.. c:function:: int PyDTrace_IMPORT_FIND_LOAD_START_ENABLED(void) +.. c:function:: int PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED(void) +.. c:function:: int PyDTrace_AUDIT_ENABLED(void) + + All calls to ``PyDTrace`` functions must be guarded by a call to one + of these functions. This allows Python to minimize performance impact + when probing is disabled. + + On builds without DTrace enabled, these functions do nothing and return + ``0``. + SystemTap Tapsets ----------------- From e167e06f8c6b24f7b54e8d6b87c1cac1667dd2cf Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Sun, 15 Mar 2026 05:48:56 -0400 Subject: [PATCH 136/775] Bump mypy to 1.19.1 (#145956) --- Lib/test/libregrtest/utils.py | 2 +- Tools/clinic/libclinic/clanguage.py | 2 +- Tools/requirements-dev.txt | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py index 3bbc3fa127a..7cc9d0bf262 100644 --- a/Lib/test/libregrtest/utils.py +++ b/Lib/test/libregrtest/utils.py @@ -150,7 +150,7 @@ def setup_unraisable_hook() -> None: sys.unraisablehook = regrtest_unraisable_hook -orig_threading_excepthook: Callable[..., None] | None = None +orig_threading_excepthook: Callable[..., object] | None = None def regrtest_threading_excepthook(args) -> None: diff --git a/Tools/clinic/libclinic/clanguage.py b/Tools/clinic/libclinic/clanguage.py index 9e7fa7a7f58..341667d2f0b 100644 --- a/Tools/clinic/libclinic/clanguage.py +++ b/Tools/clinic/libclinic/clanguage.py @@ -6,7 +6,7 @@ from operator import attrgetter from collections.abc import Iterable -import libclinic +import libclinic.cpp from libclinic import ( unspecified, fail, Sentinels, VersionTuple) from libclinic.codegen import CRenderData, TemplateDict, CodeGen diff --git a/Tools/requirements-dev.txt b/Tools/requirements-dev.txt index 73236767374..af5cbaa7689 100644 --- a/Tools/requirements-dev.txt +++ b/Tools/requirements-dev.txt @@ -1,7 +1,7 @@ # Requirements file for external linters and checks we run on # Tools/clinic, Tools/cases_generator/, and Tools/peg_generator/ in CI -mypy==1.17.1 +mypy==1.19.1 # needed for peg_generator: -types-psutil==7.0.0.20250801 -types-setuptools==80.9.0.20250801 +types-psutil==7.2.2.20260130 +types-setuptools==82.0.0.20260210 From 2f4e4ec2e7292901cab0c1466b78f5ddff48208d Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Sun, 15 Mar 2026 15:57:05 +0100 Subject: [PATCH 137/775] gh-142518: Document thread-safety guarantees of bytearray objects (#145226) --- Doc/library/stdtypes.rst | 5 ++ Doc/library/threadsafety.rst | 101 +++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 6e2c72daf7a..24f53a3a272 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3514,6 +3514,11 @@ The representation of bytearray objects uses the bytes literal format ``bytearray([46, 46, 46])``. You can always convert a bytearray object into a list of integers using ``list(b)``. +.. seealso:: + + For detailed information on thread-safety guarantees for :class:`bytearray` + objects, see :ref:`thread-safety-bytearray`. + .. _bytes-methods: diff --git a/Doc/library/threadsafety.rst b/Doc/library/threadsafety.rst index 4f2eda19b85..8063c2ea501 100644 --- a/Doc/library/threadsafety.rst +++ b/Doc/library/threadsafety.rst @@ -447,3 +447,104 @@ atomic: Consider external synchronization when sharing :class:`set` instances across threads. See :ref:`freethreading-python-howto` for more information. + + +.. _thread-safety-bytearray: + +Thread safety for bytearray objects +=================================== + + The :func:`len` function is lock-free and :term:`atomic `. + + Concatenation and comparisons use the buffer protocol, which prevents + resizing but does not hold the per-object lock. These operations may + observe intermediate states from concurrent modifications: + + .. code-block:: + :class: maybe + + ba + other # may observe concurrent writes + ba == other # may observe concurrent writes + ba < other # may observe concurrent writes + + All other operations from here on hold the per-object lock. + + Reading a single element or slice is safe to call from multiple threads: + + .. code-block:: + :class: good + + ba[i] # bytearray.__getitem__ + ba[i:j] # slice + + The following operations are safe to call from multiple threads and will + not corrupt the bytearray: + + .. code-block:: + :class: good + + ba[i] = x # write single byte + ba[i:j] = values # write slice + ba.append(x) # append single byte + ba.extend(other) # extend with iterable + ba.insert(i, x) # insert single byte + ba.pop() # remove and return last byte + ba.pop(i) # remove and return byte at index + ba.remove(x) # remove first occurrence + ba.reverse() # reverse in place + ba.clear() # remove all bytes + + Slice assignment locks both objects when *values* is a :class:`bytearray`: + + .. code-block:: + :class: good + + ba[i:j] = other_bytearray # both locked + + The following operations return new objects and hold the per-object lock + for the duration: + + .. code-block:: + :class: good + + ba.copy() # returns a shallow copy + ba * n # repeat into new bytearray + + The membership test holds the lock for its duration: + + .. code-block:: + :class: good + + x in ba # bytearray.__contains__ + + All other bytearray methods (such as :meth:`~bytearray.find`, + :meth:`~bytearray.replace`, :meth:`~bytearray.split`, + :meth:`~bytearray.decode`, etc.) hold the per-object lock for their + duration. + + Operations that involve multiple accesses, as well as iteration, are never + atomic: + + .. code-block:: + :class: bad + + # NOT atomic: check-then-act + if x in ba: + ba.remove(x) + + # NOT thread-safe: iteration while modifying + for byte in ba: + process(byte) # another thread may modify ba + + To safely iterate over a bytearray that may be modified by another + thread, iterate over a copy: + + .. code-block:: + :class: good + + # Make a copy to iterate safely + for byte in ba.copy(): + process(byte) + + Consider external synchronization when sharing :class:`bytearray` instances + across threads. See :ref:`freethreading-python-howto` for more information. From 757e2ff9d997fb8314e7270d3a71f38c18cc9235 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sun, 15 Mar 2026 17:14:27 +0000 Subject: [PATCH 138/775] gh-145976: Remove `Misc/{Porting,vgrindefs}` (#145973) Cleanup outdated files under Misc/ --- .../2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst | 1 + Misc/Porting | 1 - Misc/README | 2 -- Misc/vgrindefs | 10 ---------- 4 files changed, 1 insertion(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst delete mode 100644 Misc/Porting delete mode 100644 Misc/vgrindefs diff --git a/Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst b/Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst new file mode 100644 index 00000000000..0d74776ff90 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst @@ -0,0 +1 @@ +Remove :file:`Misc/vgrindefs` and :file:`Misc/Porting`. diff --git a/Misc/Porting b/Misc/Porting deleted file mode 100644 index f16c4600521..00000000000 --- a/Misc/Porting +++ /dev/null @@ -1 +0,0 @@ -This document is moved to https://devguide.python.org/porting/ diff --git a/Misc/README b/Misc/README index cbad9b72dc7..038f842e0bc 100644 --- a/Misc/README +++ b/Misc/README @@ -11,7 +11,6 @@ ACKS Acknowledgements HISTORY News from previous releases -- oldest last indent.pro GNU indent profile approximating my C style NEWS News for this release (for some meaning of "this") -Porting Mini-FAQ on porting to new platforms python-config.in Python script template for python-config python.man UNIX man page for the python interpreter python.pc.in Package configuration info template for pkg-config @@ -22,4 +21,3 @@ SpecialBuilds.txt Describes extra symbols you can set for debug builds svnmap.txt Map of old SVN revs and branches to hg changeset ids, help history-digging valgrind-python.supp Valgrind suppression file, see README.valgrind -vgrindefs Python configuration for vgrind (a generic pretty printer) diff --git a/Misc/vgrindefs b/Misc/vgrindefs deleted file mode 100644 index 3e6d8a4629a..00000000000 --- a/Misc/vgrindefs +++ /dev/null @@ -1,10 +0,0 @@ -# vgrind is a pretty-printer that takes source code and outputs -# eye-pleasing postscript. The entry below should be added to your -# local vgrindefs file. Contributed by Neale Pickett . - -python|Python|py:\ - :pb=^\d?(def|class)\d\p(\d|\\|\(|\:):\ - :cb=#:ce=$:sb=":se=\e":lb=':le=\e':\ - :kw=assert and break class continue def del elif else except\ - finally for from global if import in is lambda not or\ - pass print raise return try while yield: From ec5e3a5a073507089b0b5908a5a298f8845bb2e4 Mon Sep 17 00:00:00 2001 From: Matthieu Darbois Date: Sun, 15 Mar 2026 18:46:44 +0100 Subject: [PATCH 139/775] gh-145968: Fix base64.b64decode altchars translation in specific cases (GH-145969) When altchars overlaps with the standard ones, the translation does not always yield to the expected outcome. --- Lib/base64.py | 8 +++++++- Lib/test/test_base64.py | 7 +++++++ .../2026-03-15-10-17-51.gh-issue-145968.gZexry.rst | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst diff --git a/Lib/base64.py b/Lib/base64.py index 36688ce4391..dcfcbcc95a3 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -100,7 +100,13 @@ def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, *, ignorechars=_NOT_SPE break s = s.translate(bytes.maketrans(altchars, b'+/')) else: - trans = bytes.maketrans(b'+/' + altchars, altchars + b'+/') + trans_in = set(b'+/') - set(altchars) + if len(trans_in) == 2: + # we can't use the reqult of unordered sets here + trans = bytes.maketrans(altchars + b'+/', b'+/' + altchars) + else: + trans = bytes.maketrans(altchars + bytes(trans_in), + b'+/' + bytes(set(altchars) - set(b'+/'))) s = s.translate(trans) ignorechars = ignorechars.translate(trans) if ignorechars is _NOT_SPECIFIED: diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index 69aa628db7c..9648624b267 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -293,6 +293,13 @@ def test_b64decode_altchars(self): eq(base64.b64decode(data_str, altchars=altchars_str), res) eq(base64.b64decode(data, altchars=altchars, ignorechars=b'\n'), res) + eq(base64.b64decode(b'/----', altchars=b'-+', ignorechars=b'/'), b'\xfb\xef\xbe') + eq(base64.b64decode(b'/----', altchars=b'+-', ignorechars=b'/'), b'\xff\xff\xff') + eq(base64.b64decode(b'+----', altchars=b'-/', ignorechars=b'+'), b'\xfb\xef\xbe') + eq(base64.b64decode(b'+----', altchars=b'/-', ignorechars=b'+'), b'\xff\xff\xff') + eq(base64.b64decode(b'+/+/', altchars=b'/+', ignorechars=b''), b'\xff\xef\xfe') + eq(base64.b64decode(b'/+/+', altchars=b'+/', ignorechars=b''), b'\xff\xef\xfe') + self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+') self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+/-') self.assertRaises(ValueError, base64.b64decode, '', altchars='+') diff --git a/Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst b/Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst new file mode 100644 index 00000000000..9eae1dc4008 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst @@ -0,0 +1,2 @@ +Fix translation in :func:`base64.b64decode` when altchars overlaps with the +standard ones. From 4a71946b8fbc364b894a944dc4fd017ed14692cb Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Sun, 15 Mar 2026 13:30:01 -0700 Subject: [PATCH 140/775] gh-122575: gh-142349: fix sys.flags tuple size (it unintentionally increased) (GH-145988) the lazy imports PEP initial implementation (3.15 alpha) inadvertently incremented the length of the sys.flags tuple. In a way that did not do anything useful or related to the lazy imports setting (it exposed sys.flags.gil in the tuple). This fixes that to hard code the length to the 3.13 & 3.14 released length of 18 and have our tests and code comments make it clear that we've since stopped making new sys.flags attributes available via sequence index. --- Lib/test/test_sys.py | 37 +++++++++++++++++++++++++++---------- Python/sysmodule.c | 9 ++++++--- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 8974361c253..a729efee18c 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -858,24 +858,35 @@ def test_subinterp_intern_singleton(self): ''')) self.assertTrue(sys._is_interned(s)) - def test_sys_flags(self): + def test_sys_flags_indexable_attributes(self): self.assertTrue(sys.flags) - attrs = ("debug", + # We've stopped assigning sequence indices to new sys.flags attributes: + # https://github.com/python/cpython/issues/122575#issuecomment-2416497086 + indexable_attrs = ("debug", "inspect", "interactive", "optimize", "dont_write_bytecode", "no_user_site", "no_site", "ignore_environment", "verbose", "bytes_warning", "quiet", "hash_randomization", "isolated", "dev_mode", "utf8_mode", - "warn_default_encoding", "safe_path", "int_max_str_digits", - "lazy_imports") - for attr in attrs: + "warn_default_encoding", "safe_path", "int_max_str_digits") + for attr_idx, attr in enumerate(indexable_attrs): self.assertHasAttr(sys.flags, attr) attr_type = bool if attr in ("dev_mode", "safe_path") else int self.assertEqual(type(getattr(sys.flags, attr)), attr_type, attr) + attr_value = getattr(sys.flags, attr) + self.assertEqual(sys.flags[attr_idx], attr_value, + msg=f"sys.flags .{attr} vs [{attr_idx}]") self.assertTrue(repr(sys.flags)) - self.assertEqual(len(sys.flags), len(attrs)) + self.assertEqual(len(sys.flags), 18, msg="Do not increase, see GH-122575") self.assertIn(sys.flags.utf8_mode, {0, 1, 2}) + def test_sys_flags_name_only_attributes(self): + # non-tuple sequence fields (name only sys.flags attributes) + self.assertIsInstance(sys.flags.gil, int|type(None)) + self.assertIsInstance(sys.flags.thread_inherit_context, int|type(None)) + self.assertIsInstance(sys.flags.context_aware_warnings, int|type(None)) + self.assertIsInstance(sys.flags.lazy_imports, int|type(None)) + def assert_raise_on_new_sys_type(self, sys_attr): # Users are intentionally prevented from creating new instances of # sys.flags, sys.version_info, and sys.getwindowsversion. @@ -1908,10 +1919,16 @@ def test_pythontypes(self): # symtable entry # XXX # sys.flags - # FIXME: The +3 is for the 'gil', 'thread_inherit_context' and - # 'context_aware_warnings' flags and will not be necessary once - # gh-122575 is fixed - check(sys.flags, vsize('') + self.P + self.P * (3 + len(sys.flags))) + # FIXME: The non_sequence_fields adjustment is for these flags: + # - 'gil' + # - 'thread_inherit_context' + # - 'context_aware_warnings' + # - 'lazy_imports' + # Not needing to increment this every time we add a new field + # per GH-122575 would be nice... + # Q: What is the actual point of this sys.flags C size derived from PyStructSequence_Field array assertion? + non_sequence_fields = 4 + check(sys.flags, vsize('') + self.P + self.P * (non_sequence_fields + len(sys.flags))) def test_asyncgen_hooks(self): old = sys.get_asyncgen_hooks() diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 893a116565e..646b8a1c3c3 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -3495,11 +3495,12 @@ static PyStructSequence_Field flags_fields[] = { {"dev_mode", "-X dev"}, {"utf8_mode", "-X utf8"}, {"warn_default_encoding", "-X warn_default_encoding"}, - {"safe_path", "-P"}, + {"safe_path", "-P"}, {"int_max_str_digits", "-X int_max_str_digits"}, + // Fields below are only usable by sys.flags attribute name, not index: {"gil", "-X gil"}, {"thread_inherit_context", "-X thread_inherit_context"}, - {"context_aware_warnings", "-X context_aware_warnings"}, + {"context_aware_warnings", "-X context_aware_warnings"}, {"lazy_imports", "-X lazy_imports"}, {0} }; @@ -3510,7 +3511,9 @@ static PyStructSequence_Desc flags_desc = { "sys.flags", /* name */ flags__doc__, /* doc */ flags_fields, /* fields */ - 19 + 18 /* NB - do not increase beyond 3.13's value of 18. */ + // New sys.flags fields should NOT be tuple addressable per + // https://github.com/python/cpython/issues/122575#issuecomment-2416497086 }; static void From 33044b015ba1589887629e217d68bba35b1fced5 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sun, 15 Mar 2026 21:29:12 +0000 Subject: [PATCH 141/775] gh-145976: Remove `Misc/indent.pro` (#145992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- ...-03-15-20-59-29.gh-issue-145976.rEdUI-.rst | 2 ++ Misc/README | 3 +-- Misc/indent.pro | 24 ------------------- 3 files changed, 3 insertions(+), 26 deletions(-) create mode 100644 Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst delete mode 100644 Misc/indent.pro diff --git a/Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst b/Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst new file mode 100644 index 00000000000..17b0f2d797f --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst @@ -0,0 +1,2 @@ +Remove :file:`Misc/indent.pro`, a configuration file for GNU +:manpage:`indent(1)`. diff --git a/Misc/README b/Misc/README index 038f842e0bc..1993c58ad8c 100644 --- a/Misc/README +++ b/Misc/README @@ -9,8 +9,7 @@ Files found here ACKS Acknowledgements HISTORY News from previous releases -- oldest last -indent.pro GNU indent profile approximating my C style -NEWS News for this release (for some meaning of "this") +NEWS.d/ News files for this release (for some meaning of "this") python-config.in Python script template for python-config python.man UNIX man page for the python interpreter python.pc.in Package configuration info template for pkg-config diff --git a/Misc/indent.pro b/Misc/indent.pro deleted file mode 100644 index 02cceb62021..00000000000 --- a/Misc/indent.pro +++ /dev/null @@ -1,24 +0,0 @@ ---blank-lines-after-declarations ---blank-lines-after-procedures ---braces-after-func-def-line ---braces-on-if-line ---braces-on-struct-decl-line ---break-after-boolean-operator ---comment-indentation25 ---comment-line-length79 ---continue-at-parentheses ---dont-cuddle-do-while ---dont-cuddle-else ---indent-level4 ---line-length79 ---no-space-after-casts ---no-space-after-function-call-names ---no-space-after-parentheses ---no-tabs ---procnames-start-lines ---space-after-for ---space-after-if ---space-after-while ---swallow-optional-blank-lines --T PyCFunction --T PyObject From eb0e8be3a7e11b87d198a2c3af1ed0eccf532768 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sun, 15 Mar 2026 21:46:06 +0000 Subject: [PATCH 142/775] gh-145986: Avoid unbound C recursion in `conv_content_model` in `pyexpat.c` (CVE 2026-4224) (#145987) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix C stack overflow (CVE-2026-4224) when an Expat parser with a registered `ElementDeclHandler` parses inline DTD containing deeply nested content model. --------- Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/test/test_pyexpat.py | 19 +++++++++++++++++++ ...-03-14-17-31-39.gh-issue-145986.ifSSr8.rst | 4 ++++ Modules/pyexpat.c | 9 ++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 31bcee293b2..f8afc16d3cb 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -701,6 +701,25 @@ def test_trigger_leak(self): parser.ElementDeclHandler = lambda _1, _2: None self.assertRaises(TypeError, parser.Parse, data, True) + @support.skip_if_unlimited_stack_size + @support.skip_emscripten_stack_overflow() + @support.skip_wasi_stack_overflow() + def test_deeply_nested_content_model(self): + # This should raise a RecursionError and not crash. + # See https://github.com/python/cpython/issues/145986. + N = 500_000 + data = ( + b'\n]>\n\n' + ) + + parser = expat.ParserCreate() + parser.ElementDeclHandler = lambda _1, _2: None + with support.infinite_recursion(): + with self.assertRaises(RecursionError): + parser.Parse(data) + class MalformedInputTest(unittest.TestCase): def test1(self): xml = b"\0\r\n" diff --git a/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst b/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst new file mode 100644 index 00000000000..79536d1fef5 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst @@ -0,0 +1,4 @@ +:mod:`xml.parsers.expat`: Fixed a crash caused by unbounded C recursion when +converting deeply nested XML content models with +:meth:`~xml.parsers.expat.xmlparser.ElementDeclHandler`. +This addresses :cve:`2026-4224`. diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index e9255038eee..cadc6706243 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -3,6 +3,7 @@ #endif #include "Python.h" +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_import.h" // _PyImport_SetModule() #include "pycore_pyhash.h" // _Py_HashSecret #include "pycore_traceback.h" // _PyTraceback_Add() @@ -607,6 +608,10 @@ static PyObject * conv_content_model(XML_Content * const model, PyObject *(*conv_string)(void *)) { + if (_Py_EnterRecursiveCall(" in conv_content_model")) { + return NULL; + } + PyObject *result = NULL; PyObject *children = PyTuple_New(model->numchildren); int i; @@ -618,7 +623,7 @@ conv_content_model(XML_Content * const model, conv_string); if (child == NULL) { Py_XDECREF(children); - return NULL; + goto done; } PyTuple_SET_ITEM(children, i, child); } @@ -626,6 +631,8 @@ conv_content_model(XML_Content * const model, model->type, model->quant, conv_string, model->name, children); } +done: + _Py_LeaveRecursiveCall(); return result; } From f7cb789dc5ac009fa13c20527de19fb34e0e6ab8 Mon Sep 17 00:00:00 2001 From: Shahar Naveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sun, 15 Mar 2026 22:54:19 +0100 Subject: [PATCH 143/775] gh-145998: Remove duplicated "What's New in 3.15" entry (#145994) --- Doc/whatsnew/3.15.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 459846e55cc..c286e3fc4f2 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1014,13 +1014,6 @@ symtable (Contributed by Yashp002 in :gh:`143504`.) -symtable --------- - -* Add :meth:`symtable.Function.get_cells` and :meth:`symtable.Symbol.is_cell` methods. - (Contributed by Yashp002 in :gh:`143504`.) - - sys --- From b062f391cfb407b02041737914b4a1f4fb1da87b Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Sun, 15 Mar 2026 15:02:14 -0700 Subject: [PATCH 144/775] gh-145990: Sort `python --help-xoptions` by option name (GH-145991) * Sort --help-xoptions alphabetically by name. * add a sorting regression test in test_help_xoptions --- Lib/test/test_cmd_line.py | 4 +++ ...-03-15-20-47-34.gh-issue-145990.14BUzw.rst | 1 + Python/initconfig.c | 33 ++++++++++--------- 3 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index e106ac20809..c1dc5967789 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -3,6 +3,7 @@ # See test_cmd_line_script.py for testing of script execution import os +import re import subprocess import sys import sysconfig @@ -64,6 +65,9 @@ def test_help_env(self): def test_help_xoptions(self): out = self.verify_valid_flag('--help-xoptions') self.assertIn(b'-X dev', out) + options = re.findall(rb'^-X (\w+)', out, re.MULTILINE) + self.assertEqual(options, sorted(options), + "options should be sorted alphabetically") @support.cpython_only def test_help_all(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst new file mode 100644 index 00000000000..f66c156b4bc --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst @@ -0,0 +1 @@ +``python --help-xoptions`` is now sorted by ``-X`` option name. diff --git a/Python/initconfig.c b/Python/initconfig.c index 57629ff8c57..eff37fc32b4 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -304,9 +304,15 @@ arg ...: arguments passed to program in sys.argv[1:]\n\ static const char usage_xoptions[] = "\ The following implementation-specific options are available:\n\ +-X context_aware_warnings=[0|1]: if true (1) then the warnings module will\n\ + use a context variables; if false (0) then the warnings module will\n\ + use module globals, which is not concurrent-safe; set to true for\n\ + free-threaded builds and false otherwise; also\n\ + PYTHON_CONTEXT_AWARE_WARNINGS\n\ -X cpu_count=N: override the return value of os.cpu_count();\n\ -X cpu_count=default cancels overriding; also PYTHON_CPU_COUNT\n\ -X dev : enable Python Development Mode; also PYTHONDEVMODE\n\ +-X disable-remote-debug: disable remote debugging; also PYTHON_DISABLE_REMOTE_DEBUG\n\ -X faulthandler: dump the Python traceback on fatal errors;\n\ also PYTHONFAULTHANDLER\n\ -X frozen_modules=[on|off]: whether to use frozen modules; the default is \"on\"\n\ @@ -319,16 +325,18 @@ The following implementation-specific options are available:\n\ "\ -X importtime[=2]: show how long each import takes; use -X importtime=2 to\n\ log imports of already-loaded modules; also PYTHONPROFILEIMPORTTIME\n\ --X lazy_imports=[all|none|normal]: control global lazy imports;\n\ - default is normal; also PYTHON_LAZY_IMPORTS\n\ -X int_max_str_digits=N: limit the size of int<->str conversions;\n\ 0 disables the limit; also PYTHONINTMAXSTRDIGITS\n\ +-X lazy_imports=[all|none|normal]: control global lazy imports;\n\ + default is normal; also PYTHON_LAZY_IMPORTS\n\ -X no_debug_ranges: don't include extra location information in code objects;\n\ also PYTHONNODEBUGRANGES\n\ +-X pathconfig_warnings=[0|1]: if true (1) then path configuration is allowed\n\ + to log warnings into stderr; if false (0) suppress these warnings;\n\ + set to true by default; also PYTHON_PATHCONFIG_WARNINGS\n\ -X perf: support the Linux \"perf\" profiler; also PYTHONPERFSUPPORT=1\n\ -X perf_jit: support the Linux \"perf\" profiler with DWARF support;\n\ also PYTHON_PERF_JIT_SUPPORT=1\n\ --X disable-remote-debug: disable remote debugging; also PYTHON_DISABLE_REMOTE_DEBUG\n\ " #ifdef Py_DEBUG "-X presite=MOD: import this module before site; also PYTHON_PRESITE\n" @@ -343,24 +351,17 @@ The following implementation-specific options are available:\n\ "\ -X showrefcount: output the total reference count and number of used\n\ memory blocks when the program finishes or after each statement in\n\ - the interactive interpreter; only works on debug builds\n" + the interactive interpreter; only works on debug builds\n\ +-X thread_inherit_context=[0|1]: enable (1) or disable (0) threads inheriting\n\ + context vars by default; enabled by default in the free-threaded\n\ + build and disabled otherwise; also PYTHON_THREAD_INHERIT_CONTEXT\n\ +" #ifdef Py_GIL_DISABLED "-X tlbc=[0|1]: enable (1) or disable (0) thread-local bytecode. Also\n\ PYTHON_TLBC\n" #endif "\ --X thread_inherit_context=[0|1]: enable (1) or disable (0) threads inheriting\n\ - context vars by default; enabled by default in the free-threaded\n\ - build and disabled otherwise; also PYTHON_THREAD_INHERIT_CONTEXT\n\ --X context_aware_warnings=[0|1]: if true (1) then the warnings module will\n\ - use a context variables; if false (0) then the warnings module will\n\ - use module globals, which is not concurrent-safe; set to true for\n\ - free-threaded builds and false otherwise; also\n\ - PYTHON_CONTEXT_AWARE_WARNINGS\n\ --X pathconfig_warnings=[0|1]: if true (1) then path configuration is allowed\n\ - to log warnings into stderr; if false (0) suppress these warnings;\n\ - set to true by default; also PYTHON_PATHCONFIG_WARNINGS\n\ --X tracemalloc[=N]: trace Python memory allocations; N sets a traceback limit\n \ +-X tracemalloc[=N]: trace Python memory allocations; N sets a traceback limit\n\ of N frames (default: 1); also PYTHONTRACEMALLOC=N\n\ -X utf8[=0|1]: enable (1) or disable (0) UTF-8 mode; also PYTHONUTF8\n\ -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None';\n\ From 83edae33a5591c52fa45df38da2616af470f290a Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Sun, 15 Mar 2026 15:22:57 -0700 Subject: [PATCH 145/775] gh-145990: sort `--help-env` sections by environment variable name (GH-145997) * sort --help-env alphabetically by name. * add a sorting regression test in test_help_env. --- Lib/test/test_cmd_line.py | 8 +++ ...-03-15-21-45-35.gh-issue-145990.tmXwRB.rst | 1 + Python/initconfig.c | 56 +++++++++---------- 3 files changed, 37 insertions(+), 28 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index c1dc5967789..5f035c35367 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -60,6 +60,14 @@ def test_help(self): def test_help_env(self): out = self.verify_valid_flag('--help-env') self.assertIn(b'PYTHONHOME', out) + # Env vars in each section should be sorted alphabetically + # (ignoring underscores so PYTHON_FOO and PYTHONFOO intermix naturally) + sort_key = lambda name: name.replace(b'_', b'').lower() + sections = out.split(b'These variables have equivalent') + for section in sections: + envvars = re.findall(rb'^(PYTHON\w+)', section, re.MULTILINE) + self.assertEqual(envvars, sorted(envvars, key=sort_key), + "env vars should be sorted alphabetically") @support.cpython_only def test_help_xoptions(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst new file mode 100644 index 00000000000..21b9a524d00 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst @@ -0,0 +1 @@ +``python --help-env`` sections are now sorted by environment variable name. diff --git a/Python/initconfig.c b/Python/initconfig.c index eff37fc32b4..caf42f5247c 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -371,34 +371,19 @@ The following implementation-specific options are available:\n\ /* Envvars that don't have equivalent command-line options are listed first */ static const char usage_envvars[] = "Environment variables that change behavior:\n" -"PYTHONSTARTUP : file executed on interactive startup (no default)\n" -"PYTHONPATH : '%lc'-separated list of directories prefixed to the\n" -" default module search path. The result is sys.path.\n" -"PYTHONHOME : alternate directory (or %lc).\n" -" The default module search path uses %s.\n" -"PYTHONPLATLIBDIR: override sys.platlibdir\n" +"PYTHONASYNCIODEBUG: enable asyncio debug mode\n" +"PYTHON_BASIC_REPL: use the traditional parser-based REPL\n" +"PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n" +" debugger. It can be set to the callable of your debugger of\n" +" choice.\n" "PYTHONCASEOK : ignore case in 'import' statements (Windows)\n" -"PYTHONIOENCODING: encoding[:errors] used for stdin/stdout/stderr\n" -"PYTHONHASHSEED : if this variable is set to 'random', a random value is used\n" -" to seed the hashes of str and bytes objects. It can also be\n" -" set to an integer in the range [0,4294967295] to get hash\n" -" values with a predictable seed.\n" -"PYTHONMALLOC : set the Python memory allocators and/or install debug hooks\n" -" on Python memory allocators. Use PYTHONMALLOC=debug to\n" -" install debug hooks.\n" -"PYTHONMALLOCSTATS: print memory allocator statistics\n" "PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n" " coercion behavior. Use PYTHONCOERCECLOCALE=warn to request\n" " display of locale coercion and locale compatibility warnings\n" " on stderr.\n" -"PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n" -" debugger. It can be set to the callable of your debugger of\n" -" choice.\n" "PYTHON_COLORS : if this variable is set to 1, the interpreter will colorize\n" " various kinds of output. Setting it to 0 deactivates\n" " this behavior.\n" -"PYTHON_HISTORY : the location of a .python_history file.\n" -"PYTHONASYNCIODEBUG: enable asyncio debug mode\n" #ifdef Py_TRACE_REFS "PYTHONDUMPREFS : dump objects and reference counts still alive after shutdown\n" "PYTHONDUMPREFSFILE: dump objects and reference counts to the specified file\n" @@ -406,14 +391,31 @@ static const char usage_envvars[] = #ifdef __APPLE__ "PYTHONEXECUTABLE: set sys.argv[0] to this value (macOS only)\n" #endif +"PYTHONHASHSEED : if this variable is set to 'random', a random value is used\n" +" to seed the hashes of str and bytes objects. It can also be\n" +" set to an integer in the range [0,4294967295] to get hash\n" +" values with a predictable seed.\n" +"PYTHON_HISTORY : the location of a .python_history file.\n" +"PYTHONHOME : alternate directory (or %lc).\n" +" The default module search path uses %s.\n" +"PYTHONIOENCODING: encoding[:errors] used for stdin/stdout/stderr\n" #ifdef MS_WINDOWS "PYTHONLEGACYWINDOWSFSENCODING: use legacy \"mbcs\" encoding for file system\n" "PYTHONLEGACYWINDOWSSTDIO: use legacy Windows stdio\n" #endif +"PYTHONMALLOC : set the Python memory allocators and/or install debug hooks\n" +" on Python memory allocators. Use PYTHONMALLOC=debug to\n" +" install debug hooks.\n" +"PYTHONMALLOCSTATS: print memory allocator statistics\n" +"PYTHONPATH : '%lc'-separated list of directories prefixed to the\n" +" default module search path. The result is sys.path.\n" +"PYTHONPLATLIBDIR: override sys.platlibdir\n" +"PYTHONSTARTUP : file executed on interactive startup (no default)\n" "PYTHONUSERBASE : defines the user base directory (site.USER_BASE)\n" -"PYTHON_BASIC_REPL: use the traditional parser-based REPL\n" "\n" "These variables have equivalent command-line options (see --help for details):\n" +"PYTHON_CONTEXT_AWARE_WARNINGS: if true (1), enable thread-safe warnings\n" +" module behaviour (-X context_aware_warnings)\n" "PYTHON_CPU_COUNT: override the return value of os.cpu_count() (-X cpu_count)\n" "PYTHONDEBUG : enable parser debug mode (-d)\n" "PYTHONDEVMODE : enable Python Development Mode (-X dev)\n" @@ -428,31 +430,29 @@ static const char usage_envvars[] = "PYTHONINSPECT : inspect interactively after running script (-i)\n" "PYTHONINTMAXSTRDIGITS: limit the size of int<->str conversions;\n" " 0 disables the limit (-X int_max_str_digits=N)\n" +"PYTHON_LAZY_IMPORTS: control global lazy imports (-X lazy_imports)\n" "PYTHONNODEBUGRANGES: don't include extra location information in code objects\n" " (-X no_debug_ranges)\n" "PYTHONNOUSERSITE: disable user site directory (-s)\n" "PYTHONOPTIMIZE : enable level 1 optimizations (-O)\n" -"PYTHONPERFSUPPORT: support the Linux \"perf\" profiler (-X perf)\n" "PYTHON_PERF_JIT_SUPPORT: enable Linux \"perf\" profiler support with JIT\n" " (-X perf_jit)\n" +"PYTHONPERFSUPPORT: support the Linux \"perf\" profiler (-X perf)\n" #ifdef Py_DEBUG "PYTHON_PRESITE: import this module before site (-X presite)\n" #endif "PYTHONPROFILEIMPORTTIME: show how long each import takes (-X importtime)\n" -"PYTHON_LAZY_IMPORTS: control global lazy imports (-X lazy_imports)\n" "PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files\n" " (-X pycache_prefix)\n" "PYTHONSAFEPATH : don't prepend a potentially unsafe path to sys.path.\n" #ifdef Py_STATS "PYTHONSTATS : turns on statistics gathering (-X pystats)\n" #endif +"PYTHON_THREAD_INHERIT_CONTEXT: if true (1), threads inherit context vars\n" +" (-X thread_inherit_context)\n" #ifdef Py_GIL_DISABLED "PYTHON_TLBC : when set to 0, disables thread-local bytecode (-X tlbc)\n" #endif -"PYTHON_THREAD_INHERIT_CONTEXT: if true (1), threads inherit context vars\n" -" (-X thread_inherit_context)\n" -"PYTHON_CONTEXT_AWARE_WARNINGS: if true (1), enable thread-safe warnings module\n" -" behaviour (-X context_aware_warnings)\n" "PYTHONTRACEMALLOC: trace Python memory allocations (-X tracemalloc)\n" "PYTHONUNBUFFERED: disable stdout/stderr buffering (-u)\n" "PYTHONUTF8 : control the UTF-8 mode (-X utf8)\n" @@ -2947,7 +2947,7 @@ config_usage(int error, const wchar_t* program) static void config_envvars_usage(void) { - printf(usage_envvars, (wint_t)DELIM, (wint_t)DELIM, PYTHONHOMEHELP); + printf(usage_envvars, (wint_t)DELIM, PYTHONHOMEHELP, (wint_t)DELIM); } static void From 40095d526bd8ddbabee0603c2b502ed6807e5f4d Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sun, 15 Mar 2026 23:54:20 +0000 Subject: [PATCH 146/775] Expand `fuzz_pycompile.dict` for new syntax --- .../dictionaries/fuzz_pycompile.dict | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict b/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict index c6a44d94628..d36f55a4090 100644 --- a/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict +++ b/Modules/_xxtestfuzz/dictionaries/fuzz_pycompile.dict @@ -52,7 +52,9 @@ # whitespace " " +"\\t" ":\\n " +"\\\n" # type signatures and functions "-> " @@ -88,6 +90,8 @@ # variable names "x" "y" +"_" +"*x" # strings "r'x'" @@ -98,12 +102,24 @@ "br\"x\"" +"u\"x\"" + "f'{x + 5}'" "f\"{x + 5}\"" +"f'{s!r}'" +"f'{s!s}'" +"f'{s!a}'" +"f'{x=}'" + +"t'{s + 5}'" +"t\"{s + 5}\"" +"tr's'" +"rt\"s\"" "'''" "\"\"\"" +"\\N" "\\u" "\\x" @@ -131,6 +147,7 @@ "while " "try: " "except " +"except* " "finally: " "with " "lambda " @@ -148,6 +165,10 @@ "in " "is " "class " +"match " +"case " +"type " +"lazy " # shebangs and encodings "#!" From ee5318025b0f9f4d30d9358627df68181e0d223f Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Sun, 15 Mar 2026 22:50:19 -0700 Subject: [PATCH 147/775] gh-140814: Fix freeze_support() setting start method as side effect (GH-144608) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit freeze_support() called get_start_method() without allow_none=True, which locked in the default start method context. This caused a subsequent set_start_method() call to raise "context has already been set". Use allow_none=True and accept None as a matching value, since spawn.freeze_support() independently detects spawned child processes. Test that freeze_support() does not lock in the default start method, which would prevent a subsequent set_start_method() call. Co-Authored-By: Claude Opus 4.6 Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/multiprocessing/context.py | 8 +++++++- Lib/test/_test_multiprocessing.py | 14 ++++++++++++++ .../2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index a73261cde85..e1d25145602 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -145,7 +145,13 @@ def freeze_support(self): '''Check whether this is a fake forked process in a frozen executable. If so then run code specified by commandline and exit. ''' - if self.get_start_method() == 'spawn' and getattr(sys, 'frozen', False): + # gh-140814: allow_none=True avoids locking in the default start + # method, which would cause a later set_start_method() to fail. + # None is safe to pass through: spawn.freeze_support() + # independently detects whether this process is a spawned + # child, so the start method check here is only an optimization. + if (getattr(sys, 'frozen', False) + and self.get_start_method(allow_none=True) in ('spawn', None)): from .spawn import freeze_support freeze_support() diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index d67fd13fa33..490c7ae5e80 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -6005,6 +6005,20 @@ def test_spawn_dont_set_context(self): process.join() self.assertIsNone(multiprocessing.get_start_method(allow_none=True)) + @only_run_in_spawn_testsuite("freeze_support is not start method specific") + def test_freeze_support_dont_set_context(self): + # gh-140814: freeze_support() should not set the start method + # as a side effect, so a later set_start_method() still works. + multiprocessing.set_start_method(None, force=True) + try: + multiprocessing.freeze_support() + self.assertIsNone( + multiprocessing.get_start_method(allow_none=True)) + # Should not raise "context has already been set" + multiprocessing.set_start_method('spawn') + finally: + multiprocessing.set_start_method(None, force=True) + def test_context_check_module_types(self): try: ctx = multiprocessing.get_context('forkserver') diff --git a/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst b/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst new file mode 100644 index 00000000000..6077de8ac9a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst @@ -0,0 +1,3 @@ +:func:`multiprocessing.freeze_support` no longer sets the default start method +as a side effect, which previously caused a subsequent +:func:`multiprocessing.set_start_method` call to raise :exc:`RuntimeError`. From 70397fd1030c310d4d80beeb9c0d88f40c9abed8 Mon Sep 17 00:00:00 2001 From: RayXu Date: Mon, 16 Mar 2026 16:21:49 +0800 Subject: [PATCH 148/775] Docs: fix a form error and a grammatical error in float.rst (#140989) --- Doc/c-api/float.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst index ca8d44c25c1..6e83e01344a 100644 --- a/Doc/c-api/float.rst +++ b/Doc/c-api/float.rst @@ -201,8 +201,8 @@ NaNs (if such things exist on the platform) isn't handled correctly, and attempting to unpack a bytes string containing an IEEE INF or NaN will raise an exception. -Note that NaNs type may not be preserved on IEEE platforms (signaling NaN become -quiet NaN), for example on x86 systems in 32-bit mode. +Note that NaN type may not be preserved on IEEE platforms (signaling NaNs become +quiet NaNs), for example on x86 systems in 32-bit mode. On non-IEEE platforms with more precision, or larger dynamic range, than IEEE 754 supports, not all values can be packed; on non-IEEE platforms with less @@ -216,7 +216,7 @@ Pack functions The pack routines write 2, 4 or 8 bytes, starting at *p*. *le* is an :c:expr:`int` argument, non-zero if you want the bytes string in little-endian -format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` ``p+7``), zero if you +format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` and ``p+7``), zero if you want big-endian format (exponent first, at *p*). The :c:macro:`PY_BIG_ENDIAN` constant can be used to use the native endian: it is equal to ``1`` on big endian processor, or ``0`` on little endian processor. From 6f8867a6765d3e6effdc09a22691830aa887c3d0 Mon Sep 17 00:00:00 2001 From: AN Long Date: Mon, 16 Mar 2026 17:29:55 +0900 Subject: [PATCH 149/775] gh-129849: Add tests for `Py_tp_bases` (#143208) --- Lib/test/test_capi/test_misc.py | 12 +++++++++ Modules/_testcapi/heaptype.c | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 3997acbdf84..db067199195 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -916,6 +916,18 @@ def genf(): yield gen = genf() self.assertEqual(_testcapi.gen_get_code(gen), gen.gi_code) + def test_tp_bases_slot(self): + cls = _testcapi.HeapCTypeWithBasesSlot + self.assertEqual(cls.__bases__, (int,)) + self.assertEqual(cls.__base__, int) + + def test_tp_bases_slot_none(self): + self.assertRaisesRegex( + SystemError, + "Py_tp_bases is not a tuple", + _testcapi.create_heapctype_with_none_bases_slot + ) + @requires_limited_api class TestHeapTypeRelative(unittest.TestCase): diff --git a/Modules/_testcapi/heaptype.c b/Modules/_testcapi/heaptype.c index 4fdcc850a33..eb9458a066f 100644 --- a/Modules/_testcapi/heaptype.c +++ b/Modules/_testcapi/heaptype.c @@ -543,6 +543,25 @@ pytype_getmodulebytoken(PyObject *self, PyObject *args) return PyType_GetModuleByToken((PyTypeObject *)type, token); } +static PyType_Slot HeapCTypeWithBasesSlotNone_slots[] = { + {Py_tp_bases, NULL}, /* filled out with Py_None in runtime */ + {0, 0}, +}; + +static PyType_Spec HeapCTypeWithBasesSlotNone_spec = { + .name = "_testcapi.HeapCTypeWithBasesSlotNone", + .basicsize = sizeof(PyObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = HeapCTypeWithBasesSlotNone_slots +}; + +static PyObject * +create_heapctype_with_none_bases_slot(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + HeapCTypeWithBasesSlotNone_slots[0].pfunc = Py_None; + return PyType_FromSpec(&HeapCTypeWithBasesSlotNone_spec); +} + static PyMethodDef TestMethods[] = { {"pytype_fromspec_meta", pytype_fromspec_meta, METH_O}, @@ -562,6 +581,8 @@ static PyMethodDef TestMethods[] = { {"pytype_getbasebytoken", pytype_getbasebytoken, METH_VARARGS}, {"pytype_getmodulebydef", pytype_getmodulebydef, METH_O}, {"pytype_getmodulebytoken", pytype_getmodulebytoken, METH_VARARGS}, + {"create_heapctype_with_none_bases_slot", + create_heapctype_with_none_bases_slot, METH_NOARGS}, {NULL}, }; @@ -892,6 +913,18 @@ static PyType_Spec HeapCTypeMetaclassNullNew_spec = { .slots = empty_type_slots }; +static PyType_Slot HeapCTypeWithBasesSlot_slots[] = { + {Py_tp_bases, NULL}, /* filled out in module init function */ + {0, 0}, +}; + +static PyType_Spec HeapCTypeWithBasesSlot_spec = { + .name = "_testcapi.HeapCTypeWithBasesSlot", + .basicsize = sizeof(PyLongObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = HeapCTypeWithBasesSlot_slots +}; + typedef struct { PyObject_HEAD @@ -1432,6 +1465,18 @@ _PyTestCapi_Init_Heaptype(PyObject *m) { &PyType_Type, m, &HeapCTypeMetaclassNullNew_spec, (PyObject *) &PyType_Type); ADD("HeapCTypeMetaclassNullNew", HeapCTypeMetaclassNullNew); + PyObject *bases = PyTuple_Pack(1, &PyLong_Type); + if (bases == NULL) { + return -1; + } + HeapCTypeWithBasesSlot_slots[0].pfunc = bases; + PyObject *HeapCTypeWithBasesSlot = PyType_FromSpec(&HeapCTypeWithBasesSlot_spec); + Py_DECREF(bases); + if (HeapCTypeWithBasesSlot == NULL) { + return -1; + } + ADD("HeapCTypeWithBasesSlot", HeapCTypeWithBasesSlot); + ADD("Py_TP_USE_SPEC", PyLong_FromVoidPtr(Py_TP_USE_SPEC)); PyObject *HeapCCollection = PyType_FromMetaclass( From 3a248564470075cb8c7b8a75fe7ba61f7ea341b2 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 16 Mar 2026 09:53:37 +0100 Subject: [PATCH 150/775] gh-123471: make concurrent iteration over itertools.accumulate thread-safe (#144486) --- Lib/test/test_free_threading/test_itertools.py | 9 ++++++++- .../2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst | 1 + Modules/itertoolsmodule.c | 12 +++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst diff --git a/Lib/test/test_free_threading/test_itertools.py b/Lib/test/test_free_threading/test_itertools.py index bb6047e8669..20135dd3165 100644 --- a/Lib/test/test_free_threading/test_itertools.py +++ b/Lib/test/test_free_threading/test_itertools.py @@ -1,5 +1,5 @@ import unittest -from itertools import batched, chain, combinations_with_replacement, cycle, permutations +from itertools import accumulate, batched, chain, combinations_with_replacement, cycle, permutations from test.support import threading_helper @@ -16,6 +16,13 @@ def work_iterator(it): class ItertoolsThreading(unittest.TestCase): + @threading_helper.reap_threads + def test_accumulate(self): + number_of_iterations = 10 + for _ in range(number_of_iterations): + it = accumulate(tuple(range(40))) + threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it]) + @threading_helper.reap_threads def test_batched(self): number_of_iterations = 10 diff --git a/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst b/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst new file mode 100644 index 00000000000..d650103e28e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst @@ -0,0 +1 @@ +Make concurrent iteration over :class:`itertools.accumulate` safe under free-threading. diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index bc25bf6bfc1..b37256c7928 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -3073,7 +3073,7 @@ accumulate_traverse(PyObject *op, visitproc visit, void *arg) } static PyObject * -accumulate_next(PyObject *op) +accumulate_next_lock_held(PyObject *op) { accumulateobject *lz = accumulateobject_CAST(op); PyObject *val, *newtotal; @@ -3105,6 +3105,16 @@ accumulate_next(PyObject *op) return newtotal; } +static PyObject * +accumulate_next(PyObject *op) +{ + PyObject *result; + Py_BEGIN_CRITICAL_SECTION(op); + result = accumulate_next_lock_held(op); + Py_END_CRITICAL_SECTION() + return result; +} + static PyType_Slot accumulate_slots[] = { {Py_tp_dealloc, accumulate_dealloc}, {Py_tp_getattro, PyObject_GenericGetAttr}, From e2e62033aa71508893eb2ffeec44432d80dc3739 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Mon, 16 Mar 2026 18:10:34 +0800 Subject: [PATCH 151/775] gh-139038: Link to Savannah's webpage for JIT results (#146013) --- Doc/whatsnew/3.15.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index c286e3fc4f2..d4c4483bc5e 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1286,11 +1286,11 @@ Upgraded JIT compiler Results from the `pyperformance `__ benchmark suite report -`4-5% `__ +`5-6% `__ geometric mean performance improvement for the JIT over the standard CPython interpreter built with all optimizations enabled on x86-64 Linux. On AArch64 macOS, the JIT has a -`7-8% `__ +`8-9% `__ speedup over the :ref:`tail calling interpreter ` with all optimizations enabled. The speedups for JIT builds versus no JIT builds range from roughly 15% slowdown to over From 36b5284f04b0a946a7d915bcd656534c9b4dbd85 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Mon, 16 Mar 2026 03:55:00 -0700 Subject: [PATCH 152/775] gh-145649: Fix man page text wrapping for -X option (#145656) Replace hardcoded space indentation with proper troff macros (.TP, .RS/.RE, .IP) for -X sub-options so text wraps correctly at any terminal width. Co-authored-by: Claude Opus 4.6 --- ...-03-09-00-00-00.gh-issue-145649.8BcbAB.rst | 2 + Misc/python.man | 175 ++++++++++-------- 2 files changed, 101 insertions(+), 76 deletions(-) create mode 100644 Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst diff --git a/Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst b/Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst new file mode 100644 index 00000000000..33061f7dd15 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst @@ -0,0 +1,2 @@ +Fix text wrapping and formatting of ``-X`` option descriptions in the +:manpage:`python(1)` man page by using proper roff markup. diff --git a/Misc/python.man b/Misc/python.man index 612e2bbf568..a65fb98a697 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -320,82 +320,105 @@ a regular expression on the warning message. .TP .BI "\-X " option Set implementation-specific option. The following options are available: - - \fB\-X cpu_count=\fIN\fR: override the return value of \fIos.cpu_count()\fR; - \fB\-X cpu_count=default\fR cancels overriding; also \fBPYTHON_CPU_COUNT\fI - - \fB\-X dev\fR: enable CPython's "development mode", introducing additional - runtime checks which are too expensive to be enabled by default. It - will not be more verbose than the default if the code is correct: new - warnings are only emitted when an issue is detected. Effect of the - developer mode: - * Add default warning filter, as \fB\-W default\fR - * Install debug hooks on memory allocators: see the - PyMem_SetupDebugHooks() C function - * Enable the faulthandler module to dump the Python traceback on a - crash - * Enable asyncio debug mode - * Set the dev_mode attribute of sys.flags to True - * io.IOBase destructor logs close() exceptions - - \fB\-X importtime\fR: show how long each import takes. It shows module name, - cumulative time (including nested imports) and self time (excluding - nested imports). Note that its output may be broken in multi-threaded - application. Typical usage is - \fBpython3 \-X importtime \-c 'import asyncio'\fR - - \fB\-X importtime=2\fR enables additional output that indicates when an - imported module has already been loaded. In such cases, the string - \fBcached\fR will be printed in both time columns. - - \fB\-X faulthandler\fR: enable faulthandler - - \fB\-X frozen_modules=\fR[\fBon\fR|\fBoff\fR]: whether or not frozen modules - should be used. - The default is "on" (or "off" if you are running a local build). - - \fB\-X gil=\fR[\fB0\fR|\fB1\fR]: enable (1) or disable (0) the GIL; also - \fBPYTHON_GIL\fR - Only available in builds configured with \fB\-\-disable\-gil\fR. - - \fB\-X int_max_str_digits=\fInumber\fR: limit the size of int<->str conversions. - This helps avoid denial of service attacks when parsing untrusted data. - The default is sys.int_info.default_max_str_digits. 0 disables. - - \fB\-X no_debug_ranges\fR: disable the inclusion of the tables mapping extra - location information (end line, start column offset and end column - offset) to every instruction in code objects. This is useful when - smaller code objects and pyc files are desired as well as suppressing - the extra visual location indicators when the interpreter displays - tracebacks. - - \fB\-X perf\fR: support the Linux "perf" profiler; also \fBPYTHONPERFSUPPORT=1\fR - - \fB\-X perf_jit\fR: support the Linux "perf" profiler with DWARF support; - also \fBPYTHON_PERF_JIT_SUPPORT=1\fR - - \fB\-X presite=\fIMOD\fR: import this module before site; also \fBPYTHON_PRESITE\fR - This only works on debug builds. - - \fB\-X pycache_prefix=\fIPATH\fR: enable writing .pyc files to a parallel - tree rooted at the given directory instead of to the code tree. - - \fB\-X showrefcount\fR: output the total reference count and number of used - memory blocks when the program finishes or after each statement in the - interactive interpreter. This only works on debug builds - - \fB\-X tracemalloc\fR: start tracing Python memory allocations using the - tracemalloc module. By default, only the most recent frame is stored in a - traceback of a trace. Use \-X tracemalloc=NFRAME to start tracing with a - traceback limit of NFRAME frames - - \fB\-X utf8\fR: enable UTF-8 mode for operating system interfaces, - overriding the default locale-aware mode. \fB\-X utf8=0\fR explicitly - disables UTF-8 mode (even when it would otherwise activate - automatically). See \fBPYTHONUTF8\fR for more details - - \fB\-X warn_default_encoding\fR: enable opt-in EncodingWarning for 'encoding=None' - +.RS +.TP +\fB\-X cpu_count=\fIN\fR +Override the return value of \fIos.cpu_count()\fR. +\fB\-X cpu_count=default\fR cancels overriding. +See also \fBPYTHON_CPU_COUNT\fR. +.TP +\fB\-X dev\fR +Enable CPython's "development mode", introducing additional +runtime checks which are too expensive to be enabled by default. It +will not be more verbose than the default if the code is correct: new +warnings are only emitted when an issue is detected. Effect of the +developer mode: +.RS +.IP \(bu 2 +Add default warning filter, as \fB\-W default\fR. +.IP \(bu 2 +Install debug hooks on memory allocators: see the +PyMem_SetupDebugHooks() C function. +.IP \(bu 2 +Enable the faulthandler module to dump the Python traceback on a crash. +.IP \(bu 2 +Enable asyncio debug mode. +.IP \(bu 2 +Set the dev_mode attribute of sys.flags to True. +.IP \(bu 2 +io.IOBase destructor logs close() exceptions. +.RE +.TP +\fB\-X importtime\fR +Show how long each import takes. It shows module name, +cumulative time (including nested imports) and self time (excluding +nested imports). Note that its output may be broken in multi-threaded +application. Typical usage is +\fBpython3 \-X importtime \-c 'import asyncio'\fR. +.IP +\fB\-X importtime=2\fR enables additional output that indicates when an +imported module has already been loaded. In such cases, the string +\fBcached\fR will be printed in both time columns. +.TP +\fB\-X faulthandler\fR +Enable faulthandler. +.TP +\fB\-X frozen_modules=\fR[\fBon\fR|\fBoff\fR] +Whether or not frozen modules should be used. +The default is "on" (or "off" if you are running a local build). +.TP +\fB\-X gil=\fR[\fB0\fR|\fB1\fR] +Enable (1) or disable (0) the GIL. See also \fBPYTHON_GIL\fR. +Only available in builds configured with \fB\-\-disable\-gil\fR. +.TP +\fB\-X int_max_str_digits=\fInumber\fR +Limit the size of int<->str conversions. +This helps avoid denial of service attacks when parsing untrusted data. +The default is sys.int_info.default_max_str_digits. 0 disables. +.TP +\fB\-X no_debug_ranges\fR +Disable the inclusion of the tables mapping extra +location information (end line, start column offset and end column +offset) to every instruction in code objects. This is useful when +smaller code objects and pyc files are desired as well as suppressing +the extra visual location indicators when the interpreter displays +tracebacks. +.TP +\fB\-X perf\fR +Support the Linux "perf" profiler. See also \fBPYTHONPERFSUPPORT=1\fR. +.TP +\fB\-X perf_jit\fR +Support the Linux "perf" profiler with DWARF support. +See also \fBPYTHON_PERF_JIT_SUPPORT=1\fR. +.TP +\fB\-X presite=\fIMOD\fR +Import this module before site. See also \fBPYTHON_PRESITE\fR. +This only works on debug builds. +.TP +\fB\-X pycache_prefix=\fIPATH\fR +Enable writing .pyc files to a parallel +tree rooted at the given directory instead of to the code tree. +.TP +\fB\-X showrefcount\fR +Output the total reference count and number of used +memory blocks when the program finishes or after each statement in the +interactive interpreter. This only works on debug builds. +.TP +\fB\-X tracemalloc\fR +Start tracing Python memory allocations using the +tracemalloc module. By default, only the most recent frame is stored in a +traceback of a trace. Use \fB\-X tracemalloc=\fINFRAME\fR to start tracing with a +traceback limit of NFRAME frames. +.TP +\fB\-X utf8\fR +Enable UTF-8 mode for operating system interfaces, +overriding the default locale-aware mode. \fB\-X utf8=0\fR explicitly +disables UTF-8 mode (even when it would otherwise activate +automatically). See \fBPYTHONUTF8\fR for more details. +.TP +\fB\-X warn_default_encoding\fR +Enable opt-in EncodingWarning for 'encoding=None'. +.RE .TP .B \-x Skip the first line of the source. This is intended for a DOS From 37121ef77ee54bd5bf12582392ecf55afa80f366 Mon Sep 17 00:00:00 2001 From: Sacul <183588943+Sacul0457@users.noreply.github.com> Date: Mon, 16 Mar 2026 19:58:12 +0800 Subject: [PATCH 153/775] gh-145866: Convert `CALL_INTRINSIC_1` to leave its inputs on the stack to be cleaned up by `_POP_TOP`. (GH-145964) --- Include/internal/pycore_opcode_metadata.h | 4 +- Include/internal/pycore_uop_ids.h | 2332 ++++++++++----------- Include/internal/pycore_uop_metadata.h | 8 +- Lib/test/test_capi/test_opt.py | 15 + Modules/_testinternalcapi/test_cases.c.h | 37 +- Python/bytecodes.c | 11 +- Python/executor_cases.c.h | 15 +- Python/generated_cases.c.h | 37 +- Python/optimizer_bytecodes.c | 5 + Python/optimizer_cases.c.h | 8 + 10 files changed, 1257 insertions(+), 1215 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index c64d4e8ba85..fc5689c5afe 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1130,7 +1130,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [CALL_EX_NON_PY_GENERAL] = { true, INSTR_FMT_IXC, HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_EX_PY] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [CALL_FUNCTION_EX] = { true, INSTR_FMT_IXC, HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_ISINSTANCE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CALL_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, @@ -1380,7 +1380,7 @@ _PyOpcode_macro_expansion[256] = { [CALL_BUILTIN_O] = { .nuops = 5, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CALL_BUILTIN_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_EX_NON_PY_GENERAL] = { .nuops = 4, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_EX, OPARG_SIMPLE, 1 }, { _MAKE_CALLARGS_A_TUPLE, OPARG_SIMPLE, 1 }, { _CALL_FUNCTION_EX_NON_PY_GENERAL, OPARG_SIMPLE, 1 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 1 } } }, [CALL_EX_PY] = { .nuops = 7, .uops = { { _RECORD_4OS, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _MAKE_CALLARGS_A_TUPLE, OPARG_SIMPLE, 1 }, { _CHECK_IS_PY_CALLABLE_EX, OPARG_SIMPLE, 1 }, { _PY_FRAME_EX, OPARG_SIMPLE, 1 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, - [CALL_INTRINSIC_1] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_1, OPARG_SIMPLE, 0 } } }, + [CALL_INTRINSIC_1] = { .nuops = 2, .uops = { { _CALL_INTRINSIC_1, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [CALL_INTRINSIC_2] = { .nuops = 1, .uops = { { _CALL_INTRINSIC_2, OPARG_SIMPLE, 0 } } }, [CALL_ISINSTANCE] = { .nuops = 3, .uops = { { _GUARD_THIRD_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_ISINSTANCE, OPARG_SIMPLE, 3 }, { _CALL_ISINSTANCE, OPARG_SIMPLE, 3 } } }, [CALL_KW_BOUND_METHOD] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 0fdeb56122e..451c0dd5732 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -43,167 +43,167 @@ extern "C" { #define _CALL_BUILTIN_FAST_WITH_KEYWORDS 323 #define _CALL_BUILTIN_O 324 #define _CALL_FUNCTION_EX_NON_PY_GENERAL 325 -#define _CALL_INTRINSIC_1 CALL_INTRINSIC_1 +#define _CALL_INTRINSIC_1 326 #define _CALL_INTRINSIC_2 CALL_INTRINSIC_2 -#define _CALL_ISINSTANCE 326 -#define _CALL_KW_NON_PY 327 -#define _CALL_LEN 328 -#define _CALL_LIST_APPEND 329 -#define _CALL_METHOD_DESCRIPTOR_FAST 330 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 331 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 332 -#define _CALL_METHOD_DESCRIPTOR_O 333 -#define _CALL_NON_PY_GENERAL 334 -#define _CALL_STR_1 335 -#define _CALL_TUPLE_1 336 -#define _CALL_TYPE_1 337 -#define _CHECK_AND_ALLOCATE_OBJECT 338 -#define _CHECK_ATTR_CLASS 339 -#define _CHECK_ATTR_METHOD_LAZY_DICT 340 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 341 +#define _CALL_ISINSTANCE 327 +#define _CALL_KW_NON_PY 328 +#define _CALL_LEN 329 +#define _CALL_LIST_APPEND 330 +#define _CALL_METHOD_DESCRIPTOR_FAST 331 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 332 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 333 +#define _CALL_METHOD_DESCRIPTOR_O 334 +#define _CALL_NON_PY_GENERAL 335 +#define _CALL_STR_1 336 +#define _CALL_TUPLE_1 337 +#define _CALL_TYPE_1 338 +#define _CHECK_AND_ALLOCATE_OBJECT 339 +#define _CHECK_ATTR_CLASS 340 +#define _CHECK_ATTR_METHOD_LAZY_DICT 341 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 342 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION_EXACT_ARGS 342 -#define _CHECK_FUNCTION_VERSION 343 -#define _CHECK_FUNCTION_VERSION_INLINE 344 -#define _CHECK_FUNCTION_VERSION_KW 345 -#define _CHECK_IS_NOT_PY_CALLABLE 346 -#define _CHECK_IS_NOT_PY_CALLABLE_EX 347 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 348 -#define _CHECK_IS_PY_CALLABLE_EX 349 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 350 -#define _CHECK_METHOD_VERSION 351 -#define _CHECK_METHOD_VERSION_KW 352 -#define _CHECK_PEP_523 353 -#define _CHECK_PERIODIC 354 -#define _CHECK_PERIODIC_AT_END 355 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 356 -#define _CHECK_RECURSION_REMAINING 357 -#define _CHECK_STACK_SPACE 358 -#define _CHECK_STACK_SPACE_OPERAND 359 -#define _CHECK_VALIDITY 360 -#define _COLD_DYNAMIC_EXIT 361 -#define _COLD_EXIT 362 -#define _COMPARE_OP 363 -#define _COMPARE_OP_FLOAT 364 -#define _COMPARE_OP_INT 365 -#define _COMPARE_OP_STR 366 -#define _CONTAINS_OP 367 -#define _CONTAINS_OP_DICT 368 -#define _CONTAINS_OP_SET 369 +#define _CHECK_FUNCTION_EXACT_ARGS 343 +#define _CHECK_FUNCTION_VERSION 344 +#define _CHECK_FUNCTION_VERSION_INLINE 345 +#define _CHECK_FUNCTION_VERSION_KW 346 +#define _CHECK_IS_NOT_PY_CALLABLE 347 +#define _CHECK_IS_NOT_PY_CALLABLE_EX 348 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 349 +#define _CHECK_IS_PY_CALLABLE_EX 350 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 351 +#define _CHECK_METHOD_VERSION 352 +#define _CHECK_METHOD_VERSION_KW 353 +#define _CHECK_PEP_523 354 +#define _CHECK_PERIODIC 355 +#define _CHECK_PERIODIC_AT_END 356 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 357 +#define _CHECK_RECURSION_REMAINING 358 +#define _CHECK_STACK_SPACE 359 +#define _CHECK_STACK_SPACE_OPERAND 360 +#define _CHECK_VALIDITY 361 +#define _COLD_DYNAMIC_EXIT 362 +#define _COLD_EXIT 363 +#define _COMPARE_OP 364 +#define _COMPARE_OP_FLOAT 365 +#define _COMPARE_OP_INT 366 +#define _COMPARE_OP_STR 367 +#define _CONTAINS_OP 368 +#define _CONTAINS_OP_DICT 369 +#define _CONTAINS_OP_SET 370 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 370 -#define _COPY_1 371 -#define _COPY_2 372 -#define _COPY_3 373 +#define _COPY 371 +#define _COPY_1 372 +#define _COPY_2 373 +#define _COPY_3 374 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 374 +#define _CREATE_INIT_FRAME 375 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 375 +#define _DEOPT 376 #define _DICT_MERGE DICT_MERGE #define _DICT_UPDATE DICT_UPDATE -#define _DO_CALL 376 -#define _DO_CALL_FUNCTION_EX 377 -#define _DO_CALL_KW 378 -#define _DYNAMIC_EXIT 379 +#define _DO_CALL 377 +#define _DO_CALL_FUNCTION_EX 378 +#define _DO_CALL_KW 379 +#define _DYNAMIC_EXIT 380 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 380 +#define _ERROR_POP_N 381 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 381 -#define _EXPAND_METHOD_KW 382 -#define _FATAL_ERROR 383 +#define _EXPAND_METHOD 382 +#define _EXPAND_METHOD_KW 383 +#define _FATAL_ERROR 384 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 384 -#define _FOR_ITER_GEN_FRAME 385 -#define _FOR_ITER_TIER_TWO 386 +#define _FOR_ITER 385 +#define _FOR_ITER_GEN_FRAME 386 +#define _FOR_ITER_TIER_TWO 387 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER -#define _GUARD_BINARY_OP_EXTEND 387 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 388 -#define _GUARD_BIT_IS_SET_POP 389 -#define _GUARD_BIT_IS_SET_POP_4 390 -#define _GUARD_BIT_IS_SET_POP_5 391 -#define _GUARD_BIT_IS_SET_POP_6 392 -#define _GUARD_BIT_IS_SET_POP_7 393 -#define _GUARD_BIT_IS_UNSET_POP 394 -#define _GUARD_BIT_IS_UNSET_POP_4 395 -#define _GUARD_BIT_IS_UNSET_POP_5 396 -#define _GUARD_BIT_IS_UNSET_POP_6 397 -#define _GUARD_BIT_IS_UNSET_POP_7 398 -#define _GUARD_CALLABLE_ISINSTANCE 399 -#define _GUARD_CALLABLE_LEN 400 -#define _GUARD_CALLABLE_LIST_APPEND 401 -#define _GUARD_CALLABLE_STR_1 402 -#define _GUARD_CALLABLE_TUPLE_1 403 -#define _GUARD_CALLABLE_TYPE_1 404 -#define _GUARD_CODE_VERSION 405 -#define _GUARD_DORV_NO_DICT 406 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 407 -#define _GUARD_GLOBALS_VERSION 408 -#define _GUARD_IP_RETURN_GENERATOR 409 -#define _GUARD_IP_RETURN_VALUE 410 -#define _GUARD_IP_YIELD_VALUE 411 -#define _GUARD_IP__PUSH_FRAME 412 -#define _GUARD_IS_FALSE_POP 413 -#define _GUARD_IS_NONE_POP 414 -#define _GUARD_IS_NOT_NONE_POP 415 -#define _GUARD_IS_TRUE_POP 416 -#define _GUARD_KEYS_VERSION 417 -#define _GUARD_NOS_ANY_DICT 418 -#define _GUARD_NOS_COMPACT_ASCII 419 -#define _GUARD_NOS_DICT 420 -#define _GUARD_NOS_FLOAT 421 -#define _GUARD_NOS_INT 422 -#define _GUARD_NOS_LIST 423 -#define _GUARD_NOS_NOT_NULL 424 -#define _GUARD_NOS_NULL 425 -#define _GUARD_NOS_OVERFLOWED 426 -#define _GUARD_NOS_TUPLE 427 -#define _GUARD_NOS_UNICODE 428 -#define _GUARD_NOT_EXHAUSTED_LIST 429 -#define _GUARD_NOT_EXHAUSTED_RANGE 430 -#define _GUARD_NOT_EXHAUSTED_TUPLE 431 -#define _GUARD_THIRD_NULL 432 -#define _GUARD_TOS_ANY_DICT 433 -#define _GUARD_TOS_ANY_SET 434 -#define _GUARD_TOS_DICT 435 -#define _GUARD_TOS_FLOAT 436 -#define _GUARD_TOS_FROZENDICT 437 -#define _GUARD_TOS_FROZENSET 438 -#define _GUARD_TOS_INT 439 -#define _GUARD_TOS_LIST 440 -#define _GUARD_TOS_OVERFLOWED 441 -#define _GUARD_TOS_SET 442 -#define _GUARD_TOS_SLICE 443 -#define _GUARD_TOS_TUPLE 444 -#define _GUARD_TOS_UNICODE 445 -#define _GUARD_TYPE_VERSION 446 -#define _GUARD_TYPE_VERSION_LOCKED 447 -#define _HANDLE_PENDING_AND_DEOPT 448 +#define _GUARD_BINARY_OP_EXTEND 388 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 389 +#define _GUARD_BIT_IS_SET_POP 390 +#define _GUARD_BIT_IS_SET_POP_4 391 +#define _GUARD_BIT_IS_SET_POP_5 392 +#define _GUARD_BIT_IS_SET_POP_6 393 +#define _GUARD_BIT_IS_SET_POP_7 394 +#define _GUARD_BIT_IS_UNSET_POP 395 +#define _GUARD_BIT_IS_UNSET_POP_4 396 +#define _GUARD_BIT_IS_UNSET_POP_5 397 +#define _GUARD_BIT_IS_UNSET_POP_6 398 +#define _GUARD_BIT_IS_UNSET_POP_7 399 +#define _GUARD_CALLABLE_ISINSTANCE 400 +#define _GUARD_CALLABLE_LEN 401 +#define _GUARD_CALLABLE_LIST_APPEND 402 +#define _GUARD_CALLABLE_STR_1 403 +#define _GUARD_CALLABLE_TUPLE_1 404 +#define _GUARD_CALLABLE_TYPE_1 405 +#define _GUARD_CODE_VERSION 406 +#define _GUARD_DORV_NO_DICT 407 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 408 +#define _GUARD_GLOBALS_VERSION 409 +#define _GUARD_IP_RETURN_GENERATOR 410 +#define _GUARD_IP_RETURN_VALUE 411 +#define _GUARD_IP_YIELD_VALUE 412 +#define _GUARD_IP__PUSH_FRAME 413 +#define _GUARD_IS_FALSE_POP 414 +#define _GUARD_IS_NONE_POP 415 +#define _GUARD_IS_NOT_NONE_POP 416 +#define _GUARD_IS_TRUE_POP 417 +#define _GUARD_KEYS_VERSION 418 +#define _GUARD_NOS_ANY_DICT 419 +#define _GUARD_NOS_COMPACT_ASCII 420 +#define _GUARD_NOS_DICT 421 +#define _GUARD_NOS_FLOAT 422 +#define _GUARD_NOS_INT 423 +#define _GUARD_NOS_LIST 424 +#define _GUARD_NOS_NOT_NULL 425 +#define _GUARD_NOS_NULL 426 +#define _GUARD_NOS_OVERFLOWED 427 +#define _GUARD_NOS_TUPLE 428 +#define _GUARD_NOS_UNICODE 429 +#define _GUARD_NOT_EXHAUSTED_LIST 430 +#define _GUARD_NOT_EXHAUSTED_RANGE 431 +#define _GUARD_NOT_EXHAUSTED_TUPLE 432 +#define _GUARD_THIRD_NULL 433 +#define _GUARD_TOS_ANY_DICT 434 +#define _GUARD_TOS_ANY_SET 435 +#define _GUARD_TOS_DICT 436 +#define _GUARD_TOS_FLOAT 437 +#define _GUARD_TOS_FROZENDICT 438 +#define _GUARD_TOS_FROZENSET 439 +#define _GUARD_TOS_INT 440 +#define _GUARD_TOS_LIST 441 +#define _GUARD_TOS_OVERFLOWED 442 +#define _GUARD_TOS_SET 443 +#define _GUARD_TOS_SLICE 444 +#define _GUARD_TOS_TUPLE 445 +#define _GUARD_TOS_UNICODE 446 +#define _GUARD_TYPE_VERSION 447 +#define _GUARD_TYPE_VERSION_LOCKED 448 +#define _HANDLE_PENDING_AND_DEOPT 449 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 449 -#define _INIT_CALL_PY_EXACT_ARGS 450 -#define _INIT_CALL_PY_EXACT_ARGS_0 451 -#define _INIT_CALL_PY_EXACT_ARGS_1 452 -#define _INIT_CALL_PY_EXACT_ARGS_2 453 -#define _INIT_CALL_PY_EXACT_ARGS_3 454 -#define _INIT_CALL_PY_EXACT_ARGS_4 455 -#define _INSERT_1_LOAD_CONST_INLINE 456 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 457 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 458 -#define _INSERT_NULL 459 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 450 +#define _INIT_CALL_PY_EXACT_ARGS 451 +#define _INIT_CALL_PY_EXACT_ARGS_0 452 +#define _INIT_CALL_PY_EXACT_ARGS_1 453 +#define _INIT_CALL_PY_EXACT_ARGS_2 454 +#define _INIT_CALL_PY_EXACT_ARGS_3 455 +#define _INIT_CALL_PY_EXACT_ARGS_4 456 +#define _INSERT_1_LOAD_CONST_INLINE 457 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW 458 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW 459 +#define _INSERT_NULL 460 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -213,1080 +213,1080 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 460 -#define _IS_OP 461 -#define _ITER_CHECK_LIST 462 -#define _ITER_CHECK_RANGE 463 -#define _ITER_CHECK_TUPLE 464 -#define _ITER_JUMP_LIST 465 -#define _ITER_JUMP_RANGE 466 -#define _ITER_JUMP_TUPLE 467 -#define _ITER_NEXT_LIST 468 -#define _ITER_NEXT_LIST_TIER_TWO 469 -#define _ITER_NEXT_RANGE 470 -#define _ITER_NEXT_TUPLE 471 +#define _IS_NONE 461 +#define _IS_OP 462 +#define _ITER_CHECK_LIST 463 +#define _ITER_CHECK_RANGE 464 +#define _ITER_CHECK_TUPLE 465 +#define _ITER_JUMP_LIST 466 +#define _ITER_JUMP_RANGE 467 +#define _ITER_JUMP_TUPLE 468 +#define _ITER_NEXT_LIST 469 +#define _ITER_NEXT_LIST_TIER_TWO 470 +#define _ITER_NEXT_RANGE 471 +#define _ITER_NEXT_TUPLE 472 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 472 +#define _JUMP_TO_TOP 473 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 473 -#define _LOAD_ATTR_CLASS 474 +#define _LOAD_ATTR 474 +#define _LOAD_ATTR_CLASS 475 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 475 -#define _LOAD_ATTR_METHOD_LAZY_DICT 476 -#define _LOAD_ATTR_METHOD_NO_DICT 477 -#define _LOAD_ATTR_METHOD_WITH_VALUES 478 -#define _LOAD_ATTR_MODULE 479 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 480 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 481 -#define _LOAD_ATTR_PROPERTY_FRAME 482 -#define _LOAD_ATTR_SLOT 483 -#define _LOAD_ATTR_WITH_HINT 484 +#define _LOAD_ATTR_INSTANCE_VALUE 476 +#define _LOAD_ATTR_METHOD_LAZY_DICT 477 +#define _LOAD_ATTR_METHOD_NO_DICT 478 +#define _LOAD_ATTR_METHOD_WITH_VALUES 479 +#define _LOAD_ATTR_MODULE 480 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 481 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 482 +#define _LOAD_ATTR_PROPERTY_FRAME 483 +#define _LOAD_ATTR_SLOT 484 +#define _LOAD_ATTR_WITH_HINT 485 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 485 +#define _LOAD_BYTECODE 486 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 486 -#define _LOAD_CONST_INLINE_BORROW 487 -#define _LOAD_CONST_UNDER_INLINE 488 -#define _LOAD_CONST_UNDER_INLINE_BORROW 489 +#define _LOAD_CONST_INLINE 487 +#define _LOAD_CONST_INLINE_BORROW 488 +#define _LOAD_CONST_UNDER_INLINE 489 +#define _LOAD_CONST_UNDER_INLINE_BORROW 490 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 490 -#define _LOAD_FAST_0 491 -#define _LOAD_FAST_1 492 -#define _LOAD_FAST_2 493 -#define _LOAD_FAST_3 494 -#define _LOAD_FAST_4 495 -#define _LOAD_FAST_5 496 -#define _LOAD_FAST_6 497 -#define _LOAD_FAST_7 498 +#define _LOAD_FAST 491 +#define _LOAD_FAST_0 492 +#define _LOAD_FAST_1 493 +#define _LOAD_FAST_2 494 +#define _LOAD_FAST_3 495 +#define _LOAD_FAST_4 496 +#define _LOAD_FAST_5 497 +#define _LOAD_FAST_6 498 +#define _LOAD_FAST_7 499 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 499 -#define _LOAD_FAST_BORROW_0 500 -#define _LOAD_FAST_BORROW_1 501 -#define _LOAD_FAST_BORROW_2 502 -#define _LOAD_FAST_BORROW_3 503 -#define _LOAD_FAST_BORROW_4 504 -#define _LOAD_FAST_BORROW_5 505 -#define _LOAD_FAST_BORROW_6 506 -#define _LOAD_FAST_BORROW_7 507 +#define _LOAD_FAST_BORROW 500 +#define _LOAD_FAST_BORROW_0 501 +#define _LOAD_FAST_BORROW_1 502 +#define _LOAD_FAST_BORROW_2 503 +#define _LOAD_FAST_BORROW_3 504 +#define _LOAD_FAST_BORROW_4 505 +#define _LOAD_FAST_BORROW_5 506 +#define _LOAD_FAST_BORROW_6 507 +#define _LOAD_FAST_BORROW_7 508 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 508 -#define _LOAD_GLOBAL_BUILTINS 509 -#define _LOAD_GLOBAL_MODULE 510 +#define _LOAD_GLOBAL 509 +#define _LOAD_GLOBAL_BUILTINS 510 +#define _LOAD_GLOBAL_MODULE 511 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 511 -#define _LOAD_SMALL_INT_0 512 -#define _LOAD_SMALL_INT_1 513 -#define _LOAD_SMALL_INT_2 514 -#define _LOAD_SMALL_INT_3 515 -#define _LOAD_SPECIAL 516 +#define _LOAD_SMALL_INT 512 +#define _LOAD_SMALL_INT_0 513 +#define _LOAD_SMALL_INT_1 514 +#define _LOAD_SMALL_INT_2 515 +#define _LOAD_SMALL_INT_3 516 +#define _LOAD_SPECIAL 517 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _LOCK_OBJECT 517 -#define _MAKE_CALLARGS_A_TUPLE 518 +#define _LOCK_OBJECT 518 +#define _MAKE_CALLARGS_A_TUPLE 519 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_HEAP_SAFE 519 -#define _MAKE_WARM 520 +#define _MAKE_HEAP_SAFE 520 +#define _MAKE_WARM 521 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 521 +#define _MATCH_CLASS 522 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 522 -#define _MAYBE_EXPAND_METHOD_KW 523 -#define _MONITOR_CALL 524 -#define _MONITOR_CALL_KW 525 -#define _MONITOR_JUMP_BACKWARD 526 -#define _MONITOR_RESUME 527 +#define _MAYBE_EXPAND_METHOD 523 +#define _MAYBE_EXPAND_METHOD_KW 524 +#define _MONITOR_CALL 525 +#define _MONITOR_CALL_KW 526 +#define _MONITOR_JUMP_BACKWARD 527 +#define _MONITOR_RESUME 528 #define _NOP NOP -#define _POP_CALL 528 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 529 -#define _POP_CALL_ONE 530 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 531 -#define _POP_CALL_TWO 532 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 533 +#define _POP_CALL 529 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 530 +#define _POP_CALL_ONE 531 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 532 +#define _POP_CALL_TWO 533 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 534 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 534 -#define _POP_JUMP_IF_TRUE 535 +#define _POP_JUMP_IF_FALSE 535 +#define _POP_JUMP_IF_TRUE 536 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 536 -#define _POP_TOP_INT 537 -#define _POP_TOP_LOAD_CONST_INLINE 538 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 539 -#define _POP_TOP_NOP 540 -#define _POP_TOP_UNICODE 541 -#define _POP_TWO 542 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 543 +#define _POP_TOP_FLOAT 537 +#define _POP_TOP_INT 538 +#define _POP_TOP_LOAD_CONST_INLINE 539 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 540 +#define _POP_TOP_NOP 541 +#define _POP_TOP_UNICODE 542 +#define _POP_TWO 543 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 544 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 544 +#define _PUSH_FRAME 545 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 545 -#define _PY_FRAME_EX 546 -#define _PY_FRAME_GENERAL 547 -#define _PY_FRAME_KW 548 -#define _QUICKEN_RESUME 549 -#define _RECORD_4OS 550 -#define _RECORD_BOUND_METHOD 551 -#define _RECORD_CALLABLE 552 -#define _RECORD_CODE 553 -#define _RECORD_NOS 554 -#define _RECORD_NOS_GEN_FUNC 555 -#define _RECORD_TOS 556 -#define _RECORD_TOS_TYPE 557 -#define _REPLACE_WITH_TRUE 558 +#define _PUSH_NULL_CONDITIONAL 546 +#define _PY_FRAME_EX 547 +#define _PY_FRAME_GENERAL 548 +#define _PY_FRAME_KW 549 +#define _QUICKEN_RESUME 550 +#define _RECORD_4OS 551 +#define _RECORD_BOUND_METHOD 552 +#define _RECORD_CALLABLE 553 +#define _RECORD_CODE 554 +#define _RECORD_NOS 555 +#define _RECORD_NOS_GEN_FUNC 556 +#define _RECORD_TOS 557 +#define _RECORD_TOS_TYPE 558 +#define _REPLACE_WITH_TRUE 559 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 559 -#define _SAVE_RETURN_OFFSET 560 -#define _SEND 561 -#define _SEND_GEN_FRAME 562 +#define _RETURN_VALUE 560 +#define _SAVE_RETURN_OFFSET 561 +#define _SEND 562 +#define _SEND_GEN_FRAME 563 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 563 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 564 -#define _SPILL_OR_RELOAD 565 -#define _START_EXECUTOR 566 -#define _STORE_ATTR 567 -#define _STORE_ATTR_INSTANCE_VALUE 568 -#define _STORE_ATTR_SLOT 569 -#define _STORE_ATTR_WITH_HINT 570 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 564 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 565 +#define _SPILL_OR_RELOAD 566 +#define _START_EXECUTOR 567 +#define _STORE_ATTR 568 +#define _STORE_ATTR_INSTANCE_VALUE 569 +#define _STORE_ATTR_SLOT 570 +#define _STORE_ATTR_WITH_HINT 571 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 571 -#define _STORE_SUBSCR 572 -#define _STORE_SUBSCR_DICT 573 -#define _STORE_SUBSCR_LIST_INT 574 -#define _SWAP 575 -#define _SWAP_2 576 -#define _SWAP_3 577 -#define _SWAP_FAST 578 -#define _SWAP_FAST_0 579 -#define _SWAP_FAST_1 580 -#define _SWAP_FAST_2 581 -#define _SWAP_FAST_3 582 -#define _SWAP_FAST_4 583 -#define _SWAP_FAST_5 584 -#define _SWAP_FAST_6 585 -#define _SWAP_FAST_7 586 -#define _TIER2_RESUME_CHECK 587 -#define _TO_BOOL 588 +#define _STORE_SLICE 572 +#define _STORE_SUBSCR 573 +#define _STORE_SUBSCR_DICT 574 +#define _STORE_SUBSCR_LIST_INT 575 +#define _SWAP 576 +#define _SWAP_2 577 +#define _SWAP_3 578 +#define _SWAP_FAST 579 +#define _SWAP_FAST_0 580 +#define _SWAP_FAST_1 581 +#define _SWAP_FAST_2 582 +#define _SWAP_FAST_3 583 +#define _SWAP_FAST_4 584 +#define _SWAP_FAST_5 585 +#define _SWAP_FAST_6 586 +#define _SWAP_FAST_7 587 +#define _TIER2_RESUME_CHECK 588 +#define _TO_BOOL 589 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 589 -#define _TO_BOOL_LIST 590 +#define _TO_BOOL_INT 590 +#define _TO_BOOL_LIST 591 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 591 +#define _TO_BOOL_STR 592 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 592 -#define _UNARY_NEGATIVE 593 +#define _UNARY_INVERT 593 +#define _UNARY_NEGATIVE 594 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 594 -#define _UNPACK_SEQUENCE_LIST 595 -#define _UNPACK_SEQUENCE_TUPLE 596 -#define _UNPACK_SEQUENCE_TWO_TUPLE 597 +#define _UNPACK_SEQUENCE 595 +#define _UNPACK_SEQUENCE_LIST 596 +#define _UNPACK_SEQUENCE_TUPLE 597 +#define _UNPACK_SEQUENCE_TWO_TUPLE 598 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 598 -#define MAX_UOP_ID 598 -#define _BINARY_OP_r23 599 -#define _BINARY_OP_ADD_FLOAT_r03 600 -#define _BINARY_OP_ADD_FLOAT_r13 601 -#define _BINARY_OP_ADD_FLOAT_r23 602 -#define _BINARY_OP_ADD_INT_r03 603 -#define _BINARY_OP_ADD_INT_r13 604 -#define _BINARY_OP_ADD_INT_r23 605 -#define _BINARY_OP_ADD_UNICODE_r03 606 -#define _BINARY_OP_ADD_UNICODE_r13 607 -#define _BINARY_OP_ADD_UNICODE_r23 608 -#define _BINARY_OP_EXTEND_r23 609 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 610 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 611 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 612 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 613 -#define _BINARY_OP_MULTIPLY_INT_r03 614 -#define _BINARY_OP_MULTIPLY_INT_r13 615 -#define _BINARY_OP_MULTIPLY_INT_r23 616 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 617 -#define _BINARY_OP_SUBSCR_DICT_r23 618 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 619 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 620 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 621 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 622 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 623 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 624 -#define _BINARY_OP_SUBSCR_STR_INT_r23 625 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 626 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 627 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 628 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 629 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 630 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 631 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 632 -#define _BINARY_OP_SUBTRACT_INT_r03 633 -#define _BINARY_OP_SUBTRACT_INT_r13 634 -#define _BINARY_OP_SUBTRACT_INT_r23 635 -#define _BINARY_SLICE_r31 636 -#define _BUILD_INTERPOLATION_r01 637 -#define _BUILD_LIST_r01 638 -#define _BUILD_MAP_r01 639 -#define _BUILD_SET_r01 640 -#define _BUILD_SLICE_r01 641 -#define _BUILD_STRING_r01 642 -#define _BUILD_TEMPLATE_r21 643 -#define _BUILD_TUPLE_r01 644 -#define _CALL_BUILTIN_CLASS_r01 645 -#define _CALL_BUILTIN_FAST_r01 646 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 647 -#define _CALL_BUILTIN_O_r03 648 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 649 -#define _CALL_INTRINSIC_1_r11 650 -#define _CALL_INTRINSIC_2_r21 651 -#define _CALL_ISINSTANCE_r31 652 -#define _CALL_KW_NON_PY_r11 653 -#define _CALL_LEN_r33 654 -#define _CALL_LIST_APPEND_r03 655 -#define _CALL_LIST_APPEND_r13 656 -#define _CALL_LIST_APPEND_r23 657 -#define _CALL_LIST_APPEND_r33 658 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 659 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 660 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 661 -#define _CALL_METHOD_DESCRIPTOR_O_r03 662 -#define _CALL_NON_PY_GENERAL_r01 663 -#define _CALL_STR_1_r32 664 -#define _CALL_TUPLE_1_r32 665 -#define _CALL_TYPE_1_r02 666 -#define _CALL_TYPE_1_r12 667 -#define _CALL_TYPE_1_r22 668 -#define _CALL_TYPE_1_r32 669 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 670 -#define _CHECK_ATTR_CLASS_r01 671 -#define _CHECK_ATTR_CLASS_r11 672 -#define _CHECK_ATTR_CLASS_r22 673 -#define _CHECK_ATTR_CLASS_r33 674 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 675 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 676 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 677 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 678 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 679 -#define _CHECK_EG_MATCH_r22 680 -#define _CHECK_EXC_MATCH_r22 681 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 682 -#define _CHECK_FUNCTION_VERSION_r00 683 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 684 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 685 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 686 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 687 -#define _CHECK_FUNCTION_VERSION_KW_r11 688 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 689 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 690 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 691 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 692 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 693 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 694 -#define _CHECK_IS_PY_CALLABLE_EX_r03 695 -#define _CHECK_IS_PY_CALLABLE_EX_r13 696 -#define _CHECK_IS_PY_CALLABLE_EX_r23 697 -#define _CHECK_IS_PY_CALLABLE_EX_r33 698 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 699 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 700 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 701 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 702 -#define _CHECK_METHOD_VERSION_r00 703 -#define _CHECK_METHOD_VERSION_KW_r11 704 -#define _CHECK_PEP_523_r00 705 -#define _CHECK_PEP_523_r11 706 -#define _CHECK_PEP_523_r22 707 -#define _CHECK_PEP_523_r33 708 -#define _CHECK_PERIODIC_r00 709 -#define _CHECK_PERIODIC_AT_END_r00 710 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 711 -#define _CHECK_RECURSION_REMAINING_r00 712 -#define _CHECK_RECURSION_REMAINING_r11 713 -#define _CHECK_RECURSION_REMAINING_r22 714 -#define _CHECK_RECURSION_REMAINING_r33 715 -#define _CHECK_STACK_SPACE_r00 716 -#define _CHECK_STACK_SPACE_OPERAND_r00 717 -#define _CHECK_STACK_SPACE_OPERAND_r11 718 -#define _CHECK_STACK_SPACE_OPERAND_r22 719 -#define _CHECK_STACK_SPACE_OPERAND_r33 720 -#define _CHECK_VALIDITY_r00 721 -#define _CHECK_VALIDITY_r11 722 -#define _CHECK_VALIDITY_r22 723 -#define _CHECK_VALIDITY_r33 724 -#define _COLD_DYNAMIC_EXIT_r00 725 -#define _COLD_EXIT_r00 726 -#define _COMPARE_OP_r21 727 -#define _COMPARE_OP_FLOAT_r03 728 -#define _COMPARE_OP_FLOAT_r13 729 -#define _COMPARE_OP_FLOAT_r23 730 -#define _COMPARE_OP_INT_r23 731 -#define _COMPARE_OP_STR_r23 732 -#define _CONTAINS_OP_r23 733 -#define _CONTAINS_OP_DICT_r23 734 -#define _CONTAINS_OP_SET_r23 735 -#define _CONVERT_VALUE_r11 736 -#define _COPY_r01 737 -#define _COPY_1_r02 738 -#define _COPY_1_r12 739 -#define _COPY_1_r23 740 -#define _COPY_2_r03 741 -#define _COPY_2_r13 742 -#define _COPY_2_r23 743 -#define _COPY_3_r03 744 -#define _COPY_3_r13 745 -#define _COPY_3_r23 746 -#define _COPY_3_r33 747 -#define _COPY_FREE_VARS_r00 748 -#define _COPY_FREE_VARS_r11 749 -#define _COPY_FREE_VARS_r22 750 -#define _COPY_FREE_VARS_r33 751 -#define _CREATE_INIT_FRAME_r01 752 -#define _DELETE_ATTR_r10 753 -#define _DELETE_DEREF_r00 754 -#define _DELETE_FAST_r00 755 -#define _DELETE_GLOBAL_r00 756 -#define _DELETE_NAME_r00 757 -#define _DELETE_SUBSCR_r20 758 -#define _DEOPT_r00 759 -#define _DEOPT_r10 760 -#define _DEOPT_r20 761 -#define _DEOPT_r30 762 -#define _DICT_MERGE_r10 763 -#define _DICT_UPDATE_r10 764 -#define _DO_CALL_r01 765 -#define _DO_CALL_FUNCTION_EX_r31 766 -#define _DO_CALL_KW_r11 767 -#define _DYNAMIC_EXIT_r00 768 -#define _DYNAMIC_EXIT_r10 769 -#define _DYNAMIC_EXIT_r20 770 -#define _DYNAMIC_EXIT_r30 771 -#define _END_FOR_r10 772 -#define _END_SEND_r21 773 -#define _ERROR_POP_N_r00 774 -#define _EXIT_INIT_CHECK_r10 775 -#define _EXIT_TRACE_r00 776 -#define _EXIT_TRACE_r10 777 -#define _EXIT_TRACE_r20 778 -#define _EXIT_TRACE_r30 779 -#define _EXPAND_METHOD_r00 780 -#define _EXPAND_METHOD_KW_r11 781 -#define _FATAL_ERROR_r00 782 -#define _FATAL_ERROR_r11 783 -#define _FATAL_ERROR_r22 784 -#define _FATAL_ERROR_r33 785 -#define _FORMAT_SIMPLE_r11 786 -#define _FORMAT_WITH_SPEC_r21 787 -#define _FOR_ITER_r23 788 -#define _FOR_ITER_GEN_FRAME_r03 789 -#define _FOR_ITER_GEN_FRAME_r13 790 -#define _FOR_ITER_GEN_FRAME_r23 791 -#define _FOR_ITER_TIER_TWO_r23 792 -#define _GET_AITER_r11 793 -#define _GET_ANEXT_r12 794 -#define _GET_AWAITABLE_r11 795 -#define _GET_ITER_r12 796 -#define _GET_LEN_r12 797 -#define _GET_YIELD_FROM_ITER_r11 798 -#define _GUARD_BINARY_OP_EXTEND_r22 799 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 800 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 801 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 802 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 803 -#define _GUARD_BIT_IS_SET_POP_r00 804 -#define _GUARD_BIT_IS_SET_POP_r10 805 -#define _GUARD_BIT_IS_SET_POP_r21 806 -#define _GUARD_BIT_IS_SET_POP_r32 807 -#define _GUARD_BIT_IS_SET_POP_4_r00 808 -#define _GUARD_BIT_IS_SET_POP_4_r10 809 -#define _GUARD_BIT_IS_SET_POP_4_r21 810 -#define _GUARD_BIT_IS_SET_POP_4_r32 811 -#define _GUARD_BIT_IS_SET_POP_5_r00 812 -#define _GUARD_BIT_IS_SET_POP_5_r10 813 -#define _GUARD_BIT_IS_SET_POP_5_r21 814 -#define _GUARD_BIT_IS_SET_POP_5_r32 815 -#define _GUARD_BIT_IS_SET_POP_6_r00 816 -#define _GUARD_BIT_IS_SET_POP_6_r10 817 -#define _GUARD_BIT_IS_SET_POP_6_r21 818 -#define _GUARD_BIT_IS_SET_POP_6_r32 819 -#define _GUARD_BIT_IS_SET_POP_7_r00 820 -#define _GUARD_BIT_IS_SET_POP_7_r10 821 -#define _GUARD_BIT_IS_SET_POP_7_r21 822 -#define _GUARD_BIT_IS_SET_POP_7_r32 823 -#define _GUARD_BIT_IS_UNSET_POP_r00 824 -#define _GUARD_BIT_IS_UNSET_POP_r10 825 -#define _GUARD_BIT_IS_UNSET_POP_r21 826 -#define _GUARD_BIT_IS_UNSET_POP_r32 827 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 828 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 829 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 830 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 831 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 832 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 833 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 834 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 835 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 836 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 837 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 838 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 839 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 840 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 841 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 842 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 843 -#define _GUARD_CALLABLE_ISINSTANCE_r03 844 -#define _GUARD_CALLABLE_ISINSTANCE_r13 845 -#define _GUARD_CALLABLE_ISINSTANCE_r23 846 -#define _GUARD_CALLABLE_ISINSTANCE_r33 847 -#define _GUARD_CALLABLE_LEN_r03 848 -#define _GUARD_CALLABLE_LEN_r13 849 -#define _GUARD_CALLABLE_LEN_r23 850 -#define _GUARD_CALLABLE_LEN_r33 851 -#define _GUARD_CALLABLE_LIST_APPEND_r03 852 -#define _GUARD_CALLABLE_LIST_APPEND_r13 853 -#define _GUARD_CALLABLE_LIST_APPEND_r23 854 -#define _GUARD_CALLABLE_LIST_APPEND_r33 855 -#define _GUARD_CALLABLE_STR_1_r03 856 -#define _GUARD_CALLABLE_STR_1_r13 857 -#define _GUARD_CALLABLE_STR_1_r23 858 -#define _GUARD_CALLABLE_STR_1_r33 859 -#define _GUARD_CALLABLE_TUPLE_1_r03 860 -#define _GUARD_CALLABLE_TUPLE_1_r13 861 -#define _GUARD_CALLABLE_TUPLE_1_r23 862 -#define _GUARD_CALLABLE_TUPLE_1_r33 863 -#define _GUARD_CALLABLE_TYPE_1_r03 864 -#define _GUARD_CALLABLE_TYPE_1_r13 865 -#define _GUARD_CALLABLE_TYPE_1_r23 866 -#define _GUARD_CALLABLE_TYPE_1_r33 867 -#define _GUARD_CODE_VERSION_r00 868 -#define _GUARD_CODE_VERSION_r11 869 -#define _GUARD_CODE_VERSION_r22 870 -#define _GUARD_CODE_VERSION_r33 871 -#define _GUARD_DORV_NO_DICT_r01 872 -#define _GUARD_DORV_NO_DICT_r11 873 -#define _GUARD_DORV_NO_DICT_r22 874 -#define _GUARD_DORV_NO_DICT_r33 875 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 876 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 877 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 878 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 879 -#define _GUARD_GLOBALS_VERSION_r00 880 -#define _GUARD_GLOBALS_VERSION_r11 881 -#define _GUARD_GLOBALS_VERSION_r22 882 -#define _GUARD_GLOBALS_VERSION_r33 883 -#define _GUARD_IP_RETURN_GENERATOR_r00 884 -#define _GUARD_IP_RETURN_GENERATOR_r11 885 -#define _GUARD_IP_RETURN_GENERATOR_r22 886 -#define _GUARD_IP_RETURN_GENERATOR_r33 887 -#define _GUARD_IP_RETURN_VALUE_r00 888 -#define _GUARD_IP_RETURN_VALUE_r11 889 -#define _GUARD_IP_RETURN_VALUE_r22 890 -#define _GUARD_IP_RETURN_VALUE_r33 891 -#define _GUARD_IP_YIELD_VALUE_r00 892 -#define _GUARD_IP_YIELD_VALUE_r11 893 -#define _GUARD_IP_YIELD_VALUE_r22 894 -#define _GUARD_IP_YIELD_VALUE_r33 895 -#define _GUARD_IP__PUSH_FRAME_r00 896 -#define _GUARD_IP__PUSH_FRAME_r11 897 -#define _GUARD_IP__PUSH_FRAME_r22 898 -#define _GUARD_IP__PUSH_FRAME_r33 899 -#define _GUARD_IS_FALSE_POP_r00 900 -#define _GUARD_IS_FALSE_POP_r10 901 -#define _GUARD_IS_FALSE_POP_r21 902 -#define _GUARD_IS_FALSE_POP_r32 903 -#define _GUARD_IS_NONE_POP_r00 904 -#define _GUARD_IS_NONE_POP_r10 905 -#define _GUARD_IS_NONE_POP_r21 906 -#define _GUARD_IS_NONE_POP_r32 907 -#define _GUARD_IS_NOT_NONE_POP_r10 908 -#define _GUARD_IS_TRUE_POP_r00 909 -#define _GUARD_IS_TRUE_POP_r10 910 -#define _GUARD_IS_TRUE_POP_r21 911 -#define _GUARD_IS_TRUE_POP_r32 912 -#define _GUARD_KEYS_VERSION_r01 913 -#define _GUARD_KEYS_VERSION_r11 914 -#define _GUARD_KEYS_VERSION_r22 915 -#define _GUARD_KEYS_VERSION_r33 916 -#define _GUARD_NOS_ANY_DICT_r02 917 -#define _GUARD_NOS_ANY_DICT_r12 918 -#define _GUARD_NOS_ANY_DICT_r22 919 -#define _GUARD_NOS_ANY_DICT_r33 920 -#define _GUARD_NOS_COMPACT_ASCII_r02 921 -#define _GUARD_NOS_COMPACT_ASCII_r12 922 -#define _GUARD_NOS_COMPACT_ASCII_r22 923 -#define _GUARD_NOS_COMPACT_ASCII_r33 924 -#define _GUARD_NOS_DICT_r02 925 -#define _GUARD_NOS_DICT_r12 926 -#define _GUARD_NOS_DICT_r22 927 -#define _GUARD_NOS_DICT_r33 928 -#define _GUARD_NOS_FLOAT_r02 929 -#define _GUARD_NOS_FLOAT_r12 930 -#define _GUARD_NOS_FLOAT_r22 931 -#define _GUARD_NOS_FLOAT_r33 932 -#define _GUARD_NOS_INT_r02 933 -#define _GUARD_NOS_INT_r12 934 -#define _GUARD_NOS_INT_r22 935 -#define _GUARD_NOS_INT_r33 936 -#define _GUARD_NOS_LIST_r02 937 -#define _GUARD_NOS_LIST_r12 938 -#define _GUARD_NOS_LIST_r22 939 -#define _GUARD_NOS_LIST_r33 940 -#define _GUARD_NOS_NOT_NULL_r02 941 -#define _GUARD_NOS_NOT_NULL_r12 942 -#define _GUARD_NOS_NOT_NULL_r22 943 -#define _GUARD_NOS_NOT_NULL_r33 944 -#define _GUARD_NOS_NULL_r02 945 -#define _GUARD_NOS_NULL_r12 946 -#define _GUARD_NOS_NULL_r22 947 -#define _GUARD_NOS_NULL_r33 948 -#define _GUARD_NOS_OVERFLOWED_r02 949 -#define _GUARD_NOS_OVERFLOWED_r12 950 -#define _GUARD_NOS_OVERFLOWED_r22 951 -#define _GUARD_NOS_OVERFLOWED_r33 952 -#define _GUARD_NOS_TUPLE_r02 953 -#define _GUARD_NOS_TUPLE_r12 954 -#define _GUARD_NOS_TUPLE_r22 955 -#define _GUARD_NOS_TUPLE_r33 956 -#define _GUARD_NOS_UNICODE_r02 957 -#define _GUARD_NOS_UNICODE_r12 958 -#define _GUARD_NOS_UNICODE_r22 959 -#define _GUARD_NOS_UNICODE_r33 960 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 961 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 962 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 963 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 964 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 965 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 966 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 967 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 968 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 969 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 970 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 971 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 972 -#define _GUARD_THIRD_NULL_r03 973 -#define _GUARD_THIRD_NULL_r13 974 -#define _GUARD_THIRD_NULL_r23 975 -#define _GUARD_THIRD_NULL_r33 976 -#define _GUARD_TOS_ANY_DICT_r01 977 -#define _GUARD_TOS_ANY_DICT_r11 978 -#define _GUARD_TOS_ANY_DICT_r22 979 -#define _GUARD_TOS_ANY_DICT_r33 980 -#define _GUARD_TOS_ANY_SET_r01 981 -#define _GUARD_TOS_ANY_SET_r11 982 -#define _GUARD_TOS_ANY_SET_r22 983 -#define _GUARD_TOS_ANY_SET_r33 984 -#define _GUARD_TOS_DICT_r01 985 -#define _GUARD_TOS_DICT_r11 986 -#define _GUARD_TOS_DICT_r22 987 -#define _GUARD_TOS_DICT_r33 988 -#define _GUARD_TOS_FLOAT_r01 989 -#define _GUARD_TOS_FLOAT_r11 990 -#define _GUARD_TOS_FLOAT_r22 991 -#define _GUARD_TOS_FLOAT_r33 992 -#define _GUARD_TOS_FROZENDICT_r01 993 -#define _GUARD_TOS_FROZENDICT_r11 994 -#define _GUARD_TOS_FROZENDICT_r22 995 -#define _GUARD_TOS_FROZENDICT_r33 996 -#define _GUARD_TOS_FROZENSET_r01 997 -#define _GUARD_TOS_FROZENSET_r11 998 -#define _GUARD_TOS_FROZENSET_r22 999 -#define _GUARD_TOS_FROZENSET_r33 1000 -#define _GUARD_TOS_INT_r01 1001 -#define _GUARD_TOS_INT_r11 1002 -#define _GUARD_TOS_INT_r22 1003 -#define _GUARD_TOS_INT_r33 1004 -#define _GUARD_TOS_LIST_r01 1005 -#define _GUARD_TOS_LIST_r11 1006 -#define _GUARD_TOS_LIST_r22 1007 -#define _GUARD_TOS_LIST_r33 1008 -#define _GUARD_TOS_OVERFLOWED_r01 1009 -#define _GUARD_TOS_OVERFLOWED_r11 1010 -#define _GUARD_TOS_OVERFLOWED_r22 1011 -#define _GUARD_TOS_OVERFLOWED_r33 1012 -#define _GUARD_TOS_SET_r01 1013 -#define _GUARD_TOS_SET_r11 1014 -#define _GUARD_TOS_SET_r22 1015 -#define _GUARD_TOS_SET_r33 1016 -#define _GUARD_TOS_SLICE_r01 1017 -#define _GUARD_TOS_SLICE_r11 1018 -#define _GUARD_TOS_SLICE_r22 1019 -#define _GUARD_TOS_SLICE_r33 1020 -#define _GUARD_TOS_TUPLE_r01 1021 -#define _GUARD_TOS_TUPLE_r11 1022 -#define _GUARD_TOS_TUPLE_r22 1023 -#define _GUARD_TOS_TUPLE_r33 1024 -#define _GUARD_TOS_UNICODE_r01 1025 -#define _GUARD_TOS_UNICODE_r11 1026 -#define _GUARD_TOS_UNICODE_r22 1027 -#define _GUARD_TOS_UNICODE_r33 1028 -#define _GUARD_TYPE_VERSION_r01 1029 -#define _GUARD_TYPE_VERSION_r11 1030 -#define _GUARD_TYPE_VERSION_r22 1031 -#define _GUARD_TYPE_VERSION_r33 1032 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1033 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1034 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1035 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1036 -#define _HANDLE_PENDING_AND_DEOPT_r00 1037 -#define _HANDLE_PENDING_AND_DEOPT_r10 1038 -#define _HANDLE_PENDING_AND_DEOPT_r20 1039 -#define _HANDLE_PENDING_AND_DEOPT_r30 1040 -#define _IMPORT_FROM_r12 1041 -#define _IMPORT_NAME_r21 1042 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1043 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1044 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1045 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1046 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1047 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1048 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1049 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1050 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1051 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1052 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1053 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1054 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1055 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1056 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1057 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1058 -#define _INSERT_NULL_r10 1059 -#define _INSTRUMENTED_FOR_ITER_r23 1060 -#define _INSTRUMENTED_INSTRUCTION_r00 1061 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1062 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1063 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1064 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1065 -#define _INSTRUMENTED_LINE_r00 1066 -#define _INSTRUMENTED_NOT_TAKEN_r00 1067 -#define _INSTRUMENTED_NOT_TAKEN_r11 1068 -#define _INSTRUMENTED_NOT_TAKEN_r22 1069 -#define _INSTRUMENTED_NOT_TAKEN_r33 1070 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1071 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1072 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1073 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1074 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1075 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1076 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1077 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1078 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1079 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1080 -#define _IS_NONE_r11 1081 -#define _IS_OP_r03 1082 -#define _IS_OP_r13 1083 -#define _IS_OP_r23 1084 -#define _ITER_CHECK_LIST_r02 1085 -#define _ITER_CHECK_LIST_r12 1086 -#define _ITER_CHECK_LIST_r22 1087 -#define _ITER_CHECK_LIST_r33 1088 -#define _ITER_CHECK_RANGE_r02 1089 -#define _ITER_CHECK_RANGE_r12 1090 -#define _ITER_CHECK_RANGE_r22 1091 -#define _ITER_CHECK_RANGE_r33 1092 -#define _ITER_CHECK_TUPLE_r02 1093 -#define _ITER_CHECK_TUPLE_r12 1094 -#define _ITER_CHECK_TUPLE_r22 1095 -#define _ITER_CHECK_TUPLE_r33 1096 -#define _ITER_JUMP_LIST_r02 1097 -#define _ITER_JUMP_LIST_r12 1098 -#define _ITER_JUMP_LIST_r22 1099 -#define _ITER_JUMP_LIST_r33 1100 -#define _ITER_JUMP_RANGE_r02 1101 -#define _ITER_JUMP_RANGE_r12 1102 -#define _ITER_JUMP_RANGE_r22 1103 -#define _ITER_JUMP_RANGE_r33 1104 -#define _ITER_JUMP_TUPLE_r02 1105 -#define _ITER_JUMP_TUPLE_r12 1106 -#define _ITER_JUMP_TUPLE_r22 1107 -#define _ITER_JUMP_TUPLE_r33 1108 -#define _ITER_NEXT_LIST_r23 1109 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1110 -#define _ITER_NEXT_RANGE_r03 1111 -#define _ITER_NEXT_RANGE_r13 1112 -#define _ITER_NEXT_RANGE_r23 1113 -#define _ITER_NEXT_TUPLE_r03 1114 -#define _ITER_NEXT_TUPLE_r13 1115 -#define _ITER_NEXT_TUPLE_r23 1116 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1117 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1118 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1119 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1120 -#define _JUMP_TO_TOP_r00 1121 -#define _LIST_APPEND_r10 1122 -#define _LIST_EXTEND_r10 1123 -#define _LOAD_ATTR_r10 1124 -#define _LOAD_ATTR_CLASS_r11 1125 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1126 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1127 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1128 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1129 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1130 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1131 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1132 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1133 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1134 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1135 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1136 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1137 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1138 -#define _LOAD_ATTR_MODULE_r12 1139 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1140 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1141 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1142 -#define _LOAD_ATTR_SLOT_r02 1143 -#define _LOAD_ATTR_SLOT_r12 1144 -#define _LOAD_ATTR_SLOT_r23 1145 -#define _LOAD_ATTR_WITH_HINT_r12 1146 -#define _LOAD_BUILD_CLASS_r01 1147 -#define _LOAD_BYTECODE_r00 1148 -#define _LOAD_COMMON_CONSTANT_r01 1149 -#define _LOAD_COMMON_CONSTANT_r12 1150 -#define _LOAD_COMMON_CONSTANT_r23 1151 -#define _LOAD_CONST_r01 1152 -#define _LOAD_CONST_r12 1153 -#define _LOAD_CONST_r23 1154 -#define _LOAD_CONST_INLINE_r01 1155 -#define _LOAD_CONST_INLINE_r12 1156 -#define _LOAD_CONST_INLINE_r23 1157 -#define _LOAD_CONST_INLINE_BORROW_r01 1158 -#define _LOAD_CONST_INLINE_BORROW_r12 1159 -#define _LOAD_CONST_INLINE_BORROW_r23 1160 -#define _LOAD_CONST_UNDER_INLINE_r02 1161 -#define _LOAD_CONST_UNDER_INLINE_r12 1162 -#define _LOAD_CONST_UNDER_INLINE_r23 1163 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1164 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1165 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1166 -#define _LOAD_DEREF_r01 1167 -#define _LOAD_FAST_r01 1168 -#define _LOAD_FAST_r12 1169 -#define _LOAD_FAST_r23 1170 -#define _LOAD_FAST_0_r01 1171 -#define _LOAD_FAST_0_r12 1172 -#define _LOAD_FAST_0_r23 1173 -#define _LOAD_FAST_1_r01 1174 -#define _LOAD_FAST_1_r12 1175 -#define _LOAD_FAST_1_r23 1176 -#define _LOAD_FAST_2_r01 1177 -#define _LOAD_FAST_2_r12 1178 -#define _LOAD_FAST_2_r23 1179 -#define _LOAD_FAST_3_r01 1180 -#define _LOAD_FAST_3_r12 1181 -#define _LOAD_FAST_3_r23 1182 -#define _LOAD_FAST_4_r01 1183 -#define _LOAD_FAST_4_r12 1184 -#define _LOAD_FAST_4_r23 1185 -#define _LOAD_FAST_5_r01 1186 -#define _LOAD_FAST_5_r12 1187 -#define _LOAD_FAST_5_r23 1188 -#define _LOAD_FAST_6_r01 1189 -#define _LOAD_FAST_6_r12 1190 -#define _LOAD_FAST_6_r23 1191 -#define _LOAD_FAST_7_r01 1192 -#define _LOAD_FAST_7_r12 1193 -#define _LOAD_FAST_7_r23 1194 -#define _LOAD_FAST_AND_CLEAR_r01 1195 -#define _LOAD_FAST_AND_CLEAR_r12 1196 -#define _LOAD_FAST_AND_CLEAR_r23 1197 -#define _LOAD_FAST_BORROW_r01 1198 -#define _LOAD_FAST_BORROW_r12 1199 -#define _LOAD_FAST_BORROW_r23 1200 -#define _LOAD_FAST_BORROW_0_r01 1201 -#define _LOAD_FAST_BORROW_0_r12 1202 -#define _LOAD_FAST_BORROW_0_r23 1203 -#define _LOAD_FAST_BORROW_1_r01 1204 -#define _LOAD_FAST_BORROW_1_r12 1205 -#define _LOAD_FAST_BORROW_1_r23 1206 -#define _LOAD_FAST_BORROW_2_r01 1207 -#define _LOAD_FAST_BORROW_2_r12 1208 -#define _LOAD_FAST_BORROW_2_r23 1209 -#define _LOAD_FAST_BORROW_3_r01 1210 -#define _LOAD_FAST_BORROW_3_r12 1211 -#define _LOAD_FAST_BORROW_3_r23 1212 -#define _LOAD_FAST_BORROW_4_r01 1213 -#define _LOAD_FAST_BORROW_4_r12 1214 -#define _LOAD_FAST_BORROW_4_r23 1215 -#define _LOAD_FAST_BORROW_5_r01 1216 -#define _LOAD_FAST_BORROW_5_r12 1217 -#define _LOAD_FAST_BORROW_5_r23 1218 -#define _LOAD_FAST_BORROW_6_r01 1219 -#define _LOAD_FAST_BORROW_6_r12 1220 -#define _LOAD_FAST_BORROW_6_r23 1221 -#define _LOAD_FAST_BORROW_7_r01 1222 -#define _LOAD_FAST_BORROW_7_r12 1223 -#define _LOAD_FAST_BORROW_7_r23 1224 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1225 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1226 -#define _LOAD_FAST_CHECK_r01 1227 -#define _LOAD_FAST_CHECK_r12 1228 -#define _LOAD_FAST_CHECK_r23 1229 -#define _LOAD_FAST_LOAD_FAST_r02 1230 -#define _LOAD_FAST_LOAD_FAST_r13 1231 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1232 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1233 -#define _LOAD_GLOBAL_r00 1234 -#define _LOAD_GLOBAL_BUILTINS_r01 1235 -#define _LOAD_GLOBAL_MODULE_r01 1236 -#define _LOAD_LOCALS_r01 1237 -#define _LOAD_LOCALS_r12 1238 -#define _LOAD_LOCALS_r23 1239 -#define _LOAD_NAME_r01 1240 -#define _LOAD_SMALL_INT_r01 1241 -#define _LOAD_SMALL_INT_r12 1242 -#define _LOAD_SMALL_INT_r23 1243 -#define _LOAD_SMALL_INT_0_r01 1244 -#define _LOAD_SMALL_INT_0_r12 1245 -#define _LOAD_SMALL_INT_0_r23 1246 -#define _LOAD_SMALL_INT_1_r01 1247 -#define _LOAD_SMALL_INT_1_r12 1248 -#define _LOAD_SMALL_INT_1_r23 1249 -#define _LOAD_SMALL_INT_2_r01 1250 -#define _LOAD_SMALL_INT_2_r12 1251 -#define _LOAD_SMALL_INT_2_r23 1252 -#define _LOAD_SMALL_INT_3_r01 1253 -#define _LOAD_SMALL_INT_3_r12 1254 -#define _LOAD_SMALL_INT_3_r23 1255 -#define _LOAD_SPECIAL_r00 1256 -#define _LOAD_SUPER_ATTR_ATTR_r31 1257 -#define _LOAD_SUPER_ATTR_METHOD_r32 1258 -#define _LOCK_OBJECT_r01 1259 -#define _LOCK_OBJECT_r11 1260 -#define _LOCK_OBJECT_r22 1261 -#define _LOCK_OBJECT_r33 1262 -#define _MAKE_CALLARGS_A_TUPLE_r33 1263 -#define _MAKE_CELL_r00 1264 -#define _MAKE_FUNCTION_r11 1265 -#define _MAKE_HEAP_SAFE_r01 1266 -#define _MAKE_HEAP_SAFE_r11 1267 -#define _MAKE_HEAP_SAFE_r22 1268 -#define _MAKE_HEAP_SAFE_r33 1269 -#define _MAKE_WARM_r00 1270 -#define _MAKE_WARM_r11 1271 -#define _MAKE_WARM_r22 1272 -#define _MAKE_WARM_r33 1273 -#define _MAP_ADD_r20 1274 -#define _MATCH_CLASS_r33 1275 -#define _MATCH_KEYS_r23 1276 -#define _MATCH_MAPPING_r02 1277 -#define _MATCH_MAPPING_r12 1278 -#define _MATCH_MAPPING_r23 1279 -#define _MATCH_SEQUENCE_r02 1280 -#define _MATCH_SEQUENCE_r12 1281 -#define _MATCH_SEQUENCE_r23 1282 -#define _MAYBE_EXPAND_METHOD_r00 1283 -#define _MAYBE_EXPAND_METHOD_KW_r11 1284 -#define _MONITOR_CALL_r00 1285 -#define _MONITOR_CALL_KW_r11 1286 -#define _MONITOR_JUMP_BACKWARD_r00 1287 -#define _MONITOR_JUMP_BACKWARD_r11 1288 -#define _MONITOR_JUMP_BACKWARD_r22 1289 -#define _MONITOR_JUMP_BACKWARD_r33 1290 -#define _MONITOR_RESUME_r00 1291 -#define _NOP_r00 1292 -#define _NOP_r11 1293 -#define _NOP_r22 1294 -#define _NOP_r33 1295 -#define _POP_CALL_r20 1296 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1297 -#define _POP_CALL_ONE_r30 1298 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1299 -#define _POP_CALL_TWO_r30 1300 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1301 -#define _POP_EXCEPT_r10 1302 -#define _POP_ITER_r20 1303 -#define _POP_JUMP_IF_FALSE_r00 1304 -#define _POP_JUMP_IF_FALSE_r10 1305 -#define _POP_JUMP_IF_FALSE_r21 1306 -#define _POP_JUMP_IF_FALSE_r32 1307 -#define _POP_JUMP_IF_TRUE_r00 1308 -#define _POP_JUMP_IF_TRUE_r10 1309 -#define _POP_JUMP_IF_TRUE_r21 1310 -#define _POP_JUMP_IF_TRUE_r32 1311 -#define _POP_TOP_r10 1312 -#define _POP_TOP_FLOAT_r00 1313 -#define _POP_TOP_FLOAT_r10 1314 -#define _POP_TOP_FLOAT_r21 1315 -#define _POP_TOP_FLOAT_r32 1316 -#define _POP_TOP_INT_r00 1317 -#define _POP_TOP_INT_r10 1318 -#define _POP_TOP_INT_r21 1319 -#define _POP_TOP_INT_r32 1320 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1321 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1322 -#define _POP_TOP_NOP_r00 1323 -#define _POP_TOP_NOP_r10 1324 -#define _POP_TOP_NOP_r21 1325 -#define _POP_TOP_NOP_r32 1326 -#define _POP_TOP_UNICODE_r00 1327 -#define _POP_TOP_UNICODE_r10 1328 -#define _POP_TOP_UNICODE_r21 1329 -#define _POP_TOP_UNICODE_r32 1330 -#define _POP_TWO_r20 1331 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1332 -#define _PUSH_EXC_INFO_r02 1333 -#define _PUSH_EXC_INFO_r12 1334 -#define _PUSH_EXC_INFO_r23 1335 -#define _PUSH_FRAME_r10 1336 -#define _PUSH_NULL_r01 1337 -#define _PUSH_NULL_r12 1338 -#define _PUSH_NULL_r23 1339 -#define _PUSH_NULL_CONDITIONAL_r00 1340 -#define _PY_FRAME_EX_r31 1341 -#define _PY_FRAME_GENERAL_r01 1342 -#define _PY_FRAME_KW_r11 1343 -#define _QUICKEN_RESUME_r00 1344 -#define _QUICKEN_RESUME_r11 1345 -#define _QUICKEN_RESUME_r22 1346 -#define _QUICKEN_RESUME_r33 1347 -#define _REPLACE_WITH_TRUE_r02 1348 -#define _REPLACE_WITH_TRUE_r12 1349 -#define _REPLACE_WITH_TRUE_r23 1350 -#define _RESUME_CHECK_r00 1351 -#define _RESUME_CHECK_r11 1352 -#define _RESUME_CHECK_r22 1353 -#define _RESUME_CHECK_r33 1354 -#define _RETURN_GENERATOR_r01 1355 -#define _RETURN_VALUE_r11 1356 -#define _SAVE_RETURN_OFFSET_r00 1357 -#define _SAVE_RETURN_OFFSET_r11 1358 -#define _SAVE_RETURN_OFFSET_r22 1359 -#define _SAVE_RETURN_OFFSET_r33 1360 -#define _SEND_r22 1361 -#define _SEND_GEN_FRAME_r22 1362 -#define _SETUP_ANNOTATIONS_r00 1363 -#define _SET_ADD_r10 1364 -#define _SET_FUNCTION_ATTRIBUTE_r01 1365 -#define _SET_FUNCTION_ATTRIBUTE_r11 1366 -#define _SET_FUNCTION_ATTRIBUTE_r21 1367 -#define _SET_FUNCTION_ATTRIBUTE_r32 1368 -#define _SET_IP_r00 1369 -#define _SET_IP_r11 1370 -#define _SET_IP_r22 1371 -#define _SET_IP_r33 1372 -#define _SET_UPDATE_r10 1373 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1374 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1375 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1376 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1377 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1378 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1379 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1380 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1381 -#define _SPILL_OR_RELOAD_r01 1382 -#define _SPILL_OR_RELOAD_r02 1383 -#define _SPILL_OR_RELOAD_r03 1384 -#define _SPILL_OR_RELOAD_r10 1385 -#define _SPILL_OR_RELOAD_r12 1386 -#define _SPILL_OR_RELOAD_r13 1387 -#define _SPILL_OR_RELOAD_r20 1388 -#define _SPILL_OR_RELOAD_r21 1389 -#define _SPILL_OR_RELOAD_r23 1390 -#define _SPILL_OR_RELOAD_r30 1391 -#define _SPILL_OR_RELOAD_r31 1392 -#define _SPILL_OR_RELOAD_r32 1393 -#define _START_EXECUTOR_r00 1394 -#define _STORE_ATTR_r20 1395 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1396 -#define _STORE_ATTR_SLOT_r21 1397 -#define _STORE_ATTR_WITH_HINT_r21 1398 -#define _STORE_DEREF_r10 1399 -#define _STORE_FAST_LOAD_FAST_r11 1400 -#define _STORE_FAST_STORE_FAST_r20 1401 -#define _STORE_GLOBAL_r10 1402 -#define _STORE_NAME_r10 1403 -#define _STORE_SLICE_r30 1404 -#define _STORE_SUBSCR_r30 1405 -#define _STORE_SUBSCR_DICT_r31 1406 -#define _STORE_SUBSCR_LIST_INT_r32 1407 -#define _SWAP_r11 1408 -#define _SWAP_2_r02 1409 -#define _SWAP_2_r12 1410 -#define _SWAP_2_r22 1411 -#define _SWAP_2_r33 1412 -#define _SWAP_3_r03 1413 -#define _SWAP_3_r13 1414 -#define _SWAP_3_r23 1415 -#define _SWAP_3_r33 1416 -#define _SWAP_FAST_r01 1417 -#define _SWAP_FAST_r11 1418 -#define _SWAP_FAST_r22 1419 -#define _SWAP_FAST_r33 1420 -#define _SWAP_FAST_0_r01 1421 -#define _SWAP_FAST_0_r11 1422 -#define _SWAP_FAST_0_r22 1423 -#define _SWAP_FAST_0_r33 1424 -#define _SWAP_FAST_1_r01 1425 -#define _SWAP_FAST_1_r11 1426 -#define _SWAP_FAST_1_r22 1427 -#define _SWAP_FAST_1_r33 1428 -#define _SWAP_FAST_2_r01 1429 -#define _SWAP_FAST_2_r11 1430 -#define _SWAP_FAST_2_r22 1431 -#define _SWAP_FAST_2_r33 1432 -#define _SWAP_FAST_3_r01 1433 -#define _SWAP_FAST_3_r11 1434 -#define _SWAP_FAST_3_r22 1435 -#define _SWAP_FAST_3_r33 1436 -#define _SWAP_FAST_4_r01 1437 -#define _SWAP_FAST_4_r11 1438 -#define _SWAP_FAST_4_r22 1439 -#define _SWAP_FAST_4_r33 1440 -#define _SWAP_FAST_5_r01 1441 -#define _SWAP_FAST_5_r11 1442 -#define _SWAP_FAST_5_r22 1443 -#define _SWAP_FAST_5_r33 1444 -#define _SWAP_FAST_6_r01 1445 -#define _SWAP_FAST_6_r11 1446 -#define _SWAP_FAST_6_r22 1447 -#define _SWAP_FAST_6_r33 1448 -#define _SWAP_FAST_7_r01 1449 -#define _SWAP_FAST_7_r11 1450 -#define _SWAP_FAST_7_r22 1451 -#define _SWAP_FAST_7_r33 1452 -#define _TIER2_RESUME_CHECK_r00 1453 -#define _TIER2_RESUME_CHECK_r11 1454 -#define _TIER2_RESUME_CHECK_r22 1455 -#define _TIER2_RESUME_CHECK_r33 1456 -#define _TO_BOOL_r11 1457 -#define _TO_BOOL_BOOL_r01 1458 -#define _TO_BOOL_BOOL_r11 1459 -#define _TO_BOOL_BOOL_r22 1460 -#define _TO_BOOL_BOOL_r33 1461 -#define _TO_BOOL_INT_r02 1462 -#define _TO_BOOL_INT_r12 1463 -#define _TO_BOOL_INT_r23 1464 -#define _TO_BOOL_LIST_r02 1465 -#define _TO_BOOL_LIST_r12 1466 -#define _TO_BOOL_LIST_r23 1467 -#define _TO_BOOL_NONE_r01 1468 -#define _TO_BOOL_NONE_r11 1469 -#define _TO_BOOL_NONE_r22 1470 -#define _TO_BOOL_NONE_r33 1471 -#define _TO_BOOL_STR_r02 1472 -#define _TO_BOOL_STR_r12 1473 -#define _TO_BOOL_STR_r23 1474 -#define _TRACE_RECORD_r00 1475 -#define _UNARY_INVERT_r12 1476 -#define _UNARY_NEGATIVE_r12 1477 -#define _UNARY_NOT_r01 1478 -#define _UNARY_NOT_r11 1479 -#define _UNARY_NOT_r22 1480 -#define _UNARY_NOT_r33 1481 -#define _UNPACK_EX_r10 1482 -#define _UNPACK_SEQUENCE_r10 1483 -#define _UNPACK_SEQUENCE_LIST_r10 1484 -#define _UNPACK_SEQUENCE_TUPLE_r10 1485 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1486 -#define _WITH_EXCEPT_START_r33 1487 -#define _YIELD_VALUE_r11 1488 -#define MAX_UOP_REGS_ID 1488 +#define _YIELD_VALUE 599 +#define MAX_UOP_ID 599 +#define _BINARY_OP_r23 600 +#define _BINARY_OP_ADD_FLOAT_r03 601 +#define _BINARY_OP_ADD_FLOAT_r13 602 +#define _BINARY_OP_ADD_FLOAT_r23 603 +#define _BINARY_OP_ADD_INT_r03 604 +#define _BINARY_OP_ADD_INT_r13 605 +#define _BINARY_OP_ADD_INT_r23 606 +#define _BINARY_OP_ADD_UNICODE_r03 607 +#define _BINARY_OP_ADD_UNICODE_r13 608 +#define _BINARY_OP_ADD_UNICODE_r23 609 +#define _BINARY_OP_EXTEND_r23 610 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 611 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 612 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 613 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 614 +#define _BINARY_OP_MULTIPLY_INT_r03 615 +#define _BINARY_OP_MULTIPLY_INT_r13 616 +#define _BINARY_OP_MULTIPLY_INT_r23 617 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 618 +#define _BINARY_OP_SUBSCR_DICT_r23 619 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 620 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 621 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 622 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 623 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 624 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 625 +#define _BINARY_OP_SUBSCR_STR_INT_r23 626 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 627 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 628 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 629 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 630 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 631 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 632 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 633 +#define _BINARY_OP_SUBTRACT_INT_r03 634 +#define _BINARY_OP_SUBTRACT_INT_r13 635 +#define _BINARY_OP_SUBTRACT_INT_r23 636 +#define _BINARY_SLICE_r31 637 +#define _BUILD_INTERPOLATION_r01 638 +#define _BUILD_LIST_r01 639 +#define _BUILD_MAP_r01 640 +#define _BUILD_SET_r01 641 +#define _BUILD_SLICE_r01 642 +#define _BUILD_STRING_r01 643 +#define _BUILD_TEMPLATE_r21 644 +#define _BUILD_TUPLE_r01 645 +#define _CALL_BUILTIN_CLASS_r01 646 +#define _CALL_BUILTIN_FAST_r01 647 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 648 +#define _CALL_BUILTIN_O_r03 649 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 650 +#define _CALL_INTRINSIC_1_r12 651 +#define _CALL_INTRINSIC_2_r21 652 +#define _CALL_ISINSTANCE_r31 653 +#define _CALL_KW_NON_PY_r11 654 +#define _CALL_LEN_r33 655 +#define _CALL_LIST_APPEND_r03 656 +#define _CALL_LIST_APPEND_r13 657 +#define _CALL_LIST_APPEND_r23 658 +#define _CALL_LIST_APPEND_r33 659 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 660 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 661 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 662 +#define _CALL_METHOD_DESCRIPTOR_O_r03 663 +#define _CALL_NON_PY_GENERAL_r01 664 +#define _CALL_STR_1_r32 665 +#define _CALL_TUPLE_1_r32 666 +#define _CALL_TYPE_1_r02 667 +#define _CALL_TYPE_1_r12 668 +#define _CALL_TYPE_1_r22 669 +#define _CALL_TYPE_1_r32 670 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 671 +#define _CHECK_ATTR_CLASS_r01 672 +#define _CHECK_ATTR_CLASS_r11 673 +#define _CHECK_ATTR_CLASS_r22 674 +#define _CHECK_ATTR_CLASS_r33 675 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 676 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 677 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 678 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 679 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 680 +#define _CHECK_EG_MATCH_r22 681 +#define _CHECK_EXC_MATCH_r22 682 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 683 +#define _CHECK_FUNCTION_VERSION_r00 684 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 685 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 686 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 687 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 688 +#define _CHECK_FUNCTION_VERSION_KW_r11 689 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 690 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 691 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 692 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 693 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 694 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 695 +#define _CHECK_IS_PY_CALLABLE_EX_r03 696 +#define _CHECK_IS_PY_CALLABLE_EX_r13 697 +#define _CHECK_IS_PY_CALLABLE_EX_r23 698 +#define _CHECK_IS_PY_CALLABLE_EX_r33 699 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 700 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 701 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 702 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 703 +#define _CHECK_METHOD_VERSION_r00 704 +#define _CHECK_METHOD_VERSION_KW_r11 705 +#define _CHECK_PEP_523_r00 706 +#define _CHECK_PEP_523_r11 707 +#define _CHECK_PEP_523_r22 708 +#define _CHECK_PEP_523_r33 709 +#define _CHECK_PERIODIC_r00 710 +#define _CHECK_PERIODIC_AT_END_r00 711 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 712 +#define _CHECK_RECURSION_REMAINING_r00 713 +#define _CHECK_RECURSION_REMAINING_r11 714 +#define _CHECK_RECURSION_REMAINING_r22 715 +#define _CHECK_RECURSION_REMAINING_r33 716 +#define _CHECK_STACK_SPACE_r00 717 +#define _CHECK_STACK_SPACE_OPERAND_r00 718 +#define _CHECK_STACK_SPACE_OPERAND_r11 719 +#define _CHECK_STACK_SPACE_OPERAND_r22 720 +#define _CHECK_STACK_SPACE_OPERAND_r33 721 +#define _CHECK_VALIDITY_r00 722 +#define _CHECK_VALIDITY_r11 723 +#define _CHECK_VALIDITY_r22 724 +#define _CHECK_VALIDITY_r33 725 +#define _COLD_DYNAMIC_EXIT_r00 726 +#define _COLD_EXIT_r00 727 +#define _COMPARE_OP_r21 728 +#define _COMPARE_OP_FLOAT_r03 729 +#define _COMPARE_OP_FLOAT_r13 730 +#define _COMPARE_OP_FLOAT_r23 731 +#define _COMPARE_OP_INT_r23 732 +#define _COMPARE_OP_STR_r23 733 +#define _CONTAINS_OP_r23 734 +#define _CONTAINS_OP_DICT_r23 735 +#define _CONTAINS_OP_SET_r23 736 +#define _CONVERT_VALUE_r11 737 +#define _COPY_r01 738 +#define _COPY_1_r02 739 +#define _COPY_1_r12 740 +#define _COPY_1_r23 741 +#define _COPY_2_r03 742 +#define _COPY_2_r13 743 +#define _COPY_2_r23 744 +#define _COPY_3_r03 745 +#define _COPY_3_r13 746 +#define _COPY_3_r23 747 +#define _COPY_3_r33 748 +#define _COPY_FREE_VARS_r00 749 +#define _COPY_FREE_VARS_r11 750 +#define _COPY_FREE_VARS_r22 751 +#define _COPY_FREE_VARS_r33 752 +#define _CREATE_INIT_FRAME_r01 753 +#define _DELETE_ATTR_r10 754 +#define _DELETE_DEREF_r00 755 +#define _DELETE_FAST_r00 756 +#define _DELETE_GLOBAL_r00 757 +#define _DELETE_NAME_r00 758 +#define _DELETE_SUBSCR_r20 759 +#define _DEOPT_r00 760 +#define _DEOPT_r10 761 +#define _DEOPT_r20 762 +#define _DEOPT_r30 763 +#define _DICT_MERGE_r10 764 +#define _DICT_UPDATE_r10 765 +#define _DO_CALL_r01 766 +#define _DO_CALL_FUNCTION_EX_r31 767 +#define _DO_CALL_KW_r11 768 +#define _DYNAMIC_EXIT_r00 769 +#define _DYNAMIC_EXIT_r10 770 +#define _DYNAMIC_EXIT_r20 771 +#define _DYNAMIC_EXIT_r30 772 +#define _END_FOR_r10 773 +#define _END_SEND_r21 774 +#define _ERROR_POP_N_r00 775 +#define _EXIT_INIT_CHECK_r10 776 +#define _EXIT_TRACE_r00 777 +#define _EXIT_TRACE_r10 778 +#define _EXIT_TRACE_r20 779 +#define _EXIT_TRACE_r30 780 +#define _EXPAND_METHOD_r00 781 +#define _EXPAND_METHOD_KW_r11 782 +#define _FATAL_ERROR_r00 783 +#define _FATAL_ERROR_r11 784 +#define _FATAL_ERROR_r22 785 +#define _FATAL_ERROR_r33 786 +#define _FORMAT_SIMPLE_r11 787 +#define _FORMAT_WITH_SPEC_r21 788 +#define _FOR_ITER_r23 789 +#define _FOR_ITER_GEN_FRAME_r03 790 +#define _FOR_ITER_GEN_FRAME_r13 791 +#define _FOR_ITER_GEN_FRAME_r23 792 +#define _FOR_ITER_TIER_TWO_r23 793 +#define _GET_AITER_r11 794 +#define _GET_ANEXT_r12 795 +#define _GET_AWAITABLE_r11 796 +#define _GET_ITER_r12 797 +#define _GET_LEN_r12 798 +#define _GET_YIELD_FROM_ITER_r11 799 +#define _GUARD_BINARY_OP_EXTEND_r22 800 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 801 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 802 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 803 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 804 +#define _GUARD_BIT_IS_SET_POP_r00 805 +#define _GUARD_BIT_IS_SET_POP_r10 806 +#define _GUARD_BIT_IS_SET_POP_r21 807 +#define _GUARD_BIT_IS_SET_POP_r32 808 +#define _GUARD_BIT_IS_SET_POP_4_r00 809 +#define _GUARD_BIT_IS_SET_POP_4_r10 810 +#define _GUARD_BIT_IS_SET_POP_4_r21 811 +#define _GUARD_BIT_IS_SET_POP_4_r32 812 +#define _GUARD_BIT_IS_SET_POP_5_r00 813 +#define _GUARD_BIT_IS_SET_POP_5_r10 814 +#define _GUARD_BIT_IS_SET_POP_5_r21 815 +#define _GUARD_BIT_IS_SET_POP_5_r32 816 +#define _GUARD_BIT_IS_SET_POP_6_r00 817 +#define _GUARD_BIT_IS_SET_POP_6_r10 818 +#define _GUARD_BIT_IS_SET_POP_6_r21 819 +#define _GUARD_BIT_IS_SET_POP_6_r32 820 +#define _GUARD_BIT_IS_SET_POP_7_r00 821 +#define _GUARD_BIT_IS_SET_POP_7_r10 822 +#define _GUARD_BIT_IS_SET_POP_7_r21 823 +#define _GUARD_BIT_IS_SET_POP_7_r32 824 +#define _GUARD_BIT_IS_UNSET_POP_r00 825 +#define _GUARD_BIT_IS_UNSET_POP_r10 826 +#define _GUARD_BIT_IS_UNSET_POP_r21 827 +#define _GUARD_BIT_IS_UNSET_POP_r32 828 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 829 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 830 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 831 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 832 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 833 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 834 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 835 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 836 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 837 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 838 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 839 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 840 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 841 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 842 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 843 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 844 +#define _GUARD_CALLABLE_ISINSTANCE_r03 845 +#define _GUARD_CALLABLE_ISINSTANCE_r13 846 +#define _GUARD_CALLABLE_ISINSTANCE_r23 847 +#define _GUARD_CALLABLE_ISINSTANCE_r33 848 +#define _GUARD_CALLABLE_LEN_r03 849 +#define _GUARD_CALLABLE_LEN_r13 850 +#define _GUARD_CALLABLE_LEN_r23 851 +#define _GUARD_CALLABLE_LEN_r33 852 +#define _GUARD_CALLABLE_LIST_APPEND_r03 853 +#define _GUARD_CALLABLE_LIST_APPEND_r13 854 +#define _GUARD_CALLABLE_LIST_APPEND_r23 855 +#define _GUARD_CALLABLE_LIST_APPEND_r33 856 +#define _GUARD_CALLABLE_STR_1_r03 857 +#define _GUARD_CALLABLE_STR_1_r13 858 +#define _GUARD_CALLABLE_STR_1_r23 859 +#define _GUARD_CALLABLE_STR_1_r33 860 +#define _GUARD_CALLABLE_TUPLE_1_r03 861 +#define _GUARD_CALLABLE_TUPLE_1_r13 862 +#define _GUARD_CALLABLE_TUPLE_1_r23 863 +#define _GUARD_CALLABLE_TUPLE_1_r33 864 +#define _GUARD_CALLABLE_TYPE_1_r03 865 +#define _GUARD_CALLABLE_TYPE_1_r13 866 +#define _GUARD_CALLABLE_TYPE_1_r23 867 +#define _GUARD_CALLABLE_TYPE_1_r33 868 +#define _GUARD_CODE_VERSION_r00 869 +#define _GUARD_CODE_VERSION_r11 870 +#define _GUARD_CODE_VERSION_r22 871 +#define _GUARD_CODE_VERSION_r33 872 +#define _GUARD_DORV_NO_DICT_r01 873 +#define _GUARD_DORV_NO_DICT_r11 874 +#define _GUARD_DORV_NO_DICT_r22 875 +#define _GUARD_DORV_NO_DICT_r33 876 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 877 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 878 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 879 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 880 +#define _GUARD_GLOBALS_VERSION_r00 881 +#define _GUARD_GLOBALS_VERSION_r11 882 +#define _GUARD_GLOBALS_VERSION_r22 883 +#define _GUARD_GLOBALS_VERSION_r33 884 +#define _GUARD_IP_RETURN_GENERATOR_r00 885 +#define _GUARD_IP_RETURN_GENERATOR_r11 886 +#define _GUARD_IP_RETURN_GENERATOR_r22 887 +#define _GUARD_IP_RETURN_GENERATOR_r33 888 +#define _GUARD_IP_RETURN_VALUE_r00 889 +#define _GUARD_IP_RETURN_VALUE_r11 890 +#define _GUARD_IP_RETURN_VALUE_r22 891 +#define _GUARD_IP_RETURN_VALUE_r33 892 +#define _GUARD_IP_YIELD_VALUE_r00 893 +#define _GUARD_IP_YIELD_VALUE_r11 894 +#define _GUARD_IP_YIELD_VALUE_r22 895 +#define _GUARD_IP_YIELD_VALUE_r33 896 +#define _GUARD_IP__PUSH_FRAME_r00 897 +#define _GUARD_IP__PUSH_FRAME_r11 898 +#define _GUARD_IP__PUSH_FRAME_r22 899 +#define _GUARD_IP__PUSH_FRAME_r33 900 +#define _GUARD_IS_FALSE_POP_r00 901 +#define _GUARD_IS_FALSE_POP_r10 902 +#define _GUARD_IS_FALSE_POP_r21 903 +#define _GUARD_IS_FALSE_POP_r32 904 +#define _GUARD_IS_NONE_POP_r00 905 +#define _GUARD_IS_NONE_POP_r10 906 +#define _GUARD_IS_NONE_POP_r21 907 +#define _GUARD_IS_NONE_POP_r32 908 +#define _GUARD_IS_NOT_NONE_POP_r10 909 +#define _GUARD_IS_TRUE_POP_r00 910 +#define _GUARD_IS_TRUE_POP_r10 911 +#define _GUARD_IS_TRUE_POP_r21 912 +#define _GUARD_IS_TRUE_POP_r32 913 +#define _GUARD_KEYS_VERSION_r01 914 +#define _GUARD_KEYS_VERSION_r11 915 +#define _GUARD_KEYS_VERSION_r22 916 +#define _GUARD_KEYS_VERSION_r33 917 +#define _GUARD_NOS_ANY_DICT_r02 918 +#define _GUARD_NOS_ANY_DICT_r12 919 +#define _GUARD_NOS_ANY_DICT_r22 920 +#define _GUARD_NOS_ANY_DICT_r33 921 +#define _GUARD_NOS_COMPACT_ASCII_r02 922 +#define _GUARD_NOS_COMPACT_ASCII_r12 923 +#define _GUARD_NOS_COMPACT_ASCII_r22 924 +#define _GUARD_NOS_COMPACT_ASCII_r33 925 +#define _GUARD_NOS_DICT_r02 926 +#define _GUARD_NOS_DICT_r12 927 +#define _GUARD_NOS_DICT_r22 928 +#define _GUARD_NOS_DICT_r33 929 +#define _GUARD_NOS_FLOAT_r02 930 +#define _GUARD_NOS_FLOAT_r12 931 +#define _GUARD_NOS_FLOAT_r22 932 +#define _GUARD_NOS_FLOAT_r33 933 +#define _GUARD_NOS_INT_r02 934 +#define _GUARD_NOS_INT_r12 935 +#define _GUARD_NOS_INT_r22 936 +#define _GUARD_NOS_INT_r33 937 +#define _GUARD_NOS_LIST_r02 938 +#define _GUARD_NOS_LIST_r12 939 +#define _GUARD_NOS_LIST_r22 940 +#define _GUARD_NOS_LIST_r33 941 +#define _GUARD_NOS_NOT_NULL_r02 942 +#define _GUARD_NOS_NOT_NULL_r12 943 +#define _GUARD_NOS_NOT_NULL_r22 944 +#define _GUARD_NOS_NOT_NULL_r33 945 +#define _GUARD_NOS_NULL_r02 946 +#define _GUARD_NOS_NULL_r12 947 +#define _GUARD_NOS_NULL_r22 948 +#define _GUARD_NOS_NULL_r33 949 +#define _GUARD_NOS_OVERFLOWED_r02 950 +#define _GUARD_NOS_OVERFLOWED_r12 951 +#define _GUARD_NOS_OVERFLOWED_r22 952 +#define _GUARD_NOS_OVERFLOWED_r33 953 +#define _GUARD_NOS_TUPLE_r02 954 +#define _GUARD_NOS_TUPLE_r12 955 +#define _GUARD_NOS_TUPLE_r22 956 +#define _GUARD_NOS_TUPLE_r33 957 +#define _GUARD_NOS_UNICODE_r02 958 +#define _GUARD_NOS_UNICODE_r12 959 +#define _GUARD_NOS_UNICODE_r22 960 +#define _GUARD_NOS_UNICODE_r33 961 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 962 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 963 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 964 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 965 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 966 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 967 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 968 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 969 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 970 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 971 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 972 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 973 +#define _GUARD_THIRD_NULL_r03 974 +#define _GUARD_THIRD_NULL_r13 975 +#define _GUARD_THIRD_NULL_r23 976 +#define _GUARD_THIRD_NULL_r33 977 +#define _GUARD_TOS_ANY_DICT_r01 978 +#define _GUARD_TOS_ANY_DICT_r11 979 +#define _GUARD_TOS_ANY_DICT_r22 980 +#define _GUARD_TOS_ANY_DICT_r33 981 +#define _GUARD_TOS_ANY_SET_r01 982 +#define _GUARD_TOS_ANY_SET_r11 983 +#define _GUARD_TOS_ANY_SET_r22 984 +#define _GUARD_TOS_ANY_SET_r33 985 +#define _GUARD_TOS_DICT_r01 986 +#define _GUARD_TOS_DICT_r11 987 +#define _GUARD_TOS_DICT_r22 988 +#define _GUARD_TOS_DICT_r33 989 +#define _GUARD_TOS_FLOAT_r01 990 +#define _GUARD_TOS_FLOAT_r11 991 +#define _GUARD_TOS_FLOAT_r22 992 +#define _GUARD_TOS_FLOAT_r33 993 +#define _GUARD_TOS_FROZENDICT_r01 994 +#define _GUARD_TOS_FROZENDICT_r11 995 +#define _GUARD_TOS_FROZENDICT_r22 996 +#define _GUARD_TOS_FROZENDICT_r33 997 +#define _GUARD_TOS_FROZENSET_r01 998 +#define _GUARD_TOS_FROZENSET_r11 999 +#define _GUARD_TOS_FROZENSET_r22 1000 +#define _GUARD_TOS_FROZENSET_r33 1001 +#define _GUARD_TOS_INT_r01 1002 +#define _GUARD_TOS_INT_r11 1003 +#define _GUARD_TOS_INT_r22 1004 +#define _GUARD_TOS_INT_r33 1005 +#define _GUARD_TOS_LIST_r01 1006 +#define _GUARD_TOS_LIST_r11 1007 +#define _GUARD_TOS_LIST_r22 1008 +#define _GUARD_TOS_LIST_r33 1009 +#define _GUARD_TOS_OVERFLOWED_r01 1010 +#define _GUARD_TOS_OVERFLOWED_r11 1011 +#define _GUARD_TOS_OVERFLOWED_r22 1012 +#define _GUARD_TOS_OVERFLOWED_r33 1013 +#define _GUARD_TOS_SET_r01 1014 +#define _GUARD_TOS_SET_r11 1015 +#define _GUARD_TOS_SET_r22 1016 +#define _GUARD_TOS_SET_r33 1017 +#define _GUARD_TOS_SLICE_r01 1018 +#define _GUARD_TOS_SLICE_r11 1019 +#define _GUARD_TOS_SLICE_r22 1020 +#define _GUARD_TOS_SLICE_r33 1021 +#define _GUARD_TOS_TUPLE_r01 1022 +#define _GUARD_TOS_TUPLE_r11 1023 +#define _GUARD_TOS_TUPLE_r22 1024 +#define _GUARD_TOS_TUPLE_r33 1025 +#define _GUARD_TOS_UNICODE_r01 1026 +#define _GUARD_TOS_UNICODE_r11 1027 +#define _GUARD_TOS_UNICODE_r22 1028 +#define _GUARD_TOS_UNICODE_r33 1029 +#define _GUARD_TYPE_VERSION_r01 1030 +#define _GUARD_TYPE_VERSION_r11 1031 +#define _GUARD_TYPE_VERSION_r22 1032 +#define _GUARD_TYPE_VERSION_r33 1033 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1034 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1035 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1036 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1037 +#define _HANDLE_PENDING_AND_DEOPT_r00 1038 +#define _HANDLE_PENDING_AND_DEOPT_r10 1039 +#define _HANDLE_PENDING_AND_DEOPT_r20 1040 +#define _HANDLE_PENDING_AND_DEOPT_r30 1041 +#define _IMPORT_FROM_r12 1042 +#define _IMPORT_NAME_r21 1043 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1044 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1045 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1046 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1047 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1048 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1049 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1050 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1051 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1052 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1053 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1054 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1055 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1056 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1057 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1058 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1059 +#define _INSERT_NULL_r10 1060 +#define _INSTRUMENTED_FOR_ITER_r23 1061 +#define _INSTRUMENTED_INSTRUCTION_r00 1062 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1063 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1064 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1065 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1066 +#define _INSTRUMENTED_LINE_r00 1067 +#define _INSTRUMENTED_NOT_TAKEN_r00 1068 +#define _INSTRUMENTED_NOT_TAKEN_r11 1069 +#define _INSTRUMENTED_NOT_TAKEN_r22 1070 +#define _INSTRUMENTED_NOT_TAKEN_r33 1071 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1072 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1073 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1074 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1075 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1076 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1077 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1078 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1079 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1080 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1081 +#define _IS_NONE_r11 1082 +#define _IS_OP_r03 1083 +#define _IS_OP_r13 1084 +#define _IS_OP_r23 1085 +#define _ITER_CHECK_LIST_r02 1086 +#define _ITER_CHECK_LIST_r12 1087 +#define _ITER_CHECK_LIST_r22 1088 +#define _ITER_CHECK_LIST_r33 1089 +#define _ITER_CHECK_RANGE_r02 1090 +#define _ITER_CHECK_RANGE_r12 1091 +#define _ITER_CHECK_RANGE_r22 1092 +#define _ITER_CHECK_RANGE_r33 1093 +#define _ITER_CHECK_TUPLE_r02 1094 +#define _ITER_CHECK_TUPLE_r12 1095 +#define _ITER_CHECK_TUPLE_r22 1096 +#define _ITER_CHECK_TUPLE_r33 1097 +#define _ITER_JUMP_LIST_r02 1098 +#define _ITER_JUMP_LIST_r12 1099 +#define _ITER_JUMP_LIST_r22 1100 +#define _ITER_JUMP_LIST_r33 1101 +#define _ITER_JUMP_RANGE_r02 1102 +#define _ITER_JUMP_RANGE_r12 1103 +#define _ITER_JUMP_RANGE_r22 1104 +#define _ITER_JUMP_RANGE_r33 1105 +#define _ITER_JUMP_TUPLE_r02 1106 +#define _ITER_JUMP_TUPLE_r12 1107 +#define _ITER_JUMP_TUPLE_r22 1108 +#define _ITER_JUMP_TUPLE_r33 1109 +#define _ITER_NEXT_LIST_r23 1110 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1111 +#define _ITER_NEXT_RANGE_r03 1112 +#define _ITER_NEXT_RANGE_r13 1113 +#define _ITER_NEXT_RANGE_r23 1114 +#define _ITER_NEXT_TUPLE_r03 1115 +#define _ITER_NEXT_TUPLE_r13 1116 +#define _ITER_NEXT_TUPLE_r23 1117 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1118 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1119 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1120 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1121 +#define _JUMP_TO_TOP_r00 1122 +#define _LIST_APPEND_r10 1123 +#define _LIST_EXTEND_r10 1124 +#define _LOAD_ATTR_r10 1125 +#define _LOAD_ATTR_CLASS_r11 1126 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1127 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1128 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1129 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1130 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1131 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1132 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1133 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1134 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1135 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1136 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1137 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1138 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1139 +#define _LOAD_ATTR_MODULE_r12 1140 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1141 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1142 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1143 +#define _LOAD_ATTR_SLOT_r02 1144 +#define _LOAD_ATTR_SLOT_r12 1145 +#define _LOAD_ATTR_SLOT_r23 1146 +#define _LOAD_ATTR_WITH_HINT_r12 1147 +#define _LOAD_BUILD_CLASS_r01 1148 +#define _LOAD_BYTECODE_r00 1149 +#define _LOAD_COMMON_CONSTANT_r01 1150 +#define _LOAD_COMMON_CONSTANT_r12 1151 +#define _LOAD_COMMON_CONSTANT_r23 1152 +#define _LOAD_CONST_r01 1153 +#define _LOAD_CONST_r12 1154 +#define _LOAD_CONST_r23 1155 +#define _LOAD_CONST_INLINE_r01 1156 +#define _LOAD_CONST_INLINE_r12 1157 +#define _LOAD_CONST_INLINE_r23 1158 +#define _LOAD_CONST_INLINE_BORROW_r01 1159 +#define _LOAD_CONST_INLINE_BORROW_r12 1160 +#define _LOAD_CONST_INLINE_BORROW_r23 1161 +#define _LOAD_CONST_UNDER_INLINE_r02 1162 +#define _LOAD_CONST_UNDER_INLINE_r12 1163 +#define _LOAD_CONST_UNDER_INLINE_r23 1164 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1165 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1166 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1167 +#define _LOAD_DEREF_r01 1168 +#define _LOAD_FAST_r01 1169 +#define _LOAD_FAST_r12 1170 +#define _LOAD_FAST_r23 1171 +#define _LOAD_FAST_0_r01 1172 +#define _LOAD_FAST_0_r12 1173 +#define _LOAD_FAST_0_r23 1174 +#define _LOAD_FAST_1_r01 1175 +#define _LOAD_FAST_1_r12 1176 +#define _LOAD_FAST_1_r23 1177 +#define _LOAD_FAST_2_r01 1178 +#define _LOAD_FAST_2_r12 1179 +#define _LOAD_FAST_2_r23 1180 +#define _LOAD_FAST_3_r01 1181 +#define _LOAD_FAST_3_r12 1182 +#define _LOAD_FAST_3_r23 1183 +#define _LOAD_FAST_4_r01 1184 +#define _LOAD_FAST_4_r12 1185 +#define _LOAD_FAST_4_r23 1186 +#define _LOAD_FAST_5_r01 1187 +#define _LOAD_FAST_5_r12 1188 +#define _LOAD_FAST_5_r23 1189 +#define _LOAD_FAST_6_r01 1190 +#define _LOAD_FAST_6_r12 1191 +#define _LOAD_FAST_6_r23 1192 +#define _LOAD_FAST_7_r01 1193 +#define _LOAD_FAST_7_r12 1194 +#define _LOAD_FAST_7_r23 1195 +#define _LOAD_FAST_AND_CLEAR_r01 1196 +#define _LOAD_FAST_AND_CLEAR_r12 1197 +#define _LOAD_FAST_AND_CLEAR_r23 1198 +#define _LOAD_FAST_BORROW_r01 1199 +#define _LOAD_FAST_BORROW_r12 1200 +#define _LOAD_FAST_BORROW_r23 1201 +#define _LOAD_FAST_BORROW_0_r01 1202 +#define _LOAD_FAST_BORROW_0_r12 1203 +#define _LOAD_FAST_BORROW_0_r23 1204 +#define _LOAD_FAST_BORROW_1_r01 1205 +#define _LOAD_FAST_BORROW_1_r12 1206 +#define _LOAD_FAST_BORROW_1_r23 1207 +#define _LOAD_FAST_BORROW_2_r01 1208 +#define _LOAD_FAST_BORROW_2_r12 1209 +#define _LOAD_FAST_BORROW_2_r23 1210 +#define _LOAD_FAST_BORROW_3_r01 1211 +#define _LOAD_FAST_BORROW_3_r12 1212 +#define _LOAD_FAST_BORROW_3_r23 1213 +#define _LOAD_FAST_BORROW_4_r01 1214 +#define _LOAD_FAST_BORROW_4_r12 1215 +#define _LOAD_FAST_BORROW_4_r23 1216 +#define _LOAD_FAST_BORROW_5_r01 1217 +#define _LOAD_FAST_BORROW_5_r12 1218 +#define _LOAD_FAST_BORROW_5_r23 1219 +#define _LOAD_FAST_BORROW_6_r01 1220 +#define _LOAD_FAST_BORROW_6_r12 1221 +#define _LOAD_FAST_BORROW_6_r23 1222 +#define _LOAD_FAST_BORROW_7_r01 1223 +#define _LOAD_FAST_BORROW_7_r12 1224 +#define _LOAD_FAST_BORROW_7_r23 1225 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1226 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1227 +#define _LOAD_FAST_CHECK_r01 1228 +#define _LOAD_FAST_CHECK_r12 1229 +#define _LOAD_FAST_CHECK_r23 1230 +#define _LOAD_FAST_LOAD_FAST_r02 1231 +#define _LOAD_FAST_LOAD_FAST_r13 1232 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1233 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1234 +#define _LOAD_GLOBAL_r00 1235 +#define _LOAD_GLOBAL_BUILTINS_r01 1236 +#define _LOAD_GLOBAL_MODULE_r01 1237 +#define _LOAD_LOCALS_r01 1238 +#define _LOAD_LOCALS_r12 1239 +#define _LOAD_LOCALS_r23 1240 +#define _LOAD_NAME_r01 1241 +#define _LOAD_SMALL_INT_r01 1242 +#define _LOAD_SMALL_INT_r12 1243 +#define _LOAD_SMALL_INT_r23 1244 +#define _LOAD_SMALL_INT_0_r01 1245 +#define _LOAD_SMALL_INT_0_r12 1246 +#define _LOAD_SMALL_INT_0_r23 1247 +#define _LOAD_SMALL_INT_1_r01 1248 +#define _LOAD_SMALL_INT_1_r12 1249 +#define _LOAD_SMALL_INT_1_r23 1250 +#define _LOAD_SMALL_INT_2_r01 1251 +#define _LOAD_SMALL_INT_2_r12 1252 +#define _LOAD_SMALL_INT_2_r23 1253 +#define _LOAD_SMALL_INT_3_r01 1254 +#define _LOAD_SMALL_INT_3_r12 1255 +#define _LOAD_SMALL_INT_3_r23 1256 +#define _LOAD_SPECIAL_r00 1257 +#define _LOAD_SUPER_ATTR_ATTR_r31 1258 +#define _LOAD_SUPER_ATTR_METHOD_r32 1259 +#define _LOCK_OBJECT_r01 1260 +#define _LOCK_OBJECT_r11 1261 +#define _LOCK_OBJECT_r22 1262 +#define _LOCK_OBJECT_r33 1263 +#define _MAKE_CALLARGS_A_TUPLE_r33 1264 +#define _MAKE_CELL_r00 1265 +#define _MAKE_FUNCTION_r11 1266 +#define _MAKE_HEAP_SAFE_r01 1267 +#define _MAKE_HEAP_SAFE_r11 1268 +#define _MAKE_HEAP_SAFE_r22 1269 +#define _MAKE_HEAP_SAFE_r33 1270 +#define _MAKE_WARM_r00 1271 +#define _MAKE_WARM_r11 1272 +#define _MAKE_WARM_r22 1273 +#define _MAKE_WARM_r33 1274 +#define _MAP_ADD_r20 1275 +#define _MATCH_CLASS_r33 1276 +#define _MATCH_KEYS_r23 1277 +#define _MATCH_MAPPING_r02 1278 +#define _MATCH_MAPPING_r12 1279 +#define _MATCH_MAPPING_r23 1280 +#define _MATCH_SEQUENCE_r02 1281 +#define _MATCH_SEQUENCE_r12 1282 +#define _MATCH_SEQUENCE_r23 1283 +#define _MAYBE_EXPAND_METHOD_r00 1284 +#define _MAYBE_EXPAND_METHOD_KW_r11 1285 +#define _MONITOR_CALL_r00 1286 +#define _MONITOR_CALL_KW_r11 1287 +#define _MONITOR_JUMP_BACKWARD_r00 1288 +#define _MONITOR_JUMP_BACKWARD_r11 1289 +#define _MONITOR_JUMP_BACKWARD_r22 1290 +#define _MONITOR_JUMP_BACKWARD_r33 1291 +#define _MONITOR_RESUME_r00 1292 +#define _NOP_r00 1293 +#define _NOP_r11 1294 +#define _NOP_r22 1295 +#define _NOP_r33 1296 +#define _POP_CALL_r20 1297 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1298 +#define _POP_CALL_ONE_r30 1299 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1300 +#define _POP_CALL_TWO_r30 1301 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1302 +#define _POP_EXCEPT_r10 1303 +#define _POP_ITER_r20 1304 +#define _POP_JUMP_IF_FALSE_r00 1305 +#define _POP_JUMP_IF_FALSE_r10 1306 +#define _POP_JUMP_IF_FALSE_r21 1307 +#define _POP_JUMP_IF_FALSE_r32 1308 +#define _POP_JUMP_IF_TRUE_r00 1309 +#define _POP_JUMP_IF_TRUE_r10 1310 +#define _POP_JUMP_IF_TRUE_r21 1311 +#define _POP_JUMP_IF_TRUE_r32 1312 +#define _POP_TOP_r10 1313 +#define _POP_TOP_FLOAT_r00 1314 +#define _POP_TOP_FLOAT_r10 1315 +#define _POP_TOP_FLOAT_r21 1316 +#define _POP_TOP_FLOAT_r32 1317 +#define _POP_TOP_INT_r00 1318 +#define _POP_TOP_INT_r10 1319 +#define _POP_TOP_INT_r21 1320 +#define _POP_TOP_INT_r32 1321 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1322 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1323 +#define _POP_TOP_NOP_r00 1324 +#define _POP_TOP_NOP_r10 1325 +#define _POP_TOP_NOP_r21 1326 +#define _POP_TOP_NOP_r32 1327 +#define _POP_TOP_UNICODE_r00 1328 +#define _POP_TOP_UNICODE_r10 1329 +#define _POP_TOP_UNICODE_r21 1330 +#define _POP_TOP_UNICODE_r32 1331 +#define _POP_TWO_r20 1332 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1333 +#define _PUSH_EXC_INFO_r02 1334 +#define _PUSH_EXC_INFO_r12 1335 +#define _PUSH_EXC_INFO_r23 1336 +#define _PUSH_FRAME_r10 1337 +#define _PUSH_NULL_r01 1338 +#define _PUSH_NULL_r12 1339 +#define _PUSH_NULL_r23 1340 +#define _PUSH_NULL_CONDITIONAL_r00 1341 +#define _PY_FRAME_EX_r31 1342 +#define _PY_FRAME_GENERAL_r01 1343 +#define _PY_FRAME_KW_r11 1344 +#define _QUICKEN_RESUME_r00 1345 +#define _QUICKEN_RESUME_r11 1346 +#define _QUICKEN_RESUME_r22 1347 +#define _QUICKEN_RESUME_r33 1348 +#define _REPLACE_WITH_TRUE_r02 1349 +#define _REPLACE_WITH_TRUE_r12 1350 +#define _REPLACE_WITH_TRUE_r23 1351 +#define _RESUME_CHECK_r00 1352 +#define _RESUME_CHECK_r11 1353 +#define _RESUME_CHECK_r22 1354 +#define _RESUME_CHECK_r33 1355 +#define _RETURN_GENERATOR_r01 1356 +#define _RETURN_VALUE_r11 1357 +#define _SAVE_RETURN_OFFSET_r00 1358 +#define _SAVE_RETURN_OFFSET_r11 1359 +#define _SAVE_RETURN_OFFSET_r22 1360 +#define _SAVE_RETURN_OFFSET_r33 1361 +#define _SEND_r22 1362 +#define _SEND_GEN_FRAME_r22 1363 +#define _SETUP_ANNOTATIONS_r00 1364 +#define _SET_ADD_r10 1365 +#define _SET_FUNCTION_ATTRIBUTE_r01 1366 +#define _SET_FUNCTION_ATTRIBUTE_r11 1367 +#define _SET_FUNCTION_ATTRIBUTE_r21 1368 +#define _SET_FUNCTION_ATTRIBUTE_r32 1369 +#define _SET_IP_r00 1370 +#define _SET_IP_r11 1371 +#define _SET_IP_r22 1372 +#define _SET_IP_r33 1373 +#define _SET_UPDATE_r10 1374 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1375 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1376 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1377 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1378 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1379 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1380 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1381 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1382 +#define _SPILL_OR_RELOAD_r01 1383 +#define _SPILL_OR_RELOAD_r02 1384 +#define _SPILL_OR_RELOAD_r03 1385 +#define _SPILL_OR_RELOAD_r10 1386 +#define _SPILL_OR_RELOAD_r12 1387 +#define _SPILL_OR_RELOAD_r13 1388 +#define _SPILL_OR_RELOAD_r20 1389 +#define _SPILL_OR_RELOAD_r21 1390 +#define _SPILL_OR_RELOAD_r23 1391 +#define _SPILL_OR_RELOAD_r30 1392 +#define _SPILL_OR_RELOAD_r31 1393 +#define _SPILL_OR_RELOAD_r32 1394 +#define _START_EXECUTOR_r00 1395 +#define _STORE_ATTR_r20 1396 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1397 +#define _STORE_ATTR_SLOT_r21 1398 +#define _STORE_ATTR_WITH_HINT_r21 1399 +#define _STORE_DEREF_r10 1400 +#define _STORE_FAST_LOAD_FAST_r11 1401 +#define _STORE_FAST_STORE_FAST_r20 1402 +#define _STORE_GLOBAL_r10 1403 +#define _STORE_NAME_r10 1404 +#define _STORE_SLICE_r30 1405 +#define _STORE_SUBSCR_r30 1406 +#define _STORE_SUBSCR_DICT_r31 1407 +#define _STORE_SUBSCR_LIST_INT_r32 1408 +#define _SWAP_r11 1409 +#define _SWAP_2_r02 1410 +#define _SWAP_2_r12 1411 +#define _SWAP_2_r22 1412 +#define _SWAP_2_r33 1413 +#define _SWAP_3_r03 1414 +#define _SWAP_3_r13 1415 +#define _SWAP_3_r23 1416 +#define _SWAP_3_r33 1417 +#define _SWAP_FAST_r01 1418 +#define _SWAP_FAST_r11 1419 +#define _SWAP_FAST_r22 1420 +#define _SWAP_FAST_r33 1421 +#define _SWAP_FAST_0_r01 1422 +#define _SWAP_FAST_0_r11 1423 +#define _SWAP_FAST_0_r22 1424 +#define _SWAP_FAST_0_r33 1425 +#define _SWAP_FAST_1_r01 1426 +#define _SWAP_FAST_1_r11 1427 +#define _SWAP_FAST_1_r22 1428 +#define _SWAP_FAST_1_r33 1429 +#define _SWAP_FAST_2_r01 1430 +#define _SWAP_FAST_2_r11 1431 +#define _SWAP_FAST_2_r22 1432 +#define _SWAP_FAST_2_r33 1433 +#define _SWAP_FAST_3_r01 1434 +#define _SWAP_FAST_3_r11 1435 +#define _SWAP_FAST_3_r22 1436 +#define _SWAP_FAST_3_r33 1437 +#define _SWAP_FAST_4_r01 1438 +#define _SWAP_FAST_4_r11 1439 +#define _SWAP_FAST_4_r22 1440 +#define _SWAP_FAST_4_r33 1441 +#define _SWAP_FAST_5_r01 1442 +#define _SWAP_FAST_5_r11 1443 +#define _SWAP_FAST_5_r22 1444 +#define _SWAP_FAST_5_r33 1445 +#define _SWAP_FAST_6_r01 1446 +#define _SWAP_FAST_6_r11 1447 +#define _SWAP_FAST_6_r22 1448 +#define _SWAP_FAST_6_r33 1449 +#define _SWAP_FAST_7_r01 1450 +#define _SWAP_FAST_7_r11 1451 +#define _SWAP_FAST_7_r22 1452 +#define _SWAP_FAST_7_r33 1453 +#define _TIER2_RESUME_CHECK_r00 1454 +#define _TIER2_RESUME_CHECK_r11 1455 +#define _TIER2_RESUME_CHECK_r22 1456 +#define _TIER2_RESUME_CHECK_r33 1457 +#define _TO_BOOL_r11 1458 +#define _TO_BOOL_BOOL_r01 1459 +#define _TO_BOOL_BOOL_r11 1460 +#define _TO_BOOL_BOOL_r22 1461 +#define _TO_BOOL_BOOL_r33 1462 +#define _TO_BOOL_INT_r02 1463 +#define _TO_BOOL_INT_r12 1464 +#define _TO_BOOL_INT_r23 1465 +#define _TO_BOOL_LIST_r02 1466 +#define _TO_BOOL_LIST_r12 1467 +#define _TO_BOOL_LIST_r23 1468 +#define _TO_BOOL_NONE_r01 1469 +#define _TO_BOOL_NONE_r11 1470 +#define _TO_BOOL_NONE_r22 1471 +#define _TO_BOOL_NONE_r33 1472 +#define _TO_BOOL_STR_r02 1473 +#define _TO_BOOL_STR_r12 1474 +#define _TO_BOOL_STR_r23 1475 +#define _TRACE_RECORD_r00 1476 +#define _UNARY_INVERT_r12 1477 +#define _UNARY_NEGATIVE_r12 1478 +#define _UNARY_NOT_r01 1479 +#define _UNARY_NOT_r11 1480 +#define _UNARY_NOT_r22 1481 +#define _UNARY_NOT_r33 1482 +#define _UNPACK_EX_r10 1483 +#define _UNPACK_SEQUENCE_r10 1484 +#define _UNPACK_SEQUENCE_LIST_r10 1485 +#define _UNPACK_SEQUENCE_TUPLE_r10 1486 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1487 +#define _WITH_EXCEPT_START_r33 1488 +#define _YIELD_VALUE_r11 1489 +#define MAX_UOP_REGS_ID 1489 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 9a0852f872d..ce7ea4c3a77 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -140,7 +140,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_STORE_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DELETE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_MAKE_HEAP_SAFE] = 0, [_RETURN_VALUE] = HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG, @@ -1354,7 +1354,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { .best = { 1, 1, 1, 1 }, .entries = { { -1, -1, -1 }, - { 1, 1, _CALL_INTRINSIC_1_r11 }, + { 2, 1, _CALL_INTRINSIC_1_r12 }, { -1, -1, -1 }, { -1, -1, -1 }, }, @@ -3822,7 +3822,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_STORE_SUBSCR_LIST_INT_r32] = _STORE_SUBSCR_LIST_INT, [_STORE_SUBSCR_DICT_r31] = _STORE_SUBSCR_DICT, [_DELETE_SUBSCR_r20] = _DELETE_SUBSCR, - [_CALL_INTRINSIC_1_r11] = _CALL_INTRINSIC_1, + [_CALL_INTRINSIC_1_r12] = _CALL_INTRINSIC_1, [_CALL_INTRINSIC_2_r21] = _CALL_INTRINSIC_2, [_MAKE_HEAP_SAFE_r01] = _MAKE_HEAP_SAFE, [_MAKE_HEAP_SAFE_r11] = _MAKE_HEAP_SAFE, @@ -4441,7 +4441,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CALL_FUNCTION_EX_NON_PY_GENERAL] = "_CALL_FUNCTION_EX_NON_PY_GENERAL", [_CALL_FUNCTION_EX_NON_PY_GENERAL_r31] = "_CALL_FUNCTION_EX_NON_PY_GENERAL_r31", [_CALL_INTRINSIC_1] = "_CALL_INTRINSIC_1", - [_CALL_INTRINSIC_1_r11] = "_CALL_INTRINSIC_1_r11", + [_CALL_INTRINSIC_1_r12] = "_CALL_INTRINSIC_1_r12", [_CALL_INTRINSIC_2] = "_CALL_INTRINSIC_2", [_CALL_INTRINSIC_2_r21] = "_CALL_INTRINSIC_2_r21", [_CALL_ISINSTANCE] = "_CALL_ISINSTANCE", diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index e5fada1f40c..d66031ed31c 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2546,6 +2546,21 @@ def testfunc(n): self.assertIn("_POP_TOP_NOP", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 4) + def test_call_intrinsic_1(self): + def testfunc(n): + x = 0 + for _ in range(n): + +x + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 0) + uops = get_opnames(ex) + + self.assertIn("_CALL_INTRINSIC_1", uops) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 1) + self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + def test_get_len_with_const_tuple(self): def testfunc(n): x = 0.0 diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 9e86bc42f20..2f6845399d9 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -2982,23 +2982,28 @@ INSTRUCTION_STATS(CALL_INTRINSIC_1); _PyStackRef value; _PyStackRef res; - value = stack_pointer[-1]; - assert(oparg <= MAX_INTRINSIC_1); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(value); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (res_o == NULL) { - JUMP_TO_LABEL(error); + _PyStackRef v; + // _CALL_INTRINSIC_1 + { + value = stack_pointer[-1]; + assert(oparg <= MAX_INTRINSIC_1); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + JUMP_TO_LABEL(error); + } + v = value; + res = PyStackRef_FromPyObjectSteal(res_o); + } + // _POP_TOP + { + value = v; + stack_pointer[-1] = res; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 43a512611fb..c26ba89b5ab 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1246,14 +1246,19 @@ dummy_func( ERROR_IF(err); } - inst(CALL_INTRINSIC_1, (value -- res)) { + op(_CALL_INTRINSIC_1, (value -- res, v)) { assert(oparg <= MAX_INTRINSIC_1); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); - PyStackRef_CLOSE(value); - ERROR_IF(res_o == NULL); + if (res_o == NULL) { + ERROR_NO_POP(); + } + v = value; + DEAD(value); res = PyStackRef_FromPyObjectSteal(res_o); } + macro(CALL_INTRINSIC_1) = _CALL_INTRINSIC_1 + POP_TOP; + inst(CALL_INTRINSIC_2, (value2_st, value1_st -- res)) { assert(oparg <= MAX_INTRINSIC_2); PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 7a698e422ab..f00913cd359 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -6833,11 +6833,12 @@ break; } - case _CALL_INTRINSIC_1_r11: { + case _CALL_INTRINSIC_1_r12: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); _PyStackRef value; _PyStackRef res; + _PyStackRef v; _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); value = _stack_item_0; @@ -6848,20 +6849,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(value); - stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } + v = value; res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache1 = v; _tos_cache0 = res; - _tos_cache1 = PyStackRef_ZERO_BITS; _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 72619fd3afa..30f0101d2ed 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2982,23 +2982,28 @@ INSTRUCTION_STATS(CALL_INTRINSIC_1); _PyStackRef value; _PyStackRef res; - value = stack_pointer[-1]; - assert(oparg <= MAX_INTRINSIC_1); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(value); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (res_o == NULL) { - JUMP_TO_LABEL(error); + _PyStackRef v; + // _CALL_INTRINSIC_1 + { + value = stack_pointer[-1]; + assert(oparg <= MAX_INTRINSIC_1); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + JUMP_TO_LABEL(error); + } + v = value; + res = PyStackRef_FromPyObjectSteal(res_o); + } + // _POP_TOP + { + value = v; + stack_pointer[-1] = res; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_XCLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); } - res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); DISPATCH(); } diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 6092da8c04e..e0410be5565 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1177,6 +1177,11 @@ dummy_func(void) { } } + op(_CALL_INTRINSIC_1, (value -- res, v)) { + res = sym_new_not_null(ctx); + v = value; + } + op(_GUARD_IS_TRUE_POP, (flag -- )) { sym_apply_predicate_narrowing(ctx, flag, true); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 2df50ebbcaa..7e5b26c6d72 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1293,9 +1293,17 @@ } case _CALL_INTRINSIC_1: { + JitOptRef value; JitOptRef res; + JitOptRef v; + value = stack_pointer[-1]; res = sym_new_not_null(ctx); + v = value; + CHECK_STACK_BOUNDS(1); stack_pointer[-1] = res; + stack_pointer[0] = v; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); break; } From e6b9a1406980fbb1d4032eca9cc0b4f8f252b716 Mon Sep 17 00:00:00 2001 From: Ramin Farajpour Cami Date: Mon, 16 Mar 2026 16:00:13 +0330 Subject: [PATCH 154/775] gh-144984: Fix crash in Expat's `ExternalEntityParserCreate` error paths (#144992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/test/test_pyexpat.py | 37 +++++++++++++++++++ ...19-12-00-00.gh-issue-144984.b93995c982.rst | 3 ++ Modules/pyexpat.c | 16 ++++---- 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index f8afc16d3cb..c67bfc67479 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -843,6 +843,43 @@ def test_parent_parser_outlives_its_subparsers__chain(self): del subparser +class ExternalEntityParserCreateErrorTest(unittest.TestCase): + """ExternalEntityParserCreate error paths should not crash or leak + refcounts on the parent parser. + + See https://github.com/python/cpython/issues/144984. + """ + + @classmethod + def setUpClass(cls): + cls.testcapi = import_helper.import_module('_testcapi') + + def test_error_path_no_crash(self): + # When an allocation inside ExternalEntityParserCreate fails, + # the partially-initialized subparser is deallocated. This + # must not dereference NULL handlers or double-decrement the + # parent parser's refcount. + parser = expat.ParserCreate() + parser.buffer_text = True + rc_before = sys.getrefcount(parser) + + # We avoid self.assertRaises(MemoryError) here because the + # context manager itself needs memory allocations that fail + # while the nomemory hook is active. + self.testcapi.set_nomemory(1, 10) + raised = False + try: + parser.ExternalEntityParserCreate(None) + except MemoryError: + raised = True + finally: + self.testcapi.remove_mem_hooks() + self.assertTrue(raised, "MemoryError not raised") + + rc_after = sys.getrefcount(parser) + self.assertEqual(rc_after, rc_before) + + class ReparseDeferralTest(unittest.TestCase): def test_getter_setter_round_trip(self): parser = expat.ParserCreate() diff --git a/Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst b/Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst new file mode 100644 index 00000000000..66e07dc3098 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst @@ -0,0 +1,3 @@ +Fix crash in :meth:`xml.parsers.expat.xmlparser.ExternalEntityParserCreate` +when an allocation fails. The error paths could dereference NULL ``handlers`` +and double-decrement the parent parser's reference count. diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index cadc6706243..782e552f342 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1083,11 +1083,6 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, return NULL; } - // The new subparser will make use of the parent XML_Parser inside of Expat. - // So we need to take subparsers into account with the reference counting - // of their parent parser. - Py_INCREF(self); - new_parser->buffer_size = self->buffer_size; new_parser->buffer_used = 0; new_parser->buffer = NULL; @@ -1097,7 +1092,10 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, new_parser->ns_prefixes = self->ns_prefixes; new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context, encoding); - new_parser->parent = (PyObject *)self; + // The new subparser will make use of the parent XML_Parser inside of Expat. + // So we need to take subparsers into account with the reference counting + // of their parent parser. + new_parser->parent = Py_NewRef(self); new_parser->handlers = 0; new_parser->intern = Py_XNewRef(self->intern); @@ -1105,13 +1103,11 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, new_parser->buffer = PyMem_Malloc(new_parser->buffer_size); if (new_parser->buffer == NULL) { Py_DECREF(new_parser); - Py_DECREF(self); return PyErr_NoMemory(); } } if (!new_parser->itself) { Py_DECREF(new_parser); - Py_DECREF(self); return PyErr_NoMemory(); } @@ -1125,7 +1121,6 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, new_parser->handlers = PyMem_New(PyObject *, i); if (!new_parser->handlers) { Py_DECREF(new_parser); - Py_DECREF(self); return PyErr_NoMemory(); } clear_handlers(new_parser, 1); @@ -2496,6 +2491,9 @@ PyInit_pyexpat(void) static void clear_handlers(xmlparseobject *self, int initial) { + if (self->handlers == NULL) { + return; + } for (size_t i = 0; handler_info[i].name != NULL; i++) { if (initial) { self->handlers[i] = NULL; From 77632f085d0cec29c7576b8528849276109801a1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 16 Mar 2026 14:19:00 +0100 Subject: [PATCH 155/775] gh-141510: Avoid critical section on frozendict copy (#145920) --- Objects/dictobject.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 842d9be73b8..08e40bf84c4 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -968,7 +968,9 @@ clone_combined_dict_keys(PyDictObject *orig) assert(orig->ma_keys != Py_EMPTY_KEYS); assert(orig->ma_keys->dk_refcnt == 1); - ASSERT_DICT_LOCKED(orig); + if (!PyFrozenDict_Check(orig)) { + ASSERT_DICT_LOCKED(orig); + } size_t keys_size = _PyDict_KeysSize(orig->ma_keys); PyDictKeysObject *keys = PyMem_Malloc(keys_size); @@ -4322,7 +4324,10 @@ copy_lock_held(PyObject *o, int as_frozendict) PyObject *copy; PyDictObject *mp; - ASSERT_DICT_LOCKED(o); + // frozendict is immutable and so doesn't need critical section + if (!PyFrozenDict_Check(o)) { + ASSERT_DICT_LOCKED(o); + } mp = (PyDictObject *)o; if (mp->ma_used == 0) { @@ -4445,9 +4450,14 @@ anydict_copy(PyObject *o) assert(PyAnyDict_Check(o)); PyObject *res; - Py_BEGIN_CRITICAL_SECTION(o); - res = copy_lock_held(o, PyFrozenDict_Check(o)); - Py_END_CRITICAL_SECTION(); + if (PyFrozenDict_Check(o)) { + res = copy_lock_held(o, 1); + } + else { + Py_BEGIN_CRITICAL_SECTION(o); + res = copy_lock_held(o, 0); + Py_END_CRITICAL_SECTION(); + } return res; } @@ -4459,9 +4469,14 @@ _PyDict_CopyAsDict(PyObject *o) assert(PyAnyDict_Check(o)); PyObject *res; - Py_BEGIN_CRITICAL_SECTION(o); - res = copy_lock_held(o, 0); - Py_END_CRITICAL_SECTION(); + if (PyFrozenDict_Check(o)) { + res = copy_lock_held(o, 0); + } + else { + Py_BEGIN_CRITICAL_SECTION(o); + res = copy_lock_held(o, 0); + Py_END_CRITICAL_SECTION(); + } return res; } From 57e88c1cf95e1481b94ae57abe1010469d47a6b4 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:43:43 +0000 Subject: [PATCH 156/775] gh-145599, CVE 2026-3644: Reject control characters in `http.cookies.Morsel.update()` (#145600) Reject control characters in `http.cookies.Morsel.update()` and `http.cookies.BaseCookie.js_output`. Co-authored-by: Victor Stinner Co-authored-by: Victor Stinner --- Lib/http/cookies.py | 24 ++++++++++-- Lib/test/test_http_cookies.py | 38 +++++++++++++++++++ ...-03-06-17-03-38.gh-issue-145599.kchwZV.rst | 4 ++ 3 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 917280037d4..76954111699 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -337,9 +337,16 @@ def update(self, values): key = key.lower() if key not in self._reserved: raise CookieError("Invalid attribute %r" % (key,)) + if _has_control_character(key, val): + raise CookieError("Control characters are not allowed in " + f"cookies {key!r} {val!r}") data[key] = val dict.update(self, data) + def __ior__(self, values): + self.update(values) + return self + def isReservedKey(self, K): return K.lower() in self._reserved @@ -365,9 +372,15 @@ def __getstate__(self): } def __setstate__(self, state): - self._key = state['key'] - self._value = state['value'] - self._coded_value = state['coded_value'] + key = state['key'] + value = state['value'] + coded_value = state['coded_value'] + if _has_control_character(key, value, coded_value): + raise CookieError("Control characters are not allowed in cookies " + f"{key!r} {value!r} {coded_value!r}") + self._key = key + self._value = value + self._coded_value = coded_value def output(self, attrs=None, header="Set-Cookie:"): return "%s %s" % (header, self.OutputString(attrs)) @@ -379,13 +392,16 @@ def __repr__(self): def js_output(self, attrs=None): # Print javascript + output_string = self.OutputString(attrs) + if _has_control_character(output_string): + raise CookieError("Control characters are not allowed in cookies") return """ - """ % (self.OutputString(attrs).replace('"', r'\"')) + """ % (output_string.replace('"', r'\"')) def OutputString(self, attrs=None): # Build up our result diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 7d072d5fd67..e2c7551c0b3 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -604,6 +604,14 @@ def test_control_characters(self): with self.assertRaises(cookies.CookieError): morsel["path"] = c0 + # .__setstate__() + with self.assertRaises(cookies.CookieError): + morsel.__setstate__({'key': c0, 'value': 'val', 'coded_value': 'coded'}) + with self.assertRaises(cookies.CookieError): + morsel.__setstate__({'key': 'key', 'value': c0, 'coded_value': 'coded'}) + with self.assertRaises(cookies.CookieError): + morsel.__setstate__({'key': 'key', 'value': 'val', 'coded_value': c0}) + # .setdefault() with self.assertRaises(cookies.CookieError): morsel.setdefault("path", c0) @@ -618,6 +626,18 @@ def test_control_characters(self): with self.assertRaises(cookies.CookieError): morsel.set("path", "val", c0) + # .update() + with self.assertRaises(cookies.CookieError): + morsel.update({"path": c0}) + with self.assertRaises(cookies.CookieError): + morsel.update({c0: "val"}) + + # .__ior__() + with self.assertRaises(cookies.CookieError): + morsel |= {"path": c0} + with self.assertRaises(cookies.CookieError): + morsel |= {c0: "val"} + def test_control_characters_output(self): # Tests that even if the internals of Morsel are modified # that a call to .output() has control character safeguards. @@ -638,6 +658,24 @@ def test_control_characters_output(self): with self.assertRaises(cookies.CookieError): cookie.output() + # Tests that .js_output() also has control character safeguards. + for c0 in support.control_characters_c0(): + morsel = cookies.Morsel() + morsel.set("key", "value", "coded-value") + morsel._key = c0 # Override private variable. + cookie = cookies.SimpleCookie() + cookie["cookie"] = morsel + with self.assertRaises(cookies.CookieError): + cookie.js_output() + + morsel = cookies.Morsel() + morsel.set("key", "value", "coded-value") + morsel._coded_value = c0 # Override private variable. + cookie = cookies.SimpleCookie() + cookie["cookie"] = morsel + with self.assertRaises(cookies.CookieError): + cookie.js_output() + def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite(cookies)) diff --git a/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst b/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst new file mode 100644 index 00000000000..e53a932d12f --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst @@ -0,0 +1,4 @@ +Reject control characters in :class:`http.cookies.Morsel` +:meth:`~http.cookies.Morsel.update` and +:meth:`~http.cookies.BaseCookie.js_output`. +This addresses :cve:`2026-3644`. From fd50b41aa906cd3994dc2e6b884bed8f5dd605cf Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Mon, 16 Mar 2026 18:50:26 +0500 Subject: [PATCH 157/775] GH-145247: Use _PyTuple_FromPair in exceptions.c (GH-145910) --- Objects/exceptions.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index f5edc286243..4e090e5dd86 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -13,6 +13,7 @@ #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" #include "pycore_pyerrors.h" // struct _PyErr_SetRaisedException +#include "pycore_tuple.h" // _PyTuple_FromPair #include "osdefs.h" // SEP #include "clinic/exceptions.c.h" @@ -214,7 +215,7 @@ BaseException___reduce___impl(PyBaseExceptionObject *self) if (self->args && self->dict) return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict); else - return PyTuple_Pack(2, Py_TYPE(self), self->args); + return _PyTuple_FromPair((PyObject *)Py_TYPE(self), self->args); } /* @@ -1008,8 +1009,7 @@ _PyExc_CreateExceptionGroup(const char *msg_str, PyObject *excs) if (!msg) { return NULL; } - PyObject *args = PyTuple_Pack(2, msg, excs); - Py_DECREF(msg); + PyObject *args = _PyTuple_FromPairSteal(msg, Py_NewRef(excs)); if (!args) { return NULL; } @@ -1132,7 +1132,7 @@ BaseExceptionGroup_derive_impl(PyBaseExceptionGroupObject *self, PyObject *excs) /*[clinic end generated code: output=4307564218dfbf06 input=f72009d38e98cec1]*/ { - PyObject *init_args = PyTuple_Pack(2, self->msg, excs); + PyObject *init_args = _PyTuple_FromPair(self->msg, excs); if (!init_args) { return NULL; } @@ -1449,13 +1449,11 @@ BaseExceptionGroup_split_impl(PyBaseExceptionGroupObject *self, return NULL; } - PyObject *result = PyTuple_Pack( - 2, + assert(_Py_IsStaticImmortal(Py_None)); + PyObject *result = _PyTuple_FromPairSteal( split_result.match ? split_result.match : Py_None, split_result.rest ? split_result.rest : Py_None); - Py_XDECREF(split_result.match); - Py_XDECREF(split_result.rest); return result; } @@ -1764,8 +1762,8 @@ static PyObject* create_exception_group_class(void) { struct _Py_exc_state *state = get_exc_state(); - PyObject *bases = PyTuple_Pack( - 2, PyExc_BaseExceptionGroup, PyExc_Exception); + PyObject *bases = _PyTuple_FromPair( + PyExc_BaseExceptionGroup, PyExc_Exception); if (bases == NULL) { return NULL; } @@ -1913,7 +1911,7 @@ ImportError_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) return NULL; PyBaseExceptionObject *exc = PyBaseExceptionObject_CAST(self); if (state == Py_None) - res = PyTuple_Pack(2, Py_TYPE(self), exc->args); + res = _PyTuple_FromPair((PyObject *)Py_TYPE(self), exc->args); else res = PyTuple_Pack(3, Py_TYPE(self), exc->args, state); Py_DECREF(state); @@ -2421,7 +2419,7 @@ OSError_reduce(PyObject *op, PyObject *Py_UNUSED(ignored)) if (self->dict) res = PyTuple_Pack(3, Py_TYPE(self), args, self->dict); else - res = PyTuple_Pack(2, Py_TYPE(self), args); + res = _PyTuple_FromPair((PyObject *)Py_TYPE(self), args); Py_DECREF(args); return res; } From 182aea2f57002dcea39dfdfe3faf642d724dd80b Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Mon, 16 Mar 2026 21:52:56 +0800 Subject: [PATCH 158/775] gh-146018: Disable over-aggressive optimization for _GUARD_CODE_VERSION (GH-145923) --- Python/optimizer_bytecodes.c | 4 +++- Python/optimizer_cases.c.h | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index e0410be5565..f3a391b2e37 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1761,7 +1761,9 @@ dummy_func(void) { PyCodeObject *co = get_current_code_object(ctx); if (co->co_version == version) { _Py_BloomFilter_Add(dependencies, co); - REPLACE_OP(this_instr, _NOP, 0, 0); + // TODO gh-144651: + // If we've previously guarded on this code version in a trace, we + // can avoid guarding it again. } else { ctx->done = true; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 7e5b26c6d72..942a730e4fa 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -4290,7 +4290,6 @@ PyCodeObject *co = get_current_code_object(ctx); if (co->co_version == version) { _Py_BloomFilter_Add(dependencies, co); - REPLACE_OP(this_instr, _NOP, 0, 0); } else { ctx->done = true; From e18abc6a1f1b60434b529d4c1ff4855acde0fd13 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Mon, 16 Mar 2026 11:08:07 -0400 Subject: [PATCH 159/775] gh-135329: Remove flaky test_repl_eio test (gh-145932) The test doesn't actually test any pyrepl code (it runs Python with -S) and has a race condition that causes intermittent timeouts on CI. --- Lib/test/test_pyrepl/eio_test_script.py | 94 ----------------------- Lib/test/test_pyrepl/test_unix_console.py | 35 +-------- 2 files changed, 1 insertion(+), 128 deletions(-) delete mode 100644 Lib/test/test_pyrepl/eio_test_script.py diff --git a/Lib/test/test_pyrepl/eio_test_script.py b/Lib/test/test_pyrepl/eio_test_script.py deleted file mode 100644 index e3ea6caef58..00000000000 --- a/Lib/test/test_pyrepl/eio_test_script.py +++ /dev/null @@ -1,94 +0,0 @@ -import errno -import fcntl -import os -import pty -import signal -import sys -import termios - - -def handler(sig, f): - pass - - -def create_eio_condition(): - # SIGINT handler used to produce an EIO. - # See https://github.com/python/cpython/issues/135329. - try: - master_fd, slave_fd = pty.openpty() - child_pid = os.fork() - if child_pid == 0: - try: - os.setsid() - fcntl.ioctl(slave_fd, termios.TIOCSCTTY, 0) - child_process_group_id = os.getpgrp() - grandchild_pid = os.fork() - if grandchild_pid == 0: - os.setpgid(0, 0) # set process group for grandchild - os.dup2(slave_fd, 0) # redirect stdin - if slave_fd > 2: - os.close(slave_fd) - # Fork grandchild for terminal control manipulation - if os.fork() == 0: - sys.exit(0) # exit the child process that was just obtained - else: - try: - os.tcsetpgrp(0, child_process_group_id) - except OSError: - pass - sys.exit(0) - else: - # Back to child - try: - os.setpgid(grandchild_pid, grandchild_pid) - except ProcessLookupError: - pass - os.tcsetpgrp(slave_fd, grandchild_pid) - if slave_fd > 2: - os.close(slave_fd) - os.waitpid(grandchild_pid, 0) - # Manipulate terminal control to create EIO condition - os.tcsetpgrp(master_fd, child_process_group_id) - # Now try to read from master - this might cause EIO - try: - os.read(master_fd, 1) - except OSError as e: - if e.errno == errno.EIO: - print(f"Setup created EIO condition: {e}", file=sys.stderr) - sys.exit(0) - except Exception as setup_e: - print(f"Setup error: {setup_e}", file=sys.stderr) - sys.exit(1) - else: - # Parent process - os.close(slave_fd) - os.waitpid(child_pid, 0) - # Now replace stdin with master_fd and try to read - os.dup2(master_fd, 0) - os.close(master_fd) - # This should now trigger EIO - print(f"Unexpectedly got input: {input()!r}", file=sys.stderr) - sys.exit(0) - except OSError as e: - if e.errno == errno.EIO: - print(f"Got EIO: {e}", file=sys.stderr) - sys.exit(1) - elif e.errno == errno.ENXIO: - print(f"Got ENXIO (no such device): {e}", file=sys.stderr) - sys.exit(1) # Treat ENXIO as success too - else: - print(f"Got other OSError: errno={e.errno} {e}", file=sys.stderr) - sys.exit(2) - except EOFError as e: - print(f"Got EOFError: {e}", file=sys.stderr) - sys.exit(3) - except Exception as e: - print(f"Got unexpected error: {type(e).__name__}: {e}", file=sys.stderr) - sys.exit(4) - - -if __name__ == "__main__": - # Set up signal handler for coordination - signal.signal(signal.SIGUSR1, lambda *a: create_eio_condition()) - print("READY", flush=True) - signal.pause() diff --git a/Lib/test/test_pyrepl/test_unix_console.py b/Lib/test/test_pyrepl/test_unix_console.py index 680adbc2d96..a1ee6d4878f 100644 --- a/Lib/test/test_pyrepl/test_unix_console.py +++ b/Lib/test/test_pyrepl/test_unix_console.py @@ -2,14 +2,12 @@ import itertools import os import signal -import subprocess import sys import threading import unittest from functools import partial -from test import support from test.support import os_helper, force_not_colorized_test_class -from test.support import script_helper, threading_helper +from test.support import threading_helper from unittest import TestCase from unittest.mock import MagicMock, call, patch, ANY, Mock @@ -369,34 +367,3 @@ def test_eio_error_handling_in_restore(self, mock_tcgetattr, mock_tcsetattr): # EIO error should be handled gracefully in restore() console.restore() - - @unittest.skipUnless(sys.platform == "linux", "Only valid on Linux") - def test_repl_eio(self): - # Use the pty-based approach to simulate EIO error - script_path = os.path.join(os.path.dirname(__file__), "eio_test_script.py") - - proc = script_helper.spawn_python( - "-S", script_path, - stderr=subprocess.PIPE, - text=True - ) - - ready_line = proc.stdout.readline().strip() - if ready_line != "READY" or proc.poll() is not None: - self.fail("Child process failed to start properly") - - os.kill(proc.pid, signal.SIGUSR1) - # sleep for pty to settle - _, err = proc.communicate(timeout=support.LONG_TIMEOUT) - self.assertEqual( - proc.returncode, - 1, - f"Expected EIO/ENXIO error, got return code {proc.returncode}", - ) - self.assertTrue( - ( - "Got EIO:" in err - or "Got ENXIO:" in err - ), - f"Expected EIO/ENXIO error message in stderr: {err}", - ) From 81ef1b73175378543534ebe1f148c22deb8239b3 Mon Sep 17 00:00:00 2001 From: Hai Zhu Date: Mon, 16 Mar 2026 23:58:18 +0800 Subject: [PATCH 160/775] gh-144888: Replace bloom filter linked lists with continuous arrays to optimize executor invalidating performance (GH-145873) --- Include/internal/pycore_interp_structs.h | 6 +- Include/internal/pycore_optimizer.h | 6 +- InternalDocs/jit.md | 4 +- Modules/_testinternalcapi.c | 6 +- Objects/funcobject.c | 1 - Python/jit.c | 19 +++- Python/optimizer.c | 119 ++++++++++++----------- Python/pylifecycle.c | 6 ++ Python/pystate.c | 5 +- 9 files changed, 102 insertions(+), 70 deletions(-) diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 776fb9575c2..e2008f8303e 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -14,6 +14,7 @@ extern "C" { #include "pycore_structs.h" // PyHamtObject #include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_typedefs.h" // _PyRuntimeState +#include "pycore_uop.h" // _PyBloomFilter #define CODE_MAX_WATCHERS 8 #define CONTEXT_MAX_WATCHERS 8 @@ -972,7 +973,10 @@ struct _is { // Optimization configuration (thresholds and flags for JIT and interpreter) _PyOptimizationConfig opt_config; - struct _PyExecutorObject *executor_list_head; + _PyBloomFilter *executor_blooms; // Contiguous bloom filter array + struct _PyExecutorObject **executor_ptrs; // Corresponding executor pointer array + size_t executor_count; // Number of valid executors + size_t executor_capacity; // Array capacity struct _PyExecutorObject *executor_deletion_list_head; struct _PyExecutorObject *cold_executor; struct _PyExecutorObject *cold_dynamic_executor; diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index c63f0167a0f..cea9fcce237 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -128,8 +128,8 @@ typedef struct { bool cold; uint8_t pending_deletion; int32_t index; // Index of ENTER_EXECUTOR (if code isn't NULL, below). - _PyBloomFilter bloom; - _PyExecutorLinkListNode links; + int32_t bloom_array_idx; // Index in interp->executor_blooms/executor_ptrs. + _PyExecutorLinkListNode links; // Used by deletion list. PyCodeObject *code; // Weak (NULL if no corresponding ENTER_EXECUTOR). } _PyVMData; @@ -157,7 +157,7 @@ typedef struct _PyExecutorObject { // Export for '_opcode' shared extension (JIT compiler). PyAPI_FUNC(_PyExecutorObject*) _Py_GetExecutor(PyCodeObject *code, int offset); -void _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *); +int _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *); void _Py_ExecutorDetach(_PyExecutorObject *); void _Py_BloomFilter_Init(_PyBloomFilter *); void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj); diff --git a/InternalDocs/jit.md b/InternalDocs/jit.md index 1740b22b85f..decfccad2d8 100644 --- a/InternalDocs/jit.md +++ b/InternalDocs/jit.md @@ -78,8 +78,8 @@ ## The JIT interpreter ## Invalidating Executors In addition to being stored on the code object, each executor is also -inserted into a list of all executors, which is stored in the interpreter -state's `executor_list_head` field. This list is used when it is necessary +inserted into contiguous arrays (`executor_blooms` and `executor_ptrs`) +stored in the interpreter state. These arrays are used when it is necessary to invalidate executors because values they used in their construction may have changed. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index aa5911ef2fb..8c316b7c8dd 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -278,10 +278,8 @@ get_jit_code_ranges(PyObject *self, PyObject *Py_UNUSED(args)) if (interp == NULL) { return ranges; } - for (_PyExecutorObject *exec = interp->executor_list_head; - exec != NULL; - exec = exec->vm_data.links.next) - { + for (size_t i = 0; i < interp->executor_count; i++) { + _PyExecutorObject *exec = interp->executor_ptrs[i]; if (exec->jit_code == NULL || exec->jit_size == 0) { continue; } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index fc32826fb3a..a7a3d9c78ef 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -12,7 +12,6 @@ #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_stats.h" #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() -#include "pycore_optimizer.h" // _Py_Executors_InvalidateDependency static const char * func_event_name(PyFunction_WatchEvent event) { diff --git a/Python/jit.c b/Python/jit.c index 3e0a0aa8bfc..4990c743224 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -62,6 +62,23 @@ jit_error(const char *message) static size_t _Py_jit_shim_size = 0; +static int +address_in_executor_array(_PyExecutorObject **ptrs, size_t count, uintptr_t addr) +{ + for (size_t i = 0; i < count; i++) { + _PyExecutorObject *exec = ptrs[i]; + if (exec->jit_code == NULL || exec->jit_size == 0) { + continue; + } + uintptr_t start = (uintptr_t)exec->jit_code; + uintptr_t end = start + exec->jit_size; + if (addr >= start && addr < end) { + return 1; + } + } + return 0; +} + static int address_in_executor_list(_PyExecutorObject *head, uintptr_t addr) { @@ -94,7 +111,7 @@ _PyJIT_AddressInJitCode(PyInterpreterState *interp, uintptr_t addr) return 1; } } - if (address_in_executor_list(interp->executor_list_head, addr)) { + if (address_in_executor_array(interp->executor_ptrs, interp->executor_count, addr)) { return 1; } if (address_in_executor_list(interp->executor_deletion_list_head, addr)) { diff --git a/Python/optimizer.c b/Python/optimizer.c index 7315bb6b9f6..a9e788d0dcb 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1379,7 +1379,10 @@ make_executor_from_uops(_PyThreadStateImpl *tstate, _PyUOpInstruction *buffer, i // linking of executor. Otherwise, the GC tries to untrack a // still untracked object during dealloc. _PyObject_GC_TRACK(executor); - _Py_ExecutorInit(executor, dependencies); + if (_Py_ExecutorInit(executor, dependencies) < 0) { + Py_DECREF(executor); + return NULL; + } #ifdef Py_DEBUG char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); int lltrace = 0; @@ -1646,59 +1649,63 @@ bloom_filter_may_contain(_PyBloomFilter *bloom, _PyBloomFilter *hashes) return true; } -static void -link_executor(_PyExecutorObject *executor) +static int +link_executor(_PyExecutorObject *executor, const _PyBloomFilter *bloom) { PyInterpreterState *interp = _PyInterpreterState_GET(); - _PyExecutorLinkListNode *links = &executor->vm_data.links; - _PyExecutorObject *head = interp->executor_list_head; - if (head == NULL) { - interp->executor_list_head = executor; - links->previous = NULL; - links->next = NULL; + if (interp->executor_count == interp->executor_capacity) { + size_t new_cap = interp->executor_capacity ? interp->executor_capacity * 2 : 64; + _PyBloomFilter *new_blooms = PyMem_Realloc( + interp->executor_blooms, new_cap * sizeof(_PyBloomFilter)); + if (new_blooms == NULL) { + return -1; + } + _PyExecutorObject **new_ptrs = PyMem_Realloc( + interp->executor_ptrs, new_cap * sizeof(_PyExecutorObject *)); + if (new_ptrs == NULL) { + /* Revert blooms realloc — the old pointer may have been freed by + * a successful realloc, but new_blooms is the valid pointer. */ + interp->executor_blooms = new_blooms; + return -1; + } + interp->executor_blooms = new_blooms; + interp->executor_ptrs = new_ptrs; + interp->executor_capacity = new_cap; } - else { - assert(head->vm_data.links.previous == NULL); - links->previous = NULL; - links->next = head; - head->vm_data.links.previous = executor; - interp->executor_list_head = executor; - } - /* executor_list_head must be first in list */ - assert(interp->executor_list_head->vm_data.links.previous == NULL); + size_t idx = interp->executor_count++; + interp->executor_blooms[idx] = *bloom; + interp->executor_ptrs[idx] = executor; + executor->vm_data.bloom_array_idx = (int32_t)idx; + return 0; } static void unlink_executor(_PyExecutorObject *executor) { - _PyExecutorLinkListNode *links = &executor->vm_data.links; - _PyExecutorObject *next = links->next; - _PyExecutorObject *prev = links->previous; - if (next != NULL) { - next->vm_data.links.previous = prev; - } - if (prev != NULL) { - prev->vm_data.links.next = next; - } - else { - // prev == NULL implies that executor is the list head - PyInterpreterState *interp = PyInterpreterState_Get(); - assert(interp->executor_list_head == executor); - interp->executor_list_head = next; + PyInterpreterState *interp = PyInterpreterState_Get(); + int32_t idx = executor->vm_data.bloom_array_idx; + assert(idx >= 0 && (size_t)idx < interp->executor_count); + size_t last = --interp->executor_count; + if ((size_t)idx != last) { + /* Swap-remove: move the last element into the vacated slot */ + interp->executor_blooms[idx] = interp->executor_blooms[last]; + interp->executor_ptrs[idx] = interp->executor_ptrs[last]; + interp->executor_ptrs[idx]->vm_data.bloom_array_idx = idx; } + executor->vm_data.bloom_array_idx = -1; } /* This must be called by optimizers before using the executor */ -void +int _Py_ExecutorInit(_PyExecutorObject *executor, const _PyBloomFilter *dependency_set) { executor->vm_data.valid = true; executor->vm_data.pending_deletion = 0; executor->vm_data.code = NULL; - for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) { - executor->vm_data.bloom.bits[i] = dependency_set->bits[i]; + if (link_executor(executor, dependency_set) < 0) { + return -1; } - link_executor(executor); + return 0; } static _PyExecutorObject * @@ -1809,11 +1816,15 @@ void _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj) { assert(executor->vm_data.valid); - _Py_BloomFilter_Add(&executor->vm_data.bloom, obj); + PyInterpreterState *interp = _PyInterpreterState_GET(); + int32_t idx = executor->vm_data.bloom_array_idx; + assert(idx >= 0 && (size_t)idx < interp->executor_count); + _Py_BloomFilter_Add(&interp->executor_blooms[idx], obj); } /* Invalidate all executors that depend on `obj` - * May cause other executors to be invalidated as well + * May cause other executors to be invalidated as well. + * Uses contiguous bloom filter array for cache-friendly scanning. */ void _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is_invalidation) @@ -1821,23 +1832,20 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is _PyBloomFilter obj_filter; _Py_BloomFilter_Init(&obj_filter); _Py_BloomFilter_Add(&obj_filter, obj); - /* Walk the list of executors */ - /* TO DO -- Use a tree to avoid traversing as many objects */ + /* Scan contiguous bloom filter array */ PyObject *invalidate = PyList_New(0); if (invalidate == NULL) { goto error; } /* Clearing an executor can clear others, so we need to make a list of * executors to invalidate first */ - for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) { - assert(exec->vm_data.valid); - _PyExecutorObject *next = exec->vm_data.links.next; - if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter) && - PyList_Append(invalidate, (PyObject *)exec)) + for (size_t i = 0; i < interp->executor_count; i++) { + assert(interp->executor_ptrs[i]->vm_data.valid); + if (bloom_filter_may_contain(&interp->executor_blooms[i], &obj_filter) && + PyList_Append(invalidate, (PyObject *)interp->executor_ptrs[i])) { goto error; } - exec = next; } for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) { PyObject *exec = PyList_GET_ITEM(invalidate, i); @@ -1859,8 +1867,9 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is void _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation) { - while (interp->executor_list_head) { - _PyExecutorObject *executor = interp->executor_list_head; + while (interp->executor_count > 0) { + /* Invalidate from the end to avoid repeated swap-remove shifts */ + _PyExecutorObject *executor = interp->executor_ptrs[interp->executor_count - 1]; assert(executor->vm_data.valid); if (executor->vm_data.code) { // Clear the entire code object so its co_executors array be freed: @@ -1878,8 +1887,7 @@ _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation) void _Py_Executors_InvalidateCold(PyInterpreterState *interp) { - /* Walk the list of executors */ - /* TO DO -- Use a tree to avoid traversing as many objects */ + /* Scan contiguous executor array */ PyObject *invalidate = PyList_New(0); if (invalidate == NULL) { goto error; @@ -1887,9 +1895,9 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp) /* Clearing an executor can deallocate others, so we need to make a list of * executors to invalidate first */ - for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) { + for (size_t i = 0; i < interp->executor_count; i++) { + _PyExecutorObject *exec = interp->executor_ptrs[i]; assert(exec->vm_data.valid); - _PyExecutorObject *next = exec->vm_data.links.next; if (exec->vm_data.cold && PyList_Append(invalidate, (PyObject *)exec) < 0) { goto error; @@ -1897,8 +1905,6 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp) else { exec->vm_data.cold = true; } - - exec = next; } for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) { PyObject *exec = PyList_GET_ITEM(invalidate, i); @@ -2142,9 +2148,8 @@ _PyDumpExecutors(FILE *out) fprintf(out, " rankdir = \"LR\"\n\n"); fprintf(out, " node [colorscheme=greys9]\n"); PyInterpreterState *interp = PyInterpreterState_Get(); - for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) { - executor_to_gv(exec, out); - exec = exec->vm_data.links.next; + for (size_t i = 0; i < interp->executor_count; i++) { + executor_to_gv(interp->executor_ptrs[i], out); } fprintf(out, "}\n\n"); return 0; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2b8e9a02cb6..68052a91d6a 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1761,6 +1761,12 @@ finalize_modules(PyThreadState *tstate) interp->compiling = false; #ifdef _Py_TIER2 _Py_Executors_InvalidateAll(interp, 0); + PyMem_Free(interp->executor_blooms); + PyMem_Free(interp->executor_ptrs); + interp->executor_blooms = NULL; + interp->executor_ptrs = NULL; + interp->executor_count = 0; + interp->executor_capacity = 0; #endif // Stop watching __builtin__ modifications diff --git a/Python/pystate.c b/Python/pystate.c index 17b8430b19c..fcb73b4dcef 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -597,7 +597,10 @@ init_interpreter(PyInterpreterState *interp, interp->_code_object_generation = 0; interp->jit = false; interp->compiling = false; - interp->executor_list_head = NULL; + interp->executor_blooms = NULL; + interp->executor_ptrs = NULL; + interp->executor_count = 0; + interp->executor_capacity = 0; interp->executor_deletion_list_head = NULL; interp->executor_creation_counter = JIT_CLEANUP_THRESHOLD; From 3d0824aef261895bad55f7e1fa7267a926206924 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Tue, 17 Mar 2026 00:18:59 +0800 Subject: [PATCH 161/775] gh-127958: Trace from RESUME in the JIT (GH-145905) --- Include/internal/pycore_backoff.h | 14 + Include/internal/pycore_code.h | 1 + Include/internal/pycore_interp_structs.h | 3 + Include/internal/pycore_magic_number.h | 3 +- Include/internal/pycore_opcode_metadata.h | 18 +- Include/internal/pycore_optimizer.h | 2 + Include/internal/pycore_uop.h | 2 +- Include/internal/pycore_uop_ids.h | 309 ++++++------- Include/opcode_ids.h | 31 +- Lib/_opcode_metadata.py | 32 +- Lib/opcode.py | 3 + Lib/test/test_capi/test_opt.py | 24 +- Lib/test/test_code.py | 5 +- Lib/test/test_compile.py | 4 +- Lib/test/test_dis.py | 433 +++++++++--------- Lib/test/test_monitoring.py | 151 +++--- ...-03-13-09-48-57.gh-issue-127958.U-znTv.rst | 1 + Modules/_testinternalcapi.c | 8 + Modules/_testinternalcapi/test_cases.c.h | 119 ++++- Modules/_testinternalcapi/test_targets.h | 9 +- Objects/codeobject.c | 7 +- Objects/genobject.c | 1 + Programs/test_frozenmain.h | 70 +-- Python/assemble.c | 2 +- Python/bytecodes.c | 50 +- Python/ceval.c | 5 +- Python/executor_cases.c.h | 2 - Python/generated_cases.c.h | 119 ++++- Python/instrumentation.c | 1 + Python/opcode_targets.h | 9 +- Python/optimizer.c | 34 +- Python/optimizer_cases.c.h | 2 - Python/pystate.c | 8 + Python/specialize.c | 30 +- 34 files changed, 915 insertions(+), 597 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst diff --git a/Include/internal/pycore_backoff.h b/Include/internal/pycore_backoff.h index ee907ae0534..38dd82f6fc8 100644 --- a/Include/internal/pycore_backoff.h +++ b/Include/internal/pycore_backoff.h @@ -135,6 +135,20 @@ initial_jump_backoff_counter(_PyOptimizationConfig *opt_config) opt_config->jump_backward_initial_backoff); } +// This needs to be around 2-4x of JUMP_BACKWARD_INITIAL_VALUE +// The reasoning is that we always want loop traces to form and inline +// functions before functions themselves warm up and link to them instead +// of inlining. +#define RESUME_INITIAL_VALUE 8190 +#define RESUME_INITIAL_BACKOFF 6 +static inline _Py_BackoffCounter +initial_resume_backoff_counter(_PyOptimizationConfig *opt_config) +{ + return make_backoff_counter( + opt_config->resume_initial_value, + opt_config->resume_initial_backoff); +} + /* Initial exit temperature. * Must be larger than ADAPTIVE_COOLDOWN_VALUE, * otherwise when a side exit warms up we may construct diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index efae3b38654..376e68a4c87 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -323,6 +323,7 @@ PyAPI_FUNC(void) _Py_Specialize_ToBool(_PyStackRef value, _Py_CODEUNIT *instr); PyAPI_FUNC(void) _Py_Specialize_ContainsOp(_PyStackRef value, _Py_CODEUNIT *instr); PyAPI_FUNC(void) _Py_GatherStats_GetIter(_PyStackRef iterable); PyAPI_FUNC(void) _Py_Specialize_CallFunctionEx(_PyStackRef func_st, _Py_CODEUNIT *instr); +PyAPI_FUNC(void) _Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame); // Utility functions for reading/writing 32/64-bit values in the inline caches. // Great care should be taken to ensure that these functions remain correct and diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index e2008f8303e..4822360a8f0 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -414,6 +414,9 @@ typedef struct _PyOptimizationConfig { uint16_t jump_backward_initial_value; uint16_t jump_backward_initial_backoff; + uint16_t resume_initial_value; + uint16_t resume_initial_backoff; + // JIT optimization thresholds uint16_t side_exit_initial_value; uint16_t side_exit_initial_backoff; diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 3fcf650426d..ec9cfe43237 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -292,6 +292,7 @@ Known values: Python 3.15a4 3659 (Add CALL_FUNCTION_EX specialization) Python 3.15a4 3660 (Change generator preamble code) Python 3.15a4 3661 (Lazy imports IMPORT_NAME opcode changes) + Python 3.15a6 3662 (Add counter to RESUME) Python 3.16 will start with 3700 @@ -305,7 +306,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3661 +#define PYC_MAGIC_NUMBER 3662 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index fc5689c5afe..c46015c4d98 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -426,6 +426,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 0; case RESUME_CHECK: return 0; + case RESUME_CHECK_JIT: + return 0; case RETURN_GENERATOR: return 0; case RETURN_VALUE: @@ -917,6 +919,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 0; case RESUME_CHECK: return 0; + case RESUME_CHECK_JIT: + return 0; case RETURN_GENERATOR: return 1; case RETURN_VALUE: @@ -1209,7 +1213,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, - [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, @@ -1278,8 +1282,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [RAISE_VARARGS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [RERAISE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [RESERVED] = { true, INSTR_FMT_IX, 0 }, - [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, + [RESUME] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [RESUME_CHECK] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [RESUME_CHECK_JIT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, @@ -1493,7 +1498,7 @@ _PyOpcode_macro_expansion[256] = { [POP_TOP] = { .nuops = 1, .uops = { { _POP_TOP, OPARG_SIMPLE, 0 } } }, [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { _PUSH_EXC_INFO, OPARG_SIMPLE, 0 } } }, [PUSH_NULL] = { .nuops = 1, .uops = { { _PUSH_NULL, OPARG_SIMPLE, 0 } } }, - [RESUME_CHECK] = { .nuops = 1, .uops = { { _RESUME_CHECK, OPARG_SIMPLE, 0 } } }, + [RESUME_CHECK] = { .nuops = 1, .uops = { { _RESUME_CHECK, OPARG_SIMPLE, 1 } } }, [RETURN_GENERATOR] = { .nuops = 1, .uops = { { _RETURN_GENERATOR, OPARG_SIMPLE, 0 } } }, [RETURN_VALUE] = { .nuops = 2, .uops = { { _MAKE_HEAP_SAFE, OPARG_SIMPLE, 0 }, { _RETURN_VALUE, OPARG_SIMPLE, 0 } } }, [SEND_GEN] = { .nuops = 4, .uops = { { _RECORD_NOS_GEN_FUNC, OPARG_SIMPLE, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _SEND_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, @@ -1734,6 +1739,7 @@ const char *_PyOpcode_OpName[267] = { [RESERVED] = "RESERVED", [RESUME] = "RESUME", [RESUME_CHECK] = "RESUME_CHECK", + [RESUME_CHECK_JIT] = "RESUME_CHECK_JIT", [RETURN_GENERATOR] = "RETURN_GENERATOR", [RETURN_VALUE] = "RETURN_VALUE", [SEND] = "SEND", @@ -1785,6 +1791,7 @@ const char *_PyOpcode_OpName[267] = { PyAPI_DATA(const uint8_t) _PyOpcode_Caches[256]; #ifdef NEED_OPCODE_METADATA const uint8_t _PyOpcode_Caches[256] = { + [RESUME] = 1, [TO_BOOL] = 3, [STORE_SUBSCR] = 1, [SEND] = 1, @@ -1818,7 +1825,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [125] = 125, [126] = 126, [127] = 127, - [213] = 213, [214] = 214, [215] = 215, [216] = 216, @@ -2026,6 +2032,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [RESERVED] = RESERVED, [RESUME] = RESUME, [RESUME_CHECK] = RESUME, + [RESUME_CHECK_JIT] = RESUME, [RETURN_GENERATOR] = RETURN_GENERATOR, [RETURN_VALUE] = RETURN_VALUE, [SEND] = SEND, @@ -2079,7 +2086,6 @@ const uint8_t _PyOpcode_Deopt[256] = { case 125: \ case 126: \ case 127: \ - case 213: \ case 214: \ case 215: \ case 216: \ diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index cea9fcce237..8b52d77538a 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -361,6 +361,8 @@ _PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, int oparg, _PyExecutorObject *current_executor); PyAPI_FUNC(void) _PyJit_FinalizeTracing(PyThreadState *tstate, int err); +PyAPI_FUNC(bool) _PyJit_EnterExecutorShouldStopTracing(int og_opcode); + void _PyPrintExecutor(_PyExecutorObject *executor, const _PyUOpInstruction *marker); void _PyJit_TracerFree(_PyThreadStateImpl *_tstate); diff --git a/Include/internal/pycore_uop.h b/Include/internal/pycore_uop.h index f9be01acb57..e7ac7d59ff7 100644 --- a/Include/internal/pycore_uop.h +++ b/Include/internal/pycore_uop.h @@ -36,7 +36,7 @@ typedef struct _PyUOpInstruction{ } _PyUOpInstruction; // This is the length of the trace we translate initially. -#ifdef Py_DEBUG +#if defined(Py_DEBUG) && defined(_Py_JIT) // With asserts, the stencils are a lot larger #define UOP_MAX_TRACE_LENGTH 1000 #else diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 451c0dd5732..d29d98d3f16 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -330,17 +330,16 @@ extern "C" { #define _PY_FRAME_EX 547 #define _PY_FRAME_GENERAL 548 #define _PY_FRAME_KW 549 -#define _QUICKEN_RESUME 550 -#define _RECORD_4OS 551 -#define _RECORD_BOUND_METHOD 552 -#define _RECORD_CALLABLE 553 -#define _RECORD_CODE 554 -#define _RECORD_NOS 555 -#define _RECORD_NOS_GEN_FUNC 556 -#define _RECORD_TOS 557 -#define _RECORD_TOS_TYPE 558 -#define _REPLACE_WITH_TRUE 559 -#define _RESUME_CHECK RESUME_CHECK +#define _RECORD_4OS 550 +#define _RECORD_BOUND_METHOD 551 +#define _RECORD_CALLABLE 552 +#define _RECORD_CODE 553 +#define _RECORD_NOS 554 +#define _RECORD_NOS_GEN_FUNC 555 +#define _RECORD_TOS 556 +#define _RECORD_TOS_TYPE 557 +#define _REPLACE_WITH_TRUE 558 +#define _RESUME_CHECK 559 #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE 560 #define _SAVE_RETURN_OFFSET 561 @@ -1141,152 +1140,148 @@ extern "C" { #define _PY_FRAME_EX_r31 1342 #define _PY_FRAME_GENERAL_r01 1343 #define _PY_FRAME_KW_r11 1344 -#define _QUICKEN_RESUME_r00 1345 -#define _QUICKEN_RESUME_r11 1346 -#define _QUICKEN_RESUME_r22 1347 -#define _QUICKEN_RESUME_r33 1348 -#define _REPLACE_WITH_TRUE_r02 1349 -#define _REPLACE_WITH_TRUE_r12 1350 -#define _REPLACE_WITH_TRUE_r23 1351 -#define _RESUME_CHECK_r00 1352 -#define _RESUME_CHECK_r11 1353 -#define _RESUME_CHECK_r22 1354 -#define _RESUME_CHECK_r33 1355 -#define _RETURN_GENERATOR_r01 1356 -#define _RETURN_VALUE_r11 1357 -#define _SAVE_RETURN_OFFSET_r00 1358 -#define _SAVE_RETURN_OFFSET_r11 1359 -#define _SAVE_RETURN_OFFSET_r22 1360 -#define _SAVE_RETURN_OFFSET_r33 1361 -#define _SEND_r22 1362 -#define _SEND_GEN_FRAME_r22 1363 -#define _SETUP_ANNOTATIONS_r00 1364 -#define _SET_ADD_r10 1365 -#define _SET_FUNCTION_ATTRIBUTE_r01 1366 -#define _SET_FUNCTION_ATTRIBUTE_r11 1367 -#define _SET_FUNCTION_ATTRIBUTE_r21 1368 -#define _SET_FUNCTION_ATTRIBUTE_r32 1369 -#define _SET_IP_r00 1370 -#define _SET_IP_r11 1371 -#define _SET_IP_r22 1372 -#define _SET_IP_r33 1373 -#define _SET_UPDATE_r10 1374 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1375 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1376 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1377 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1378 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1379 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1380 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1381 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1382 -#define _SPILL_OR_RELOAD_r01 1383 -#define _SPILL_OR_RELOAD_r02 1384 -#define _SPILL_OR_RELOAD_r03 1385 -#define _SPILL_OR_RELOAD_r10 1386 -#define _SPILL_OR_RELOAD_r12 1387 -#define _SPILL_OR_RELOAD_r13 1388 -#define _SPILL_OR_RELOAD_r20 1389 -#define _SPILL_OR_RELOAD_r21 1390 -#define _SPILL_OR_RELOAD_r23 1391 -#define _SPILL_OR_RELOAD_r30 1392 -#define _SPILL_OR_RELOAD_r31 1393 -#define _SPILL_OR_RELOAD_r32 1394 -#define _START_EXECUTOR_r00 1395 -#define _STORE_ATTR_r20 1396 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1397 -#define _STORE_ATTR_SLOT_r21 1398 -#define _STORE_ATTR_WITH_HINT_r21 1399 -#define _STORE_DEREF_r10 1400 -#define _STORE_FAST_LOAD_FAST_r11 1401 -#define _STORE_FAST_STORE_FAST_r20 1402 -#define _STORE_GLOBAL_r10 1403 -#define _STORE_NAME_r10 1404 -#define _STORE_SLICE_r30 1405 -#define _STORE_SUBSCR_r30 1406 -#define _STORE_SUBSCR_DICT_r31 1407 -#define _STORE_SUBSCR_LIST_INT_r32 1408 -#define _SWAP_r11 1409 -#define _SWAP_2_r02 1410 -#define _SWAP_2_r12 1411 -#define _SWAP_2_r22 1412 -#define _SWAP_2_r33 1413 -#define _SWAP_3_r03 1414 -#define _SWAP_3_r13 1415 -#define _SWAP_3_r23 1416 -#define _SWAP_3_r33 1417 -#define _SWAP_FAST_r01 1418 -#define _SWAP_FAST_r11 1419 -#define _SWAP_FAST_r22 1420 -#define _SWAP_FAST_r33 1421 -#define _SWAP_FAST_0_r01 1422 -#define _SWAP_FAST_0_r11 1423 -#define _SWAP_FAST_0_r22 1424 -#define _SWAP_FAST_0_r33 1425 -#define _SWAP_FAST_1_r01 1426 -#define _SWAP_FAST_1_r11 1427 -#define _SWAP_FAST_1_r22 1428 -#define _SWAP_FAST_1_r33 1429 -#define _SWAP_FAST_2_r01 1430 -#define _SWAP_FAST_2_r11 1431 -#define _SWAP_FAST_2_r22 1432 -#define _SWAP_FAST_2_r33 1433 -#define _SWAP_FAST_3_r01 1434 -#define _SWAP_FAST_3_r11 1435 -#define _SWAP_FAST_3_r22 1436 -#define _SWAP_FAST_3_r33 1437 -#define _SWAP_FAST_4_r01 1438 -#define _SWAP_FAST_4_r11 1439 -#define _SWAP_FAST_4_r22 1440 -#define _SWAP_FAST_4_r33 1441 -#define _SWAP_FAST_5_r01 1442 -#define _SWAP_FAST_5_r11 1443 -#define _SWAP_FAST_5_r22 1444 -#define _SWAP_FAST_5_r33 1445 -#define _SWAP_FAST_6_r01 1446 -#define _SWAP_FAST_6_r11 1447 -#define _SWAP_FAST_6_r22 1448 -#define _SWAP_FAST_6_r33 1449 -#define _SWAP_FAST_7_r01 1450 -#define _SWAP_FAST_7_r11 1451 -#define _SWAP_FAST_7_r22 1452 -#define _SWAP_FAST_7_r33 1453 -#define _TIER2_RESUME_CHECK_r00 1454 -#define _TIER2_RESUME_CHECK_r11 1455 -#define _TIER2_RESUME_CHECK_r22 1456 -#define _TIER2_RESUME_CHECK_r33 1457 -#define _TO_BOOL_r11 1458 -#define _TO_BOOL_BOOL_r01 1459 -#define _TO_BOOL_BOOL_r11 1460 -#define _TO_BOOL_BOOL_r22 1461 -#define _TO_BOOL_BOOL_r33 1462 -#define _TO_BOOL_INT_r02 1463 -#define _TO_BOOL_INT_r12 1464 -#define _TO_BOOL_INT_r23 1465 -#define _TO_BOOL_LIST_r02 1466 -#define _TO_BOOL_LIST_r12 1467 -#define _TO_BOOL_LIST_r23 1468 -#define _TO_BOOL_NONE_r01 1469 -#define _TO_BOOL_NONE_r11 1470 -#define _TO_BOOL_NONE_r22 1471 -#define _TO_BOOL_NONE_r33 1472 -#define _TO_BOOL_STR_r02 1473 -#define _TO_BOOL_STR_r12 1474 -#define _TO_BOOL_STR_r23 1475 -#define _TRACE_RECORD_r00 1476 -#define _UNARY_INVERT_r12 1477 -#define _UNARY_NEGATIVE_r12 1478 -#define _UNARY_NOT_r01 1479 -#define _UNARY_NOT_r11 1480 -#define _UNARY_NOT_r22 1481 -#define _UNARY_NOT_r33 1482 -#define _UNPACK_EX_r10 1483 -#define _UNPACK_SEQUENCE_r10 1484 -#define _UNPACK_SEQUENCE_LIST_r10 1485 -#define _UNPACK_SEQUENCE_TUPLE_r10 1486 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1487 -#define _WITH_EXCEPT_START_r33 1488 -#define _YIELD_VALUE_r11 1489 -#define MAX_UOP_REGS_ID 1489 +#define _REPLACE_WITH_TRUE_r02 1345 +#define _REPLACE_WITH_TRUE_r12 1346 +#define _REPLACE_WITH_TRUE_r23 1347 +#define _RESUME_CHECK_r00 1348 +#define _RESUME_CHECK_r11 1349 +#define _RESUME_CHECK_r22 1350 +#define _RESUME_CHECK_r33 1351 +#define _RETURN_GENERATOR_r01 1352 +#define _RETURN_VALUE_r11 1353 +#define _SAVE_RETURN_OFFSET_r00 1354 +#define _SAVE_RETURN_OFFSET_r11 1355 +#define _SAVE_RETURN_OFFSET_r22 1356 +#define _SAVE_RETURN_OFFSET_r33 1357 +#define _SEND_r22 1358 +#define _SEND_GEN_FRAME_r22 1359 +#define _SETUP_ANNOTATIONS_r00 1360 +#define _SET_ADD_r10 1361 +#define _SET_FUNCTION_ATTRIBUTE_r01 1362 +#define _SET_FUNCTION_ATTRIBUTE_r11 1363 +#define _SET_FUNCTION_ATTRIBUTE_r21 1364 +#define _SET_FUNCTION_ATTRIBUTE_r32 1365 +#define _SET_IP_r00 1366 +#define _SET_IP_r11 1367 +#define _SET_IP_r22 1368 +#define _SET_IP_r33 1369 +#define _SET_UPDATE_r10 1370 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1371 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1372 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1373 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1374 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1375 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1376 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1377 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1378 +#define _SPILL_OR_RELOAD_r01 1379 +#define _SPILL_OR_RELOAD_r02 1380 +#define _SPILL_OR_RELOAD_r03 1381 +#define _SPILL_OR_RELOAD_r10 1382 +#define _SPILL_OR_RELOAD_r12 1383 +#define _SPILL_OR_RELOAD_r13 1384 +#define _SPILL_OR_RELOAD_r20 1385 +#define _SPILL_OR_RELOAD_r21 1386 +#define _SPILL_OR_RELOAD_r23 1387 +#define _SPILL_OR_RELOAD_r30 1388 +#define _SPILL_OR_RELOAD_r31 1389 +#define _SPILL_OR_RELOAD_r32 1390 +#define _START_EXECUTOR_r00 1391 +#define _STORE_ATTR_r20 1392 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1393 +#define _STORE_ATTR_SLOT_r21 1394 +#define _STORE_ATTR_WITH_HINT_r21 1395 +#define _STORE_DEREF_r10 1396 +#define _STORE_FAST_LOAD_FAST_r11 1397 +#define _STORE_FAST_STORE_FAST_r20 1398 +#define _STORE_GLOBAL_r10 1399 +#define _STORE_NAME_r10 1400 +#define _STORE_SLICE_r30 1401 +#define _STORE_SUBSCR_r30 1402 +#define _STORE_SUBSCR_DICT_r31 1403 +#define _STORE_SUBSCR_LIST_INT_r32 1404 +#define _SWAP_r11 1405 +#define _SWAP_2_r02 1406 +#define _SWAP_2_r12 1407 +#define _SWAP_2_r22 1408 +#define _SWAP_2_r33 1409 +#define _SWAP_3_r03 1410 +#define _SWAP_3_r13 1411 +#define _SWAP_3_r23 1412 +#define _SWAP_3_r33 1413 +#define _SWAP_FAST_r01 1414 +#define _SWAP_FAST_r11 1415 +#define _SWAP_FAST_r22 1416 +#define _SWAP_FAST_r33 1417 +#define _SWAP_FAST_0_r01 1418 +#define _SWAP_FAST_0_r11 1419 +#define _SWAP_FAST_0_r22 1420 +#define _SWAP_FAST_0_r33 1421 +#define _SWAP_FAST_1_r01 1422 +#define _SWAP_FAST_1_r11 1423 +#define _SWAP_FAST_1_r22 1424 +#define _SWAP_FAST_1_r33 1425 +#define _SWAP_FAST_2_r01 1426 +#define _SWAP_FAST_2_r11 1427 +#define _SWAP_FAST_2_r22 1428 +#define _SWAP_FAST_2_r33 1429 +#define _SWAP_FAST_3_r01 1430 +#define _SWAP_FAST_3_r11 1431 +#define _SWAP_FAST_3_r22 1432 +#define _SWAP_FAST_3_r33 1433 +#define _SWAP_FAST_4_r01 1434 +#define _SWAP_FAST_4_r11 1435 +#define _SWAP_FAST_4_r22 1436 +#define _SWAP_FAST_4_r33 1437 +#define _SWAP_FAST_5_r01 1438 +#define _SWAP_FAST_5_r11 1439 +#define _SWAP_FAST_5_r22 1440 +#define _SWAP_FAST_5_r33 1441 +#define _SWAP_FAST_6_r01 1442 +#define _SWAP_FAST_6_r11 1443 +#define _SWAP_FAST_6_r22 1444 +#define _SWAP_FAST_6_r33 1445 +#define _SWAP_FAST_7_r01 1446 +#define _SWAP_FAST_7_r11 1447 +#define _SWAP_FAST_7_r22 1448 +#define _SWAP_FAST_7_r33 1449 +#define _TIER2_RESUME_CHECK_r00 1450 +#define _TIER2_RESUME_CHECK_r11 1451 +#define _TIER2_RESUME_CHECK_r22 1452 +#define _TIER2_RESUME_CHECK_r33 1453 +#define _TO_BOOL_r11 1454 +#define _TO_BOOL_BOOL_r01 1455 +#define _TO_BOOL_BOOL_r11 1456 +#define _TO_BOOL_BOOL_r22 1457 +#define _TO_BOOL_BOOL_r33 1458 +#define _TO_BOOL_INT_r02 1459 +#define _TO_BOOL_INT_r12 1460 +#define _TO_BOOL_INT_r23 1461 +#define _TO_BOOL_LIST_r02 1462 +#define _TO_BOOL_LIST_r12 1463 +#define _TO_BOOL_LIST_r23 1464 +#define _TO_BOOL_NONE_r01 1465 +#define _TO_BOOL_NONE_r11 1466 +#define _TO_BOOL_NONE_r22 1467 +#define _TO_BOOL_NONE_r33 1468 +#define _TO_BOOL_STR_r02 1469 +#define _TO_BOOL_STR_r12 1470 +#define _TO_BOOL_STR_r23 1471 +#define _TRACE_RECORD_r00 1472 +#define _UNARY_INVERT_r12 1473 +#define _UNARY_NEGATIVE_r12 1474 +#define _UNARY_NOT_r01 1475 +#define _UNARY_NOT_r11 1476 +#define _UNARY_NOT_r22 1477 +#define _UNARY_NOT_r33 1478 +#define _UNPACK_EX_r10 1479 +#define _UNPACK_SEQUENCE_r10 1480 +#define _UNPACK_SEQUENCE_LIST_r10 1481 +#define _UNPACK_SEQUENCE_TUPLE_r10 1482 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1483 +#define _WITH_EXCEPT_START_r33 1484 +#define _YIELD_VALUE_r11 1485 +#define MAX_UOP_REGS_ID 1485 #ifdef __cplusplus } diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index c46368444f4..f9173fd83c2 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -201,21 +201,22 @@ extern "C" { #define LOAD_SUPER_ATTR_ATTR 195 #define LOAD_SUPER_ATTR_METHOD 196 #define RESUME_CHECK 197 -#define SEND_GEN 198 -#define STORE_ATTR_INSTANCE_VALUE 199 -#define STORE_ATTR_SLOT 200 -#define STORE_ATTR_WITH_HINT 201 -#define STORE_SUBSCR_DICT 202 -#define STORE_SUBSCR_LIST_INT 203 -#define TO_BOOL_ALWAYS_TRUE 204 -#define TO_BOOL_BOOL 205 -#define TO_BOOL_INT 206 -#define TO_BOOL_LIST 207 -#define TO_BOOL_NONE 208 -#define TO_BOOL_STR 209 -#define UNPACK_SEQUENCE_LIST 210 -#define UNPACK_SEQUENCE_TUPLE 211 -#define UNPACK_SEQUENCE_TWO_TUPLE 212 +#define RESUME_CHECK_JIT 198 +#define SEND_GEN 199 +#define STORE_ATTR_INSTANCE_VALUE 200 +#define STORE_ATTR_SLOT 201 +#define STORE_ATTR_WITH_HINT 202 +#define STORE_SUBSCR_DICT 203 +#define STORE_SUBSCR_LIST_INT 204 +#define TO_BOOL_ALWAYS_TRUE 205 +#define TO_BOOL_BOOL 206 +#define TO_BOOL_INT 207 +#define TO_BOOL_LIST 208 +#define TO_BOOL_NONE 209 +#define TO_BOOL_STR 210 +#define UNPACK_SEQUENCE_LIST 211 +#define UNPACK_SEQUENCE_TUPLE 212 +#define UNPACK_SEQUENCE_TWO_TUPLE 213 #define INSTRUMENTED_END_FOR 233 #define INSTRUMENTED_POP_ITER 234 #define INSTRUMENTED_END_SEND 235 diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 6e37288c32d..8d2c1ece8bc 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -5,6 +5,7 @@ _specializations = frozendict( RESUME=( "RESUME_CHECK", + "RESUME_CHECK_JIT", ), TO_BOOL=( "TO_BOOL_ALWAYS_TRUE", @@ -195,21 +196,22 @@ _specialized_opmap = frozendict( LOAD_SUPER_ATTR_ATTR=195, LOAD_SUPER_ATTR_METHOD=196, RESUME_CHECK=197, - SEND_GEN=198, - STORE_ATTR_INSTANCE_VALUE=199, - STORE_ATTR_SLOT=200, - STORE_ATTR_WITH_HINT=201, - STORE_SUBSCR_DICT=202, - STORE_SUBSCR_LIST_INT=203, - TO_BOOL_ALWAYS_TRUE=204, - TO_BOOL_BOOL=205, - TO_BOOL_INT=206, - TO_BOOL_LIST=207, - TO_BOOL_NONE=208, - TO_BOOL_STR=209, - UNPACK_SEQUENCE_LIST=210, - UNPACK_SEQUENCE_TUPLE=211, - UNPACK_SEQUENCE_TWO_TUPLE=212, + RESUME_CHECK_JIT=198, + SEND_GEN=199, + STORE_ATTR_INSTANCE_VALUE=200, + STORE_ATTR_SLOT=201, + STORE_ATTR_WITH_HINT=202, + STORE_SUBSCR_DICT=203, + STORE_SUBSCR_LIST_INT=204, + TO_BOOL_ALWAYS_TRUE=205, + TO_BOOL_BOOL=206, + TO_BOOL_INT=207, + TO_BOOL_LIST=208, + TO_BOOL_NONE=209, + TO_BOOL_STR=210, + UNPACK_SEQUENCE_LIST=211, + UNPACK_SEQUENCE_TUPLE=212, + UNPACK_SEQUENCE_TWO_TUPLE=213, ) opmap = frozendict( diff --git a/Lib/opcode.py b/Lib/opcode.py index 165f42baed9..d53b94d89b4 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -119,6 +119,9 @@ POP_JUMP_IF_NOT_NONE=frozendict( counter=1, ), + RESUME=frozendict( + counter=1, + ), ) _inline_cache_entries = frozendict({ diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index d66031ed31c..1385a7f840d 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -15,7 +15,7 @@ _testinternalcapi = import_helper.import_module("_testinternalcapi") -from _testinternalcapi import _PY_NSMALLPOSINTS, TIER2_THRESHOLD +from _testinternalcapi import _PY_NSMALLPOSINTS, TIER2_THRESHOLD, TIER2_RESUME_THRESHOLD #For test of issue 136154 GLOBAL_136154 = 42 @@ -322,6 +322,23 @@ def testfunc(n): uops = get_opnames(ex) self.assertIn("_JUMP_TO_TOP", uops) + def test_resume(self): + def testfunc(x): + if x <= 1: + return 1 + return testfunc(x-1) + + for _ in range((TIER2_RESUME_THRESHOLD + 99)//100): + testfunc(101) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # 0. _START_EXECUTOR + # 1. _MAKE_WARM + # 2. _TIER2_RESUME_CHECK + self.assertEqual(uops[2], "_TIER2_RESUME_CHECK") + def test_jump_forward(self): def testfunc(n): a = 0 @@ -1419,7 +1436,7 @@ def test_guard_type_version_removed_invalidation(self): def thing(a): x = 0 - for i in range(TIER2_THRESHOLD * 2 + 1): + for i in range(TIER2_THRESHOLD + 1): x += a.attr # The first TIER2_THRESHOLD iterations we set the attribute on # this dummy class, which shouldn't trigger the type watcher. @@ -1437,8 +1454,7 @@ class Bar: res, ex = self._run_with_optimizer(thing, Foo()) opnames = list(iter_opnames(ex)) - self.assertIsNotNone(ex) - self.assertEqual(res, TIER2_THRESHOLD * 6 + 1) + self.assertEqual(res, TIER2_THRESHOLD * 2 + 2) call = opnames.index("_CALL_BUILTIN_FAST") load_attr_top = opnames.index("_POP_TOP_LOAD_CONST_INLINE_BORROW", 0, call) load_attr_bottom = opnames.index("_POP_TOP_LOAD_CONST_INLINE_BORROW", call) diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 0d5c6e6e77f..19fa387cd7b 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -1437,6 +1437,7 @@ def f(): co_code=bytes( [ dis.opmap["RESUME"], 0, + dis.opmap["CACHE"], 0, dis.opmap["LOAD_COMMON_CONSTANT"], 0, dis.opmap["RAISE_VARARGS"], 1, ] @@ -1445,7 +1446,7 @@ def f(): [ (1 << 7) | (PY_CODE_LOCATION_INFO_NO_COLUMNS << 3) - | (3 - 1), + | (4 - 1), 0, ] ), @@ -1453,7 +1454,7 @@ def f(): self.assertRaises(AssertionError, f) self.assertEqual( list(f.__code__.co_positions()), - 3 * [(42, 42, None, None)], + 4 * [(42, 42, None, None)], ) @cpython_only diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 302b2c21935..ac8837359c1 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -2458,8 +2458,8 @@ def test_lambda_return_position(self): for i, pos in enumerate(positions): with self.subTest(i=i, pos=pos): start_line, end_line, start_col, end_col = pos - if i == 0 and start_col == end_col == 0: - # ignore the RESUME in the beginning + if i <= 1: + # ignore the RESUME and CACHE in the beginning continue self.assertEqual(start_line, 1) self.assertEqual(end_line, 1) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index cefd64ddfe8..f4210db5bd7 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -127,13 +127,13 @@ def _f(a): dis_f_with_offsets = """\ %3d 0 RESUME 0 -%3d 2 LOAD_GLOBAL 1 (print + NULL) - 12 LOAD_FAST_BORROW 0 (a) - 14 CALL 1 - 22 POP_TOP +%3d 4 LOAD_GLOBAL 1 (print + NULL) + 14 LOAD_FAST_BORROW 0 (a) + 16 CALL 1 + 24 POP_TOP -%3d 24 LOAD_SMALL_INT 1 - 26 RETURN_VALUE +%3d 26 LOAD_SMALL_INT 1 + 28 RETURN_VALUE """ % (_f.__code__.co_firstlineno, _f.__code__.co_firstlineno + 1, _f.__code__.co_firstlineno + 2) @@ -617,10 +617,10 @@ async def _asyncwith(c): CALL 0 GET_AWAITABLE 1 LOAD_CONST 0 (None) - L2: SEND 3 (to L5) + L2: SEND 4 (to L5) L3: YIELD_VALUE 1 L4: RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to L2) + JUMP_BACKWARD_NO_INTERRUPT 6 (to L2) L5: END_SEND L6: POP_TOP @@ -633,10 +633,10 @@ async def _asyncwith(c): CALL 3 GET_AWAITABLE 2 LOAD_CONST 0 (None) - L8: SEND 3 (to L11) + L8: SEND 4 (to L11) L9: YIELD_VALUE 1 L10: RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to L8) + JUMP_BACKWARD_NO_INTERRUPT 6 (to L8) L11: END_SEND POP_TOP @@ -646,17 +646,17 @@ async def _asyncwith(c): RETURN_VALUE %4d L12: CLEANUP_THROW - L13: JUMP_BACKWARD_NO_INTERRUPT 26 (to L5) + L13: JUMP_BACKWARD_NO_INTERRUPT 27 (to L5) L14: CLEANUP_THROW L15: JUMP_BACKWARD_NO_INTERRUPT 10 (to L11) L16: PUSH_EXC_INFO WITH_EXCEPT_START GET_AWAITABLE 2 LOAD_CONST 0 (None) - L17: SEND 4 (to L21) + L17: SEND 5 (to L21) L18: YIELD_VALUE 1 L19: RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 5 (to L17) + JUMP_BACKWARD_NO_INTERRUPT 6 (to L17) L20: CLEANUP_THROW L21: END_SEND TO_BOOL @@ -880,7 +880,7 @@ def foo(x): RETURN_GENERATOR POP_TOP L1: RESUME 0 - L2: FOR_ITER 14 (to L3) + L2: FOR_ITER 15 (to L3) STORE_FAST 1 (z) LOAD_DEREF 2 (x) LOAD_FAST_BORROW 1 (z) @@ -888,7 +888,7 @@ def foo(x): YIELD_VALUE 0 RESUME 5 POP_TOP - JUMP_BACKWARD 16 (to L2) + JUMP_BACKWARD 17 (to L2) L3: END_FOR POP_ITER LOAD_CONST 0 (None) @@ -909,7 +909,7 @@ def load_test(x, y=0): return a, b dis_load_test_quickened_code = """\ -%3d RESUME_CHECK 0 +%3d RESUME_CHECK{: <6} 0 %3d LOAD_FAST_LOAD_FAST 1 (x, y) STORE_FAST_STORE_FAST 50 (b, a) @@ -926,7 +926,7 @@ def loop_test(): load_test(i) dis_loop_test_quickened_code = """\ -%3d RESUME_CHECK 0 +%3d RESUME_CHECK{: <6} 0 %3d BUILD_LIST 0 LOAD_CONST 2 ((1, 2, 3)) @@ -1323,13 +1323,15 @@ def code_quicken(f): def test_super_instructions(self): self.code_quicken(lambda: load_test(0, 0)) got = self.get_disassembly(load_test, adaptive=True) - self.do_disassembly_compare(got, dis_load_test_quickened_code) + jit = sys._jit.is_enabled() + expected = dis_load_test_quickened_code.format("_JIT" if jit else "") + self.do_disassembly_compare(got, expected) @cpython_only @requires_specialization def test_load_attr_specialize(self): load_attr_quicken = """\ - 0 RESUME_CHECK 0 + 0 RESUME_CHECK{: <6} 0 1 LOAD_CONST 0 ('a') LOAD_ATTR_SLOT 0 (__class__) @@ -1338,13 +1340,15 @@ def test_load_attr_specialize(self): co = compile("'a'.__class__", "", "eval") self.code_quicken(lambda: exec(co, {}, {})) got = self.get_disassembly(co, adaptive=True) - self.do_disassembly_compare(got, load_attr_quicken) + jit = sys._jit.is_enabled() + expected = load_attr_quicken.format("_JIT" if jit else "") + self.do_disassembly_compare(got, expected) @cpython_only @requires_specialization def test_call_specialize(self): call_quicken = """\ - 0 RESUME_CHECK 0 + 0 RESUME_CHECK{: <6} 0 1 LOAD_NAME 0 (str) PUSH_NULL @@ -1355,7 +1359,9 @@ def test_call_specialize(self): co = compile("str(1)", "", "eval") self.code_quicken(lambda: exec(co, {}, {})) got = self.get_disassembly(co, adaptive=True) - self.do_disassembly_compare(got, call_quicken) + jit = sys._jit.is_enabled() + expected = call_quicken.format("_JIT" if jit else "") + self.do_disassembly_compare(got, expected) @cpython_only @requires_specialization @@ -1364,7 +1370,9 @@ def test_loop_quicken(self): self.code_quicken(loop_test) got = self.get_disassembly(loop_test, adaptive=True) jit = sys._jit.is_enabled() - expected = dis_loop_test_quickened_code.format("JIT" if jit else "NO_JIT") + resume_str = "_JIT" if jit else "" + jit_str = "JIT " if jit else "NO_JIT" + expected = dis_loop_test_quickened_code.format(resume_str, jit_str) self.do_disassembly_compare(got, expected) @cpython_only @@ -1431,7 +1439,7 @@ def test_show_caches(self): caches = list(self.get_cached_values(quickened, adaptive)) for cache in caches: self.assertRegex(cache, pattern) - total_caches = 21 + total_caches = 22 empty_caches = 7 self.assertEqual(caches.count(""), empty_caches) self.assertEqual(len(caches), total_caches) @@ -1776,210 +1784,210 @@ def _prepare_test_cases(): expected_opinfo_outer = [ make_inst(opname='MAKE_CELL', arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None), make_inst(opname='MAKE_CELL', arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None), - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1), - make_inst(opname='LOAD_CONST', arg=4, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2), - make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2), - make_inst(opname='BUILD_TUPLE', arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2), - make_inst(opname='LOAD_CONST', arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2), - make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2), - make_inst(opname='STORE_FAST', arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=False, line_number=2), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_DEREF', arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7), - make_inst(opname='LOAD_DEREF', arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7), - make_inst(opname='LOAD_CONST', arg=2, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=7), - make_inst(opname='BUILD_LIST', arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7), - make_inst(opname='BUILD_MAP', arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7), - make_inst(opname='LOAD_CONST', arg=3, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7), - make_inst(opname='CALL', arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7), - make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=8), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=4, argval=(3, 4), argrepr='(3, 4)', offset=8, start_offset=8, starts_line=True, line_number=2), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=2), + make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=2), + make_inst(opname='BUILD_TUPLE', arg=2, argval=2, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=2), + make_inst(opname='LOAD_CONST', arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=16, start_offset=16, starts_line=False, line_number=2), + make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=2), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=20, start_offset=20, starts_line=False, line_number=2), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=22, start_offset=22, starts_line=False, line_number=2), + make_inst(opname='STORE_FAST', arg=2, argval='f', argrepr='f', offset=24, start_offset=24, starts_line=False, line_number=2), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=26, start_offset=26, starts_line=True, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_DEREF', arg=0, argval='a', argrepr='a', offset=36, start_offset=36, starts_line=False, line_number=7), + make_inst(opname='LOAD_DEREF', arg=1, argval='b', argrepr='b', offset=38, start_offset=38, starts_line=False, line_number=7), + make_inst(opname='LOAD_CONST', arg=2, argval='', argrepr="''", offset=40, start_offset=40, starts_line=False, line_number=7), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7), + make_inst(opname='BUILD_LIST', arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7), + make_inst(opname='BUILD_MAP', arg=0, argval=0, argrepr='', offset=46, start_offset=46, starts_line=False, line_number=7), + make_inst(opname='LOAD_CONST', arg=3, argval='Hello world!', argrepr="'Hello world!'", offset=48, start_offset=48, starts_line=False, line_number=7), + make_inst(opname='CALL', arg=7, argval=7, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=7), + make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='f', argrepr='f', offset=60, start_offset=60, starts_line=True, line_number=8), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=62, start_offset=62, starts_line=False, line_number=8), ] expected_opinfo_f = [ make_inst(opname='COPY_FREE_VARS', arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None), make_inst(opname='MAKE_CELL', arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None), make_inst(opname='MAKE_CELL', arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None), - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2), - make_inst(opname='LOAD_CONST', arg=2, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3), - make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3), - make_inst(opname='BUILD_TUPLE', arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3), - make_inst(opname='LOAD_CONST', arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3), - make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3), - make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3), - make_inst(opname='STORE_FAST', arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_DEREF', arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=False, line_number=5), - make_inst(opname='LOAD_DEREF', arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=False, line_number=5), - make_inst(opname='LOAD_DEREF', arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=False, line_number=5), - make_inst(opname='LOAD_DEREF', arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=False, line_number=5), - make_inst(opname='CALL', arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5), - make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=True, line_number=6), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=6), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=2, argval=(5, 6), argrepr='(5, 6)', offset=10, start_offset=10, starts_line=True, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=3, argval='a', argrepr='a', offset=12, start_offset=12, starts_line=False, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=4, argval='b', argrepr='b', offset=14, start_offset=14, starts_line=False, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='c', argrepr='c', offset=16, start_offset=16, starts_line=False, line_number=3), + make_inst(opname='LOAD_FAST_BORROW', arg=1, argval='d', argrepr='d', offset=18, start_offset=18, starts_line=False, line_number=3), + make_inst(opname='BUILD_TUPLE', arg=4, argval=4, argrepr='', offset=20, start_offset=20, starts_line=False, line_number=3), + make_inst(opname='LOAD_CONST', arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=22, start_offset=22, starts_line=False, line_number=3), + make_inst(opname='MAKE_FUNCTION', arg=None, argval=None, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=8, argval=8, argrepr='closure', offset=26, start_offset=26, starts_line=False, line_number=3), + make_inst(opname='SET_FUNCTION_ATTRIBUTE', arg=1, argval=1, argrepr='defaults', offset=28, start_offset=28, starts_line=False, line_number=3), + make_inst(opname='STORE_FAST', arg=2, argval='inner', argrepr='inner', offset=30, start_offset=30, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=32, start_offset=32, starts_line=True, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_DEREF', arg=3, argval='a', argrepr='a', offset=42, start_offset=42, starts_line=False, line_number=5), + make_inst(opname='LOAD_DEREF', arg=4, argval='b', argrepr='b', offset=44, start_offset=44, starts_line=False, line_number=5), + make_inst(opname='LOAD_DEREF', arg=0, argval='c', argrepr='c', offset=46, start_offset=46, starts_line=False, line_number=5), + make_inst(opname='LOAD_DEREF', arg=1, argval='d', argrepr='d', offset=48, start_offset=48, starts_line=False, line_number=5), + make_inst(opname='CALL', arg=4, argval=4, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=58, start_offset=58, starts_line=False, line_number=5), + make_inst(opname='LOAD_FAST_BORROW', arg=2, argval='inner', argrepr='inner', offset=60, start_offset=60, starts_line=True, line_number=6), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=62, start_offset=62, starts_line=False, line_number=6), ] expected_opinfo_inner = [ make_inst(opname='COPY_FREE_VARS', arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None), - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=True, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=4, start_offset=4, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_DEREF', arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=False, line_number=4), - make_inst(opname='LOAD_DEREF', arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=False, line_number=4), - make_inst(opname='LOAD_DEREF', arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=False, line_number=4), - make_inst(opname='LOAD_DEREF', arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=False, line_number=4), - make_inst(opname='LOAD_FAST_BORROW_LOAD_FAST_BORROW', arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=False, line_number=4), - make_inst(opname='CALL', arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=False, line_number=4), - make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=False, line_number=4), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=36, start_offset=36, starts_line=False, line_number=4), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='print', argrepr='print + NULL', offset=6, start_offset=6, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_DEREF', arg=2, argval='a', argrepr='a', offset=16, start_offset=16, starts_line=False, line_number=4), + make_inst(opname='LOAD_DEREF', arg=3, argval='b', argrepr='b', offset=18, start_offset=18, starts_line=False, line_number=4), + make_inst(opname='LOAD_DEREF', arg=4, argval='c', argrepr='c', offset=20, start_offset=20, starts_line=False, line_number=4), + make_inst(opname='LOAD_DEREF', arg=5, argval='d', argrepr='d', offset=22, start_offset=22, starts_line=False, line_number=4), + make_inst(opname='LOAD_FAST_BORROW_LOAD_FAST_BORROW', arg=1, argval=('e', 'f'), argrepr='e, f', offset=24, start_offset=24, starts_line=False, line_number=4), + make_inst(opname='CALL', arg=6, argval=6, argrepr='', offset=26, start_offset=26, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=34, start_offset=34, starts_line=False, line_number=4), + make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=36, start_offset=36, starts_line=False, line_number=4), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=38, start_offset=38, starts_line=False, line_number=4), ] expected_opinfo_jumpy = [ - make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=1), - make_inst(opname='LOAD_GLOBAL', arg=1, argval='range', argrepr='range + NULL', offset=2, start_offset=2, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3), - make_inst(opname='FOR_ITER', arg=33, argval=94, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=4), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=True, line_number=5), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=5), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=70, argrepr='to L2', offset=60, start_offset=60, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=64, start_offset=64, starts_line=False, line_number=5), - make_inst(opname='JUMP_BACKWARD', arg=23, argval=24, argrepr='to L1', offset=66, start_offset=66, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=70, start_offset=70, starts_line=True, line_number=7, label=2), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=72, start_offset=72, starts_line=False, line_number=7), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=74, start_offset=74, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=88, argrepr='to L3', offset=78, start_offset=78, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=82, start_offset=82, starts_line=False, line_number=7), - make_inst(opname='JUMP_BACKWARD', arg=32, argval=24, argrepr='to L1', offset=84, start_offset=84, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=8, label=3), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=False, line_number=8), - make_inst(opname='JUMP_FORWARD', arg=13, argval=120, argrepr='to L5', offset=92, start_offset=92, starts_line=False, line_number=8), - make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=True, line_number=3, label=4), - make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=98, start_offset=98, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=108, start_offset=108, starts_line=False, line_number=10), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=110, start_offset=110, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=118, start_offset=118, starts_line=False, line_number=10), - make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=120, start_offset=120, starts_line=True, line_number=11, label=5), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=122, start_offset=122, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=214, argrepr='to L8', offset=130, start_offset=130, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=134, start_offset=134, starts_line=False, line_number=11), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=136, start_offset=136, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=146, start_offset=146, starts_line=False, line_number=12), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=148, start_offset=148, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=156, start_offset=156, starts_line=False, line_number=12), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=158, start_offset=158, starts_line=True, line_number=13), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=160, start_offset=160, starts_line=False, line_number=13), - make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=162, start_offset=162, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=False, line_number=13), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=True, line_number=14), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=178, start_offset=178, starts_line=False, line_number=14), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=180, start_offset=180, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=194, argrepr='to L6', offset=184, start_offset=184, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=188, start_offset=188, starts_line=False, line_number=14), - make_inst(opname='JUMP_BACKWARD', arg=37, argval=120, argrepr='to L5', offset=190, start_offset=190, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=194, start_offset=194, starts_line=True, line_number=16, label=6), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=196, start_offset=196, starts_line=False, line_number=16), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=198, start_offset=198, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=212, argrepr='to L7', offset=202, start_offset=202, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=206, start_offset=206, starts_line=False, line_number=16), - make_inst(opname='JUMP_BACKWARD', arg=46, argval=120, argrepr='to L5', offset=208, start_offset=208, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='JUMP_FORWARD', arg=11, argval=236, argrepr='to L9', offset=212, start_offset=212, starts_line=True, line_number=17, label=7), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=214, start_offset=214, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=224, start_offset=224, starts_line=False, line_number=19), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=226, start_offset=226, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=234, start_offset=234, starts_line=False, line_number=19), - make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=True, line_number=20, label=9), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=238, start_offset=238, starts_line=True, line_number=21), - make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=21), - make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=242, start_offset=242, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=254, start_offset=254, starts_line=False, line_number=21), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=256, start_offset=256, starts_line=True, line_number=25), - make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=258, start_offset=258, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=260, start_offset=260, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=264, start_offset=264, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=266, start_offset=266, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=268, start_offset=268, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=276, start_offset=276, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=278, start_offset=278, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=288, start_offset=288, starts_line=False, line_number=26), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=290, start_offset=290, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=298, start_offset=298, starts_line=False, line_number=26), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=300, start_offset=300, starts_line=True, line_number=25), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=False, line_number=25), + make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_GLOBAL', arg=1, argval='range', argrepr='range + NULL', offset=4, start_offset=4, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=3), + make_inst(opname='FOR_ITER', arg=33, argval=96, argrepr='to L4', offset=26, start_offset=26, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=30, start_offset=30, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=32, start_offset=32, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=42, start_offset=42, starts_line=False, line_number=4), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=52, start_offset=52, starts_line=False, line_number=4), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=54, start_offset=54, starts_line=True, line_number=5), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=58, start_offset=58, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=72, argrepr='to L2', offset=62, start_offset=62, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=66, start_offset=66, starts_line=False, line_number=5), + make_inst(opname='JUMP_BACKWARD', arg=23, argval=26, argrepr='to L1', offset=68, start_offset=68, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=72, start_offset=72, starts_line=True, line_number=7, label=2), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=74, start_offset=74, starts_line=False, line_number=7), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=76, start_offset=76, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=90, argrepr='to L3', offset=80, start_offset=80, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=False, line_number=7), + make_inst(opname='JUMP_BACKWARD', arg=32, argval=26, argrepr='to L1', offset=86, start_offset=86, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=True, line_number=8, label=3), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=False, line_number=8), + make_inst(opname='JUMP_FORWARD', arg=13, argval=122, argrepr='to L5', offset=94, start_offset=94, starts_line=False, line_number=8), + make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=True, line_number=3, label=4), + make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=98, start_offset=98, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=100, start_offset=100, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=110, start_offset=110, starts_line=False, line_number=10), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=112, start_offset=112, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=120, start_offset=120, starts_line=False, line_number=10), + make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=122, start_offset=122, starts_line=True, line_number=11, label=5), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=124, start_offset=124, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=216, argrepr='to L8', offset=132, start_offset=132, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=136, start_offset=136, starts_line=False, line_number=11), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=138, start_offset=138, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=148, start_offset=148, starts_line=False, line_number=12), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=150, start_offset=150, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=158, start_offset=158, starts_line=False, line_number=12), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=160, start_offset=160, starts_line=True, line_number=13), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=162, start_offset=162, starts_line=False, line_number=13), + make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=164, start_offset=164, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=False, line_number=13), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=178, start_offset=178, starts_line=True, line_number=14), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=180, start_offset=180, starts_line=False, line_number=14), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=182, start_offset=182, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=196, argrepr='to L6', offset=186, start_offset=186, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=190, start_offset=190, starts_line=False, line_number=14), + make_inst(opname='JUMP_BACKWARD', arg=37, argval=122, argrepr='to L5', offset=192, start_offset=192, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=196, start_offset=196, starts_line=True, line_number=16, label=6), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=198, start_offset=198, starts_line=False, line_number=16), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=200, start_offset=200, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=214, argrepr='to L7', offset=204, start_offset=204, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=208, start_offset=208, starts_line=False, line_number=16), + make_inst(opname='JUMP_BACKWARD', arg=46, argval=122, argrepr='to L5', offset=210, start_offset=210, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='JUMP_FORWARD', arg=11, argval=238, argrepr='to L9', offset=214, start_offset=214, starts_line=True, line_number=17, label=7), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=216, start_offset=216, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=226, start_offset=226, starts_line=False, line_number=19), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=228, start_offset=228, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=False, line_number=19), + make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=238, start_offset=238, starts_line=True, line_number=20, label=9), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=240, start_offset=240, starts_line=True, line_number=21), + make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=242, start_offset=242, starts_line=False, line_number=21), + make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=244, start_offset=244, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=256, start_offset=256, starts_line=False, line_number=21), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=258, start_offset=258, starts_line=True, line_number=25), + make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=260, start_offset=260, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=262, start_offset=262, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=264, start_offset=264, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=268, start_offset=268, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=270, start_offset=270, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=278, start_offset=278, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=280, start_offset=280, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=290, start_offset=290, starts_line=False, line_number=26), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=292, start_offset=292, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=300, start_offset=300, starts_line=False, line_number=26), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=True, line_number=25), make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=304, start_offset=304, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=306, start_offset=306, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=316, start_offset=316, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=326, start_offset=326, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=328, start_offset=328, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=336, start_offset=336, starts_line=False, line_number=28), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=338, start_offset=338, starts_line=False, line_number=28), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=28), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=True, line_number=25), - make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=25), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=362, argrepr='to L11', offset=354, start_offset=354, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25), - make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25, label=11), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=306, start_offset=306, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=308, start_offset=308, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=318, start_offset=318, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=328, start_offset=328, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=330, start_offset=330, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=28), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=340, start_offset=340, starts_line=False, line_number=28), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=28), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=True, line_number=25), + make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=364, argrepr='to L11', offset=356, start_offset=356, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25), + make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25, label=11), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25), make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25), make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=False, line_number=25), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=316, argrepr='to L10', offset=372, start_offset=372, starts_line=False, line_number=25), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=374, start_offset=374, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=382, start_offset=382, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=392, start_offset=392, starts_line=False, line_number=22), - make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=428, argrepr='to L12', offset=394, start_offset=394, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=398, start_offset=398, starts_line=False, line_number=22), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=22), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=402, start_offset=402, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=412, start_offset=412, starts_line=False, line_number=23), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=414, start_offset=414, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=422, start_offset=422, starts_line=False, line_number=23), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=316, argrepr='to L10', offset=426, start_offset=426, starts_line=False, line_number=23), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=428, start_offset=428, starts_line=True, line_number=22, label=12), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=438, start_offset=438, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=448, start_offset=448, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=450, start_offset=450, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=458, start_offset=458, starts_line=False, line_number=28), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=460, start_offset=460, starts_line=False, line_number=28), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=462, start_offset=462, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=None), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=372, start_offset=372, starts_line=False, line_number=25), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=318, argrepr='to L10', offset=374, start_offset=374, starts_line=False, line_number=25), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=376, start_offset=376, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=384, start_offset=384, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=394, start_offset=394, starts_line=False, line_number=22), + make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=430, argrepr='to L12', offset=396, start_offset=396, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=22), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=402, start_offset=402, starts_line=False, line_number=22), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=404, start_offset=404, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=414, start_offset=414, starts_line=False, line_number=23), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=416, start_offset=416, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=426, start_offset=426, starts_line=False, line_number=23), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=318, argrepr='to L10', offset=428, start_offset=428, starts_line=False, line_number=23), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=22, label=12), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=432, start_offset=432, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=438, start_offset=438, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=440, start_offset=440, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=450, start_offset=450, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=452, start_offset=452, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=460, start_offset=460, starts_line=False, line_number=28), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=28), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=464, start_offset=464, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=468, start_offset=468, starts_line=False, line_number=None), ] # One last piece of inspect fodder to check the default line number handling def simple(): pass expected_opinfo_simple = [ make_inst(opname='RESUME', arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=simple.__code__.co_firstlineno), - make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=False, line_number=simple.__code__.co_firstlineno), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno), + make_inst(opname='LOAD_CONST', arg=0, argval=None, argrepr='None', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=6, start_offset=6, starts_line=False, line_number=simple.__code__.co_firstlineno), ] @@ -2370,8 +2378,10 @@ def test_from_traceback_dis(self): @requires_debug_ranges() def test_bytecode_co_positions(self): bytecode = dis.Bytecode("a=1") - for instr, positions in zip(bytecode, bytecode.codeobj.co_positions()): - assert instr.positions == positions + it = bytecode.codeobj.co_positions() + next(it) # Ignore the CACHE for the RESUME + for instr, positions in zip(bytecode, it): + self.assertEqual(instr.positions, positions) class TestBytecodeTestCase(BytecodeTestCase): def test_assert_not_in_with_op_not_in_bytecode(self): @@ -2439,7 +2449,7 @@ def func(): code = func.__code__ offsets = [linestart[0] for linestart in dis.findlinestarts(code)] - self.assertEqual(offsets, [0, 2]) + self.assertEqual(offsets, [0, 4]) class TestDisTraceback(DisTestBase): @@ -2576,6 +2586,7 @@ def test_show_cache(self): source = 'print()' expect = ''' 0 RESUME 0 + CACHE 0 (counter: 0) 1 LOAD_NAME 0 (print) PUSH_NULL @@ -2596,8 +2607,8 @@ def test_show_offsets(self): expect = ''' 0 0 RESUME 0 - 1 2 LOAD_CONST 0 (None) - 4 RETURN_VALUE + 1 4 LOAD_CONST 0 (None) + 6 RETURN_VALUE ''' for flag in ['-O', '--show-offsets']: self.check_output(source, expect, flag) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 1b22e0ec875..116a8bac6fb 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1214,19 +1214,20 @@ def func1(): line3 = 3 self.check_events(func1, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ - ('line', 'get_events', 10), - ('line', 'func1', 1), - ('instruction', 'func1', 2), - ('instruction', 'func1', 4), - ('line', 'func1', 2), - ('instruction', 'func1', 6), - ('instruction', 'func1', 8), - ('line', 'func1', 3), - ('instruction', 'func1', 10), - ('instruction', 'func1', 12), - ('instruction', 'func1', 14), - ('instruction', 'func1', 16), - ('line', 'get_events', 11)]) + ("line", "get_events", 10), + ("line", "func1", 1), + ("instruction", "func1", 4), + ("instruction", "func1", 6), + ("line", "func1", 2), + ("instruction", "func1", 8), + ("instruction", "func1", 10), + ("line", "func1", 3), + ("instruction", "func1", 12), + ("instruction", "func1", 14), + ("instruction", "func1", 16), + ("instruction", "func1", 18), + ("line", "get_events", 11), + ]) def test_c_call(self): @@ -1236,22 +1237,23 @@ def func2(): line3 = 3 self.check_events(func2, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ - ('line', 'get_events', 10), - ('line', 'func2', 1), - ('instruction', 'func2', 2), - ('instruction', 'func2', 4), - ('line', 'func2', 2), - ('instruction', 'func2', 6), - ('instruction', 'func2', 8), - ('instruction', 'func2', 28), - ('instruction', 'func2', 30), - ('instruction', 'func2', 38), - ('line', 'func2', 3), - ('instruction', 'func2', 40), - ('instruction', 'func2', 42), - ('instruction', 'func2', 44), - ('instruction', 'func2', 46), - ('line', 'get_events', 11)]) + ("line", "get_events", 10), + ("line", "func2", 1), + ("instruction", "func2", 4), + ("instruction", "func2", 6), + ("line", "func2", 2), + ("instruction", "func2", 8), + ("instruction", "func2", 10), + ("instruction", "func2", 30), + ("instruction", "func2", 32), + ("instruction", "func2", 40), + ("line", "func2", 3), + ("instruction", "func2", 42), + ("instruction", "func2", 44), + ("instruction", "func2", 46), + ("instruction", "func2", 48), + ("line", "get_events", 11), + ]) def test_try_except(self): @@ -1264,28 +1266,29 @@ def func3(): line = 6 self.check_events(func3, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ - ('line', 'get_events', 10), - ('line', 'func3', 1), - ('instruction', 'func3', 2), - ('line', 'func3', 2), - ('instruction', 'func3', 4), - ('instruction', 'func3', 6), - ('line', 'func3', 3), - ('instruction', 'func3', 8), - ('instruction', 'func3', 18), - ('instruction', 'func3', 20), - ('line', 'func3', 4), - ('instruction', 'func3', 22), - ('line', 'func3', 5), - ('instruction', 'func3', 24), - ('instruction', 'func3', 26), - ('instruction', 'func3', 28), - ('line', 'func3', 6), - ('instruction', 'func3', 30), - ('instruction', 'func3', 32), - ('instruction', 'func3', 34), - ('instruction', 'func3', 36), - ('line', 'get_events', 11)]) + ("line", "get_events", 10), + ("line", "func3", 1), + ("instruction", "func3", 4), + ("line", "func3", 2), + ("instruction", "func3", 6), + ("instruction", "func3", 8), + ("line", "func3", 3), + ("instruction", "func3", 10), + ("instruction", "func3", 20), + ("instruction", "func3", 22), + ("line", "func3", 4), + ("instruction", "func3", 24), + ("line", "func3", 5), + ("instruction", "func3", 26), + ("instruction", "func3", 28), + ("instruction", "func3", 30), + ("line", "func3", 6), + ("instruction", "func3", 32), + ("instruction", "func3", 34), + ("instruction", "func3", 36), + ("instruction", "func3", 38), + ("line", "get_events", 11), + ]) def test_with_restart(self): def func1(): @@ -1296,16 +1299,16 @@ def func1(): self.check_events(func1, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ ('line', 'get_events', 10), ('line', 'func1', 1), - ('instruction', 'func1', 2), ('instruction', 'func1', 4), - ('line', 'func1', 2), ('instruction', 'func1', 6), + ('line', 'func1', 2), ('instruction', 'func1', 8), - ('line', 'func1', 3), ('instruction', 'func1', 10), + ('line', 'func1', 3), ('instruction', 'func1', 12), ('instruction', 'func1', 14), ('instruction', 'func1', 16), + ('instruction', 'func1', 18), ('line', 'get_events', 11)]) sys.monitoring.restart_events() @@ -1313,16 +1316,16 @@ def func1(): self.check_events(func1, recorders = LINE_AND_INSTRUCTION_RECORDERS, expected = [ ('line', 'get_events', 10), ('line', 'func1', 1), - ('instruction', 'func1', 2), ('instruction', 'func1', 4), - ('line', 'func1', 2), ('instruction', 'func1', 6), + ('line', 'func1', 2), ('instruction', 'func1', 8), - ('line', 'func1', 3), ('instruction', 'func1', 10), + ('line', 'func1', 3), ('instruction', 'func1', 12), ('instruction', 'func1', 14), ('instruction', 'func1', 16), + ('instruction', 'func1', 18), ('line', 'get_events', 11)]) def test_turn_off_only_instruction(self): @@ -1370,10 +1373,10 @@ def func1(): line1 = 1 MUST_INCLUDE_LI = [ - ('instruction', 'func1', 2), - ('line', 'func1', 2), ('instruction', 'func1', 4), - ('instruction', 'func1', 6)] + ('line', 'func1', 2), + ('instruction', 'func1', 6), + ('instruction', 'func1', 8)] def test_line_then_instruction(self): recorders = [ LineRecorder, InstructionRecorder ] @@ -1390,11 +1393,11 @@ def func2(): len(()) MUST_INCLUDE_CI = [ - ('instruction', 'func2', 2), + ('instruction', 'func2', 4), ('call', 'func2', sys.monitoring.MISSING), ('call', 'len', ()), - ('instruction', 'func2', 12), - ('instruction', 'func2', 14)] + ('instruction', 'func2', 14), + ('instruction', 'func2', 16)] @@ -1609,11 +1612,11 @@ def whilefunc(n=0): ('branch right', 'whilefunc', 1, 3)]) self.check_events(func, recorders = BRANCH_OFFSET_RECORDERS, expected = [ - ('branch left', 'func', 28, 32), - ('branch right', 'func', 44, 58), - ('branch left', 'func', 28, 32), - ('branch left', 'func', 44, 50), - ('branch right', 'func', 28, 70)]) + ('branch left', 'func', 30, 34), + ('branch right', 'func', 46, 60), + ('branch left', 'func', 30, 34), + ('branch left', 'func', 46, 52), + ('branch right', 'func', 30, 72)]) def test_except_star(self): @@ -1640,8 +1643,8 @@ def func(): ('branch', 'func', 4, 4), ('line', 'func', 5), ('line', 'meth', 1), - ('jump', 'func', 5, '[offset=120]'), - ('branch', 'func', '[offset=124]', '[offset=130]'), + ('jump', 'func', 5, '[offset=122]'), + ('branch', 'func', '[offset=126]', '[offset=132]'), ('line', 'get_events', 11)]) self.check_events(func, recorders = FLOW_AND_LINE_RECORDERS, expected = [ @@ -1655,8 +1658,8 @@ def func(): ('line', 'func', 5), ('line', 'meth', 1), ('return', 'meth', None), - ('jump', 'func', 5, '[offset=120]'), - ('branch', 'func', '[offset=124]', '[offset=130]'), + ('jump', 'func', 5, '[offset=122]'), + ('branch', 'func', '[offset=126]', '[offset=132]'), ('return', 'func', None), ('line', 'get_events', 11)]) @@ -1668,8 +1671,8 @@ def foo(n=0): n += 1 return None - in_loop = ('branch left', 'foo', 10, 16) - exit_loop = ('branch right', 'foo', 10, 40) + in_loop = ('branch left', 'foo', 12, 18) + exit_loop = ('branch right', 'foo', 12, 42) self.check_events(foo, recorders = BRANCH_OFFSET_RECORDERS, expected = [ in_loop, in_loop, diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst new file mode 100644 index 00000000000..9808a27e9ea --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst @@ -0,0 +1 @@ +Support tracing from function entrypoints in the JIT. Patch by Ken Jin. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 8c316b7c8dd..e1acce8f586 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -3021,6 +3021,14 @@ module_exec(PyObject *module) return 1; } + // + 1 to specialize from RESUME to RESUME_CHECK_JIT + // + 1 more due to one loop spent on tracing. + long resume_threshold = interp->opt_config.resume_initial_value + 2; + if (PyModule_Add(module, "TIER2_RESUME_THRESHOLD", + PyLong_FromLong(resume_threshold)) < 0) { + return 1; + } + if (PyModule_Add(module, "SPECIALIZATION_THRESHOLD", PyLong_FromLong(ADAPTIVE_WARMUP_VALUE + 1)) < 0) { return 1; diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 2f6845399d9..948a413d98d 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -5691,12 +5691,22 @@ INSTRUCTION_STATS(ENTER_EXECUTOR); opcode = ENTER_EXECUTOR; #ifdef _Py_TIER2 - if (IS_JIT_TRACING()) { - next_instr = this_instr; - JUMP_TO_LABEL(stop_tracing); - } PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; + if (IS_JIT_TRACING()) { + int og_opcode = executor->vm_data.opcode; + int og_oparg = (oparg & ~255) | executor->vm_data.oparg; + next_instr = this_instr; + if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + opcode = og_opcode; + oparg = og_oparg; + DISPATCH_GOTO_NON_TRACING(); + } + JUMP_TO_LABEL(stop_tracing); + } assert(executor->vm_data.index == INSTR_OFFSET() - 1); assert(executor->vm_data.code == code); assert(executor->vm_data.valid); @@ -7436,8 +7446,9 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(INSTRUMENTED_RESUME); + /* Skip 1 cache entry */ // _LOAD_BYTECODE { #ifdef Py_GIL_DISABLED @@ -7786,16 +7797,19 @@ // _JIT { #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; _Py_BackoffCounter counter = this_instr[1].counter; - if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) && - this_instr->op.code == JUMP_BACKWARD_JIT && + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && next_instr->op.code != ENTER_EXECUTOR) { _Py_CODEUNIT *insert_exec_at = this_instr; while (oparg > 255) { oparg >>= 8; insert_exec_at--; } - int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, stack_pointer, 0, NULL, oparg, NULL); + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); if (succ) { ENTER_TRACING(); } @@ -10448,10 +10462,10 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME); PREDICTED_RESUME:; - _Py_CODEUNIT* const this_instr = next_instr - 1; + _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; // _LOAD_BYTECODE { @@ -10498,11 +10512,11 @@ } // _QUICKEN_RESUME { - #if ENABLE_SPECIALIZATION - if (tstate->tracing == 0 && this_instr->op.code == RESUME) { - FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK); - } - #endif /* ENABLE_SPECIALIZATION */ + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_Resume(this_instr, tstate, frame); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_IF_NOT_YIELD_FROM { @@ -10527,9 +10541,10 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME_CHECK); - static_assert(0 == 0, "incorrect cache size"); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ #if defined(__EMSCRIPTEN__) if (_Py_emscripten_signal_clock == 0) { UPDATE_MISS_STATS(RESUME); @@ -10557,6 +10572,76 @@ DISPATCH(); } + TARGET(RESUME_CHECK_JIT) { + #if _Py_TAIL_CALL_INTERP + int opcode = RESUME_CHECK_JIT; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(RESUME_CHECK_JIT); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ + // _RESUME_CHECK + { + #if defined(__EMSCRIPTEN__) + if (_Py_emscripten_signal_clock == 0) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; + #endif + uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); + uintptr_t version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + if (eval_breaker != version) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #ifdef Py_GIL_DISABLED + if (frame->tlbc_index != + ((_PyThreadStateImpl *)tstate)->tlbc_index) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #endif + } + // _JIT + { + #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; + _Py_BackoffCounter counter = this_instr[1].counter; + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && + next_instr->op.code != ENTER_EXECUTOR) { + _Py_CODEUNIT *insert_exec_at = this_instr; + while (oparg > 255) { + oparg >>= 8; + insert_exec_at--; + } + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); + if (succ) { + ENTER_TRACING(); + } + else { + this_instr[1].counter = restart_backoff_counter(counter); + } + } + else { + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + #endif + } + DISPATCH(); + } + TARGET(RETURN_GENERATOR) { #if _Py_TAIL_CALL_INTERP int opcode = RETURN_GENERATOR; diff --git a/Modules/_testinternalcapi/test_targets.h b/Modules/_testinternalcapi/test_targets.h index f57c33feec2..def462bacec 100644 --- a/Modules/_testinternalcapi/test_targets.h +++ b/Modules/_testinternalcapi/test_targets.h @@ -198,6 +198,7 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_SUPER_ATTR_ATTR, &&TARGET_LOAD_SUPER_ATTR_METHOD, &&TARGET_RESUME_CHECK, + &&TARGET_RESUME_CHECK_JIT, &&TARGET_SEND_GEN, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, @@ -232,7 +233,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, @@ -472,7 +472,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -718,6 +718,7 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RERAISE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESERVED(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK_JIT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_GENERATOR(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_VALUE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_SEND(TAIL_CALL_PARAMS); @@ -959,6 +960,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [RESERVED] = _TAIL_CALL_RESERVED, [RESUME] = _TAIL_CALL_RESUME, [RESUME_CHECK] = _TAIL_CALL_RESUME_CHECK, + [RESUME_CHECK_JIT] = _TAIL_CALL_RESUME_CHECK_JIT, [RETURN_GENERATOR] = _TAIL_CALL_RETURN_GENERATOR, [RETURN_VALUE] = _TAIL_CALL_RETURN_VALUE, [SEND] = _TAIL_CALL_SEND, @@ -1007,7 +1009,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, [214] = _TAIL_CALL_UNKNOWN_OPCODE, [215] = _TAIL_CALL_UNKNOWN_OPCODE, [216] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1217,6 +1218,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [RESERVED] = _TAIL_CALL_TRACE_RECORD, [RESUME] = _TAIL_CALL_TRACE_RECORD, [RESUME_CHECK] = _TAIL_CALL_TRACE_RECORD, + [RESUME_CHECK_JIT] = _TAIL_CALL_TRACE_RECORD, [RETURN_GENERATOR] = _TAIL_CALL_TRACE_RECORD, [RETURN_VALUE] = _TAIL_CALL_TRACE_RECORD, [SEND] = _TAIL_CALL_TRACE_RECORD, @@ -1265,7 +1267,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, [214] = _TAIL_CALL_UNKNOWN_OPCODE, [215] = _TAIL_CALL_UNKNOWN_OPCODE, [216] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Objects/codeobject.c b/Objects/codeobject.c index d26516f7c2f..fbf0985e905 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -931,8 +931,9 @@ PyUnstable_Code_New(int argcount, int kwonlyargcount, // NOTE: When modifying the construction of PyCode_NewEmpty, please also change // test.test_code.CodeLocationTest.test_code_new_empty to keep it in sync! -static const uint8_t assert0[6] = { +static const uint8_t assert0[8] = { RESUME, RESUME_AT_FUNC_START, + CACHE, 0, LOAD_COMMON_CONSTANT, CONSTANT_ASSERTIONERROR, RAISE_VARARGS, 1 }; @@ -940,7 +941,7 @@ static const uint8_t assert0[6] = { static const uint8_t linetable[2] = { (1 << 7) // New entry. | (PY_CODE_LOCATION_INFO_NO_COLUMNS << 3) - | (3 - 1), // Three code units. + | (4 - 1), // Four code units. 0, // Offset from co_firstlineno. }; @@ -966,7 +967,7 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) if (filename_ob == NULL) { goto failed; } - code_ob = PyBytes_FromStringAndSize((const char *)assert0, 6); + code_ob = PyBytes_FromStringAndSize((const char *)assert0, 8); if (code_ob == NULL) { goto failed; } diff --git a/Objects/genobject.c b/Objects/genobject.c index 5088500fc41..9dece8a7700 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -454,6 +454,7 @@ is_resume(_Py_CODEUNIT *instr) return ( code == RESUME || code == RESUME_CHECK || + code == RESUME_CHECK_JIT || code == INSTRUMENTED_RESUME ); } diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index f808544045e..1411eb1718b 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,39 +1,39 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0, - 0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1, - 73,0,116,0,94,0,82,1,73,4,116,1,93,2,33,0, - 82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0, - 82,3,93,0,80,6,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,52,2,0,0,0,0,0,0, - 31,0,93,1,80,8,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,33,0,52,0,0,0,0,0, - 0,0,82,4,44,26,0,0,0,0,0,0,0,0,0,0, - 116,5,82,7,16,0,70,24,0,0,116,6,93,2,33,0, - 82,5,93,6,12,0,82,6,93,5,93,6,44,26,0,0, - 0,0,0,0,0,0,0,0,12,0,50,4,52,1,0,0, - 0,0,0,0,31,0,75,26,0,0,9,0,30,0,82,1, - 35,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, - 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, - 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, - 122,7,99,111,110,102,105,103,32,122,2,58,32,41,5,218, - 12,112,114,111,103,114,97,109,95,110,97,109,101,218,10,101, - 120,101,99,117,116,97,98,108,101,218,15,117,115,101,95,101, - 110,118,105,114,111,110,109,101,110,116,218,17,99,111,110,102, - 105,103,117,114,101,95,99,95,115,116,100,105,111,218,14,98, - 117,102,102,101,114,101,100,95,115,116,100,105,111,41,7,218, - 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, - 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, - 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, - 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, - 0,0,218,18,116,101,115,116,95,102,114,111,122,101,110,109, - 97,105,110,46,112,121,218,8,60,109,111,100,117,108,101,62, - 114,18,0,0,0,1,0,0,0,115,94,0,0,0,240,3, - 1,1,1,243,8,0,1,11,219,0,24,225,0,5,208,6, - 26,212,0,27,217,0,5,128,106,144,35,151,40,145,40,212, - 0,27,216,9,26,215,9,38,210,9,38,211,9,40,168,24, - 213,9,50,128,6,243,2,6,12,2,128,67,241,14,0,5, - 10,136,71,144,67,144,53,152,2,152,54,160,35,157,59,152, - 45,208,10,40,214,4,41,243,15,6,12,2,114,16,0,0, - 0, + 0,0,0,0,0,243,186,0,0,0,128,0,0,0,94,0, + 82,1,73,0,116,0,94,0,82,1,73,4,116,1,93,2, + 33,0,82,2,52,1,0,0,0,0,0,0,31,0,93,2, + 33,0,82,3,93,0,80,6,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,52,2,0,0,0,0, + 0,0,31,0,93,1,80,8,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,33,0,52,0,0,0, + 0,0,0,0,82,4,44,26,0,0,0,0,0,0,0,0, + 0,0,116,5,82,7,16,0,70,24,0,0,116,6,93,2, + 33,0,82,5,93,6,12,0,82,6,93,5,93,6,44,26, + 0,0,0,0,0,0,0,0,0,0,12,0,50,4,52,1, + 0,0,0,0,0,0,31,0,75,26,0,0,9,0,30,0, + 82,1,35,0,41,8,233,0,0,0,0,78,122,18,70,114, + 111,122,101,110,32,72,101,108,108,111,32,87,111,114,108,100, + 122,8,115,121,115,46,97,114,103,118,218,6,99,111,110,102, + 105,103,122,7,99,111,110,102,105,103,32,122,2,58,32,41, + 5,218,12,112,114,111,103,114,97,109,95,110,97,109,101,218, + 10,101,120,101,99,117,116,97,98,108,101,218,15,117,115,101, + 95,101,110,118,105,114,111,110,109,101,110,116,218,17,99,111, + 110,102,105,103,117,114,101,95,99,95,115,116,100,105,111,218, + 14,98,117,102,102,101,114,101,100,95,115,116,100,105,111,41, + 7,218,3,115,121,115,218,17,95,116,101,115,116,105,110,116, + 101,114,110,97,108,99,97,112,105,218,5,112,114,105,110,116, + 218,4,97,114,103,118,218,11,103,101,116,95,99,111,110,102, + 105,103,115,114,3,0,0,0,218,3,107,101,121,169,0,243, + 0,0,0,0,218,18,116,101,115,116,95,102,114,111,122,101, + 110,109,97,105,110,46,112,121,218,8,60,109,111,100,117,108, + 101,62,114,18,0,0,0,1,0,0,0,115,94,0,0,0, + 241,3,1,1,1,243,8,0,1,11,219,0,24,225,0,5, + 208,6,26,212,0,27,217,0,5,128,106,144,35,151,40,145, + 40,212,0,27,216,9,26,215,9,38,210,9,38,211,9,40, + 168,24,213,9,50,128,6,243,2,6,12,2,128,67,241,14, + 0,5,10,136,71,144,67,144,53,152,2,152,54,160,35,157, + 59,152,45,208,10,40,214,4,41,243,15,6,12,2,114,16, + 0,0,0, }; diff --git a/Python/assemble.c b/Python/assemble.c index 8cc2d50a322..7c08488092d 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -669,7 +669,7 @@ makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_ // The offset (in code units) of the END_SEND from the SEND in the `yield from` sequence. -#define END_SEND_OFFSET 5 +#define END_SEND_OFFSET 6 static int resolve_jump_offsets(instr_sequence *instrs) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c26ba89b5ab..eaa123f8850 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -148,8 +148,9 @@ dummy_func( pure inst(NOP, (--)) { } - family(RESUME, 0) = { + family(RESUME, 1) = { RESUME_CHECK, + RESUME_CHECK_JIT, }; macro(NOT_TAKEN) = NOP; @@ -171,12 +172,8 @@ dummy_func( } } - op(_QUICKEN_RESUME, (--)) { - #if ENABLE_SPECIALIZATION - if (tstate->tracing == 0 && this_instr->op.code == RESUME) { - FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK); - } - #endif /* ENABLE_SPECIALIZATION */ + tier1 op(_QUICKEN_RESUME, (counter/1 --)) { + _Py_Specialize_Resume(this_instr, tstate, frame); } tier1 op(_MAYBE_INSTRUMENT, (--)) { @@ -226,7 +223,11 @@ dummy_func( _QUICKEN_RESUME + _CHECK_PERIODIC_IF_NOT_YIELD_FROM; - inst(RESUME_CHECK, (--)) { + macro(RESUME_CHECK) = + unused/1 + + _RESUME_CHECK; + + op(_RESUME_CHECK, (--)) { #if defined(__EMSCRIPTEN__) DEOPT_IF(_Py_emscripten_signal_clock == 0); _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; @@ -241,6 +242,11 @@ dummy_func( #endif } + macro(RESUME_CHECK_JIT) = + unused/1 + + _RESUME_CHECK + + _JIT; + op(_MONITOR_RESUME, (--)) { int err = _Py_call_instrumentation( tstate, oparg == 0 ? PY_MONITORING_EVENT_PY_START : PY_MONITORING_EVENT_PY_RESUME, frame, this_instr); @@ -252,6 +258,7 @@ dummy_func( } macro(INSTRUMENTED_RESUME) = + unused/1 + _LOAD_BYTECODE + _MAYBE_INSTRUMENT + _CHECK_PERIODIC_IF_NOT_YIELD_FROM + @@ -3114,9 +3121,11 @@ dummy_func( tier1 op(_JIT, (--)) { #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; _Py_BackoffCounter counter = this_instr[1].counter; - if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) && - this_instr->op.code == JUMP_BACKWARD_JIT && + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && next_instr->op.code != ENTER_EXECUTOR) { /* Back up over EXTENDED_ARGs so executor is inserted at the correct place */ _Py_CODEUNIT *insert_exec_at = this_instr; @@ -3124,7 +3133,8 @@ dummy_func( oparg >>= 8; insert_exec_at--; } - int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, stack_pointer, 0, NULL, oparg, NULL); + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); if (succ) { ENTER_TRACING(); } @@ -3175,12 +3185,22 @@ dummy_func( tier1 inst(ENTER_EXECUTOR, (--)) { #ifdef _Py_TIER2 - if (IS_JIT_TRACING()) { - next_instr = this_instr; - goto stop_tracing; - } PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; + if (IS_JIT_TRACING()) { + int og_opcode = executor->vm_data.opcode; + int og_oparg = (oparg & ~255) | executor->vm_data.oparg; + next_instr = this_instr; + if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + opcode = og_opcode; + oparg = og_oparg; + DISPATCH_GOTO_NON_TRACING(); + } + goto stop_tracing; + } assert(executor->vm_data.index == INSTR_OFFSET() - 1); assert(executor->vm_data.code == code); assert(executor->vm_data.valid); diff --git a/Python/ceval.c b/Python/ceval.c index 950050a6027..da41851e744 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1095,7 +1095,8 @@ static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = { { .op.code = INTERPRETER_EXIT, .op.arg = 0 }, /* reached on return */ { .op.code = NOP, .op.arg = 0 }, { .op.code = INTERPRETER_EXIT, .op.arg = 0 }, /* reached on yield */ - { .op.code = RESUME, .op.arg = RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START } + { .op.code = RESUME, .op.arg = RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START }, + { .op.code = CACHE, .op.arg = 0 } /* RESUME's CACHE */ }; const _Py_CODEUNIT *_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR = (_Py_CODEUNIT*)&_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS; @@ -1371,7 +1372,7 @@ _PyTier2Interpreter( for (;;) { uopcode = next_uop->opcode; #ifdef Py_DEBUG - if (frame->lltrace >= 3) { + if (frame->lltrace >= 4) { dump_stack(frame, stack_pointer); printf(" cache=["); dump_cache_item(_tos_cache0, 0, current_cached_values); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index f00913cd359..e57bdd686dc 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -93,8 +93,6 @@ break; } - /* _QUICKEN_RESUME is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ - /* _LOAD_BYTECODE is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ case _RESUME_CHECK_r00: { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 30f0101d2ed..a66d6ccff2d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -5691,12 +5691,22 @@ INSTRUCTION_STATS(ENTER_EXECUTOR); opcode = ENTER_EXECUTOR; #ifdef _Py_TIER2 - if (IS_JIT_TRACING()) { - next_instr = this_instr; - JUMP_TO_LABEL(stop_tracing); - } PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; + if (IS_JIT_TRACING()) { + int og_opcode = executor->vm_data.opcode; + int og_oparg = (oparg & ~255) | executor->vm_data.oparg; + next_instr = this_instr; + if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) { + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) { + PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + opcode = og_opcode; + oparg = og_oparg; + DISPATCH_GOTO_NON_TRACING(); + } + JUMP_TO_LABEL(stop_tracing); + } assert(executor->vm_data.index == INSTR_OFFSET() - 1); assert(executor->vm_data.code == code); assert(executor->vm_data.valid); @@ -7436,8 +7446,9 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(INSTRUMENTED_RESUME); + /* Skip 1 cache entry */ // _LOAD_BYTECODE { #ifdef Py_GIL_DISABLED @@ -7785,16 +7796,19 @@ // _JIT { #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; _Py_BackoffCounter counter = this_instr[1].counter; - if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) && - this_instr->op.code == JUMP_BACKWARD_JIT && + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && next_instr->op.code != ENTER_EXECUTOR) { _Py_CODEUNIT *insert_exec_at = this_instr; while (oparg > 255) { oparg >>= 8; insert_exec_at--; } - int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, stack_pointer, 0, NULL, oparg, NULL); + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); if (succ) { ENTER_TRACING(); } @@ -10446,10 +10460,10 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME); PREDICTED_RESUME:; - _Py_CODEUNIT* const this_instr = next_instr - 1; + _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; // _LOAD_BYTECODE { @@ -10496,11 +10510,11 @@ } // _QUICKEN_RESUME { - #if ENABLE_SPECIALIZATION - if (tstate->tracing == 0 && this_instr->op.code == RESUME) { - FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK); - } - #endif /* ENABLE_SPECIALIZATION */ + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_Resume(this_instr, tstate, frame); + stack_pointer = _PyFrame_GetStackPointer(frame); } // _CHECK_PERIODIC_IF_NOT_YIELD_FROM { @@ -10524,9 +10538,10 @@ _Py_CODEUNIT* const this_instr = next_instr; (void)this_instr; frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(RESUME_CHECK); - static_assert(0 == 0, "incorrect cache size"); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ #if defined(__EMSCRIPTEN__) if (_Py_emscripten_signal_clock == 0) { UPDATE_MISS_STATS(RESUME); @@ -10554,6 +10569,76 @@ DISPATCH(); } + TARGET(RESUME_CHECK_JIT) { + #if _Py_TAIL_CALL_INTERP + int opcode = RESUME_CHECK_JIT; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(RESUME_CHECK_JIT); + static_assert(1 == 1, "incorrect cache size"); + /* Skip 1 cache entry */ + // _RESUME_CHECK + { + #if defined(__EMSCRIPTEN__) + if (_Py_emscripten_signal_clock == 0) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; + #endif + uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); + uintptr_t version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); + assert((version & _PY_EVAL_EVENTS_MASK) == 0); + if (eval_breaker != version) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #ifdef Py_GIL_DISABLED + if (frame->tlbc_index != + ((_PyThreadStateImpl *)tstate)->tlbc_index) { + UPDATE_MISS_STATS(RESUME); + assert(_PyOpcode_Deopt[opcode] == (RESUME)); + JUMP_TO_PREDICTED(RESUME); + } + #endif + } + // _JIT + { + #ifdef _Py_TIER2 + bool is_resume = this_instr->op.code == RESUME_CHECK_JIT; + _Py_BackoffCounter counter = this_instr[1].counter; + if ((backoff_counter_triggers(counter) && + !IS_JIT_TRACING() && + (this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) && + next_instr->op.code != ENTER_EXECUTOR) { + _Py_CODEUNIT *insert_exec_at = this_instr; + while (oparg > 255) { + oparg >>= 8; + insert_exec_at--; + } + int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, + is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL); + if (succ) { + ENTER_TRACING(); + } + else { + this_instr[1].counter = restart_backoff_counter(counter); + } + } + else { + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + } + #endif + } + DISPATCH(); + } + TARGET(RETURN_GENERATOR) { #if _Py_TAIL_CALL_INTERP int opcode = RETURN_GENERATOR; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index b074d232778..1aed6769d21 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -576,6 +576,7 @@ sanity_check_instrumentation(PyCodeObject *code) CHECK(opcode != END_FOR); CHECK(opcode != RESUME); CHECK(opcode != RESUME_CHECK); + CHECK(opcode != RESUME_CHECK_JIT); CHECK(opcode != INSTRUMENTED_RESUME); if (!is_instrumented(opcode)) { CHECK(_PyOpcode_Deopt[opcode] == opcode); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index f57c33feec2..def462bacec 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -198,6 +198,7 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_SUPER_ATTR_ATTR, &&TARGET_LOAD_SUPER_ATTR_METHOD, &&TARGET_RESUME_CHECK, + &&TARGET_RESUME_CHECK_JIT, &&TARGET_SEND_GEN, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, @@ -232,7 +233,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, @@ -472,7 +472,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -718,6 +718,7 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RERAISE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESERVED(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RESUME_CHECK_JIT(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_GENERATOR(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_RETURN_VALUE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_SEND(TAIL_CALL_PARAMS); @@ -959,6 +960,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [RESERVED] = _TAIL_CALL_RESERVED, [RESUME] = _TAIL_CALL_RESUME, [RESUME_CHECK] = _TAIL_CALL_RESUME_CHECK, + [RESUME_CHECK_JIT] = _TAIL_CALL_RESUME_CHECK_JIT, [RETURN_GENERATOR] = _TAIL_CALL_RETURN_GENERATOR, [RETURN_VALUE] = _TAIL_CALL_RETURN_VALUE, [SEND] = _TAIL_CALL_SEND, @@ -1007,7 +1009,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, [214] = _TAIL_CALL_UNKNOWN_OPCODE, [215] = _TAIL_CALL_UNKNOWN_OPCODE, [216] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1217,6 +1218,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [RESERVED] = _TAIL_CALL_TRACE_RECORD, [RESUME] = _TAIL_CALL_TRACE_RECORD, [RESUME_CHECK] = _TAIL_CALL_TRACE_RECORD, + [RESUME_CHECK_JIT] = _TAIL_CALL_TRACE_RECORD, [RETURN_GENERATOR] = _TAIL_CALL_TRACE_RECORD, [RETURN_VALUE] = _TAIL_CALL_TRACE_RECORD, [SEND] = _TAIL_CALL_TRACE_RECORD, @@ -1265,7 +1267,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [213] = _TAIL_CALL_UNKNOWN_OPCODE, [214] = _TAIL_CALL_UNKNOWN_OPCODE, [215] = _TAIL_CALL_UNKNOWN_OPCODE, [216] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer.c b/Python/optimizer.c index a9e788d0dcb..f350b82397f 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -632,6 +632,12 @@ _PyJit_translate_single_bytecode_to_trace( target--; } + if (opcode == ENTER_EXECUTOR) { + _PyExecutorObject *executor = old_code->co_executors->executors[oparg & 255]; + opcode = executor->vm_data.opcode; + oparg = (oparg & ~255) | executor->vm_data.oparg; + } + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] > 0) { uint16_t backoff = (this_instr + 1)->counter.value_and_backoff; // adaptive_counter_cooldown is a fresh specialization. @@ -823,6 +829,7 @@ _PyJit_translate_single_bytecode_to_trace( case RESUME: case RESUME_CHECK: + case RESUME_CHECK_JIT: /* Use a special tier 2 version of RESUME_CHECK to allow traces to * start with RESUME_CHECK */ ADD_TO_TRACE(_TIER2_RESUME_CHECK, 0, 0, target); @@ -1038,12 +1045,9 @@ _PyJit_TryInitializeTracing( _Py_RecordFuncPtr record_func = _PyOpcode_RecordFunctions[record_func_index]; record_func(frame, stack_pointer, oparg, &tracer->prev_state.recorded_value); } - assert(curr_instr->op.code == JUMP_BACKWARD_JIT || (exit != NULL)); + assert(curr_instr->op.code == JUMP_BACKWARD_JIT || curr_instr->op.code == RESUME_CHECK_JIT || (exit != NULL)); tracer->initial_state.jump_backward_instr = curr_instr; - if (_PyOpcode_Caches[_PyOpcode_Deopt[close_loop_instr->op.code]]) { - close_loop_instr[1].counter = trigger_backoff_counter(); - } tracer->is_tracing = true; return 1; } @@ -1063,7 +1067,12 @@ _PyJit_FinalizeTracing(PyThreadState *tstate, int err) tracer->initial_state.jump_backward_instr[1].counter = restart_backoff_counter(counter); } else { - tracer->initial_state.jump_backward_instr[1].counter = initial_jump_backoff_counter(&tstate->interp->opt_config); + if (tracer->initial_state.jump_backward_instr[0].op.code == JUMP_BACKWARD_JIT) { + tracer->initial_state.jump_backward_instr[1].counter = initial_jump_backoff_counter(&tstate->interp->opt_config); + } + else { + tracer->initial_state.jump_backward_instr[1].counter = initial_resume_backoff_counter(&tstate->interp->opt_config); + } } } else if (tracer->initial_state.executor->vm_data.valid) { @@ -1092,6 +1101,19 @@ _PyJit_FinalizeTracing(PyThreadState *tstate, int err) tracer->is_tracing = false; } +bool +_PyJit_EnterExecutorShouldStopTracing(int og_opcode) +{ + // Continue tracing (skip over the executor). If it's a RESUME + // trace to form longer, more optimizeable traces. + // We want to trace over RESUME traces. Otherwise, functions with lots of RESUME + // end up with many fragmented traces which perform badly. + // See for example, the richards benchmark in pyperformance. + // For consideration: We may want to consider tracing over side traces + // inserted into bytecode as well in the future. + return og_opcode == RESUME_CHECK_JIT; +} + void _PyJit_TracerFree(_PyThreadStateImpl *_tstate) { @@ -1780,7 +1802,7 @@ _Py_ExecutorDetach(_PyExecutorObject *executor) assert(instruction->op.code == ENTER_EXECUTOR); int index = instruction->op.arg; assert(code->co_executors->executors[index] == executor); - instruction->op.code = executor->vm_data.opcode; + instruction->op.code = _PyOpcode_Deopt[executor->vm_data.opcode]; instruction->op.arg = executor->vm_data.oparg; executor->vm_data.code = NULL; code->co_executors->executors[index] = NULL; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 942a730e4fa..52a0c08ac67 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -17,8 +17,6 @@ break; } - /* _QUICKEN_RESUME is not a viable micro-op for tier 2 */ - /* _LOAD_BYTECODE is not a viable micro-op for tier 2 */ case _RESUME_CHECK: { diff --git a/Python/pystate.c b/Python/pystate.c index fcb73b4dcef..143175da0f4 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -607,11 +607,13 @@ init_interpreter(PyInterpreterState *interp, // Initialize optimization configuration from environment variables // PYTHON_JIT_STRESS sets aggressive defaults for testing, but can be overridden uint16_t jump_default = JUMP_BACKWARD_INITIAL_VALUE; + uint16_t resume_default = RESUME_INITIAL_VALUE; uint16_t side_exit_default = SIDE_EXIT_INITIAL_VALUE; if (is_env_enabled("PYTHON_JIT_STRESS")) { jump_default = 63; side_exit_default = 63; + resume_default = 127; } init_policy(&interp->opt_config.jump_backward_initial_value, @@ -620,6 +622,12 @@ init_interpreter(PyInterpreterState *interp, init_policy(&interp->opt_config.jump_backward_initial_backoff, "PYTHON_JIT_JUMP_BACKWARD_INITIAL_BACKOFF", JUMP_BACKWARD_INITIAL_BACKOFF, 0, MAX_BACKOFF); + init_policy(&interp->opt_config.resume_initial_value, + "PYTHON_JIT_RESUME_INITIAL_VALUE", + resume_default, 1, MAX_VALUE); + init_policy(&interp->opt_config.resume_initial_backoff, + "PYTHON_JIT_RESUME_INITIAL_BACKOFF", + RESUME_INITIAL_BACKOFF, 0, MAX_BACKOFF); init_policy(&interp->opt_config.side_exit_initial_value, "PYTHON_JIT_SIDE_EXIT_INITIAL_VALUE", side_exit_default, 1, MAX_VALUE); diff --git a/Python/specialize.c b/Python/specialize.c index 1eabdb1b5b1..4ef8b277956 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -46,16 +46,18 @@ void _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters) { #if ENABLE_SPECIALIZATION - _Py_BackoffCounter jump_counter, adaptive_counter; + _Py_BackoffCounter jump_counter, adaptive_counter, resume_counter; if (enable_counters) { PyThreadState *tstate = _PyThreadState_GET(); PyInterpreterState *interp = tstate->interp; jump_counter = initial_jump_backoff_counter(&interp->opt_config); adaptive_counter = adaptive_counter_warmup(); + resume_counter = initial_resume_backoff_counter(&interp->opt_config); } else { jump_counter = initial_unreachable_backoff_counter(); adaptive_counter = initial_unreachable_backoff_counter(); + resume_counter = initial_unreachable_backoff_counter(); } int opcode = 0; int oparg = 0; @@ -70,6 +72,9 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters case JUMP_BACKWARD: instructions[i + 1].counter = jump_counter; break; + case RESUME: + instructions[i + 1].counter = resume_counter; + break; case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: case POP_JUMP_IF_NONE: @@ -2781,6 +2786,28 @@ _Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr) return; } + +void +_Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame) +{ + if (tstate->tracing == 0 && instr->op.code == RESUME) { + if (tstate->interp->jit) { + PyCodeObject *co = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable); + if (co != NULL && + PyCode_Check(co) && + (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) { + specialize(instr, RESUME_CHECK_JIT); + set_counter((_Py_BackoffCounter *)instr + 1, initial_resume_backoff_counter(&tstate->interp->opt_config)); + return; + } + } + specialize(instr, RESUME_CHECK); + return; + } + unspecialize(instr); + return; +} + #ifdef Py_STATS void _Py_GatherStats_GetIter(_PyStackRef iterable) @@ -2883,5 +2910,6 @@ const struct _PyCode8 _Py_InitCleanup = { EXIT_INIT_CHECK, 0, RETURN_VALUE, 0, RESUME, RESUME_AT_FUNC_START, + CACHE, 0, /* RESUME's cache */ } }; From ae1b3074330b8eefada470fd921b05664e6646f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 19:07:07 +0100 Subject: [PATCH 162/775] build(deps): bump hypothesis from 6.135.26 to 6.151.9 in /Tools (#145948) Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.135.26 to 6.151.9. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.135.26...hypothesis-python-6.151.9) --- updated-dependencies: - dependency-name: hypothesis dependency-version: 6.151.9 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Tools/requirements-hypothesis.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/requirements-hypothesis.txt b/Tools/requirements-hypothesis.txt index e5deac497fb..8ecf796ec73 100644 --- a/Tools/requirements-hypothesis.txt +++ b/Tools/requirements-hypothesis.txt @@ -1,4 +1,4 @@ # Requirements file for hypothesis that # we use to run our property-based tests in CI. -hypothesis==6.135.26 +hypothesis==6.151.9 From 2a0fa500f82fc160feb726c0631f58c9a2f76796 Mon Sep 17 00:00:00 2001 From: wavebyrd <160968744+wavebyrd@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:25:31 -0400 Subject: [PATCH 163/775] gh-145870: Fix Format.SOURCE reference in get_annotations docstring (#145889) The get_annotations() docstring incorrectly referred to the SOURCE format, which was renamed to STRING during PEP 749 development. Co-authored-by: Carson Jones --- Lib/annotationlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/annotationlib.py b/Lib/annotationlib.py index 832d160de7f..df8fb5e4c62 100644 --- a/Lib/annotationlib.py +++ b/Lib/annotationlib.py @@ -919,7 +919,7 @@ def get_annotations( does not exist, the __annotate__ function is called. The FORWARDREF format uses __annotations__ if it exists and can be evaluated, and otherwise falls back to calling the __annotate__ function. - The SOURCE format tries __annotate__ first, and falls back to + The STRING format tries __annotate__ first, and falls back to using __annotations__, stringified using annotations_to_string(). This function handles several details for you: From 4e96282ee42ab51cf325b52a0173ddddbe66c05c Mon Sep 17 00:00:00 2001 From: trag1c Date: Mon, 16 Mar 2026 20:55:29 +0100 Subject: [PATCH 164/775] Docs: remove unmatched parenthesis for `asyncio.TaskGroup` note (#146035) --- Doc/library/asyncio-task.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 1b7c8ff0c76..e2a6752be12 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -557,7 +557,7 @@ Running Tasks Concurrently provides stronger safety guarantees than *gather* for scheduling a nesting of subtasks: if a task (or a subtask, a task scheduled by a task) raises an exception, *TaskGroup* will, while *gather* will not, - cancel the remaining scheduled tasks). + cancel the remaining scheduled tasks. .. _asyncio_example_gather: From 104cae039ac428709c7bcf9b1a00102f97be0a5c Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 17 Mar 2026 00:01:41 +0100 Subject: [PATCH 165/775] gh-142927: Move hotspots up flamegraph sidebar (#145428) --- .../flamegraph_template.html | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html index 07b15a5a2b4..c0d40b2712b 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph_template.html @@ -178,6 +178,51 @@

Profile Summary

+ + + - - - - - + + + diff --git a/Lib/profiling/sampling/cli.py b/Lib/profiling/sampling/cli.py index f4b31aad45b..e22ab158d6a 100644 --- a/Lib/profiling/sampling/cli.py +++ b/Lib/profiling/sampling/cli.py @@ -16,7 +16,7 @@ from .errors import SamplingUnknownProcessError, SamplingModuleNotFoundError, SamplingScriptNotFoundError from .sample import sample, sample_live, _is_process_running from .pstats_collector import PstatsCollector -from .stack_collector import CollapsedStackCollector, FlamegraphCollector +from .stack_collector import CollapsedStackCollector, FlamegraphCollector, DiffFlamegraphCollector from .heatmap_collector import HeatmapCollector from .gecko_collector import GeckoCollector from .binary_collector import BinaryCollector @@ -56,6 +56,13 @@ class CustomFormatter( pass +class DiffFlamegraphAction(argparse.Action): + """Custom action for --diff-flamegraph that sets both format and baseline path.""" + def __call__(self, parser, namespace, values, option_string=None): + namespace.format = 'diff_flamegraph' + namespace.diff_baseline = values + + _HELP_DESCRIPTION = """Sample a process's stack frames and generate profiling data. Examples: @@ -85,6 +92,7 @@ class CustomFormatter( "pstats": "pstats", "collapsed": "txt", "flamegraph": "html", + "diff_flamegraph": "html", "gecko": "json", "heatmap": "html", "binary": "bin", @@ -94,6 +102,7 @@ class CustomFormatter( "pstats": PstatsCollector, "collapsed": CollapsedStackCollector, "flamegraph": FlamegraphCollector, + "diff_flamegraph": DiffFlamegraphCollector, "gecko": GeckoCollector, "heatmap": HeatmapCollector, "binary": BinaryCollector, @@ -467,6 +476,12 @@ def _add_format_options(parser, include_compression=True, include_binary=True): dest="format", help="Generate interactive HTML heatmap visualization with line-level sample counts", ) + format_group.add_argument( + "--diff-flamegraph", + metavar="BASELINE", + action=DiffFlamegraphAction, + help="Generate differential flamegraph comparing current profile to BASELINE binary file", + ) if include_binary: format_group.add_argument( "--binary", @@ -475,7 +490,7 @@ def _add_format_options(parser, include_compression=True, include_binary=True): dest="format", help="Generate high-performance binary format (use 'replay' command to convert)", ) - parser.set_defaults(format="pstats") + parser.set_defaults(format="pstats", diff_baseline=None) if include_compression: output_group.add_argument( @@ -545,17 +560,18 @@ def _sort_to_mode(sort_choice): return sort_map.get(sort_choice, SORT_MODE_NSAMPLES) def _create_collector(format_type, sample_interval_usec, skip_idle, opcodes=False, - output_file=None, compression='auto'): + output_file=None, compression='auto', diff_baseline=None): """Create the appropriate collector based on format type. Args: - format_type: The output format ('pstats', 'collapsed', 'flamegraph', 'gecko', 'heatmap', 'binary') + format_type: The output format ('pstats', 'collapsed', 'flamegraph', 'gecko', 'heatmap', 'binary', 'diff_flamegraph') sample_interval_usec: Sampling interval in microseconds skip_idle: Whether to skip idle samples opcodes: Whether to collect opcode information (only used by gecko format for creating interval markers in Firefox Profiler) output_file: Output file path (required for binary format) compression: Compression type for binary format ('auto', 'zstd', 'none') + diff_baseline: Path to baseline binary file for differential flamegraph Returns: A collector instance of the appropriate type @@ -564,6 +580,17 @@ def _create_collector(format_type, sample_interval_usec, skip_idle, opcodes=Fals if collector_class is None: raise ValueError(f"Unknown format: {format_type}") + if format_type == "diff_flamegraph": + if diff_baseline is None: + raise ValueError("Differential flamegraph requires a baseline file") + if not os.path.exists(diff_baseline): + raise ValueError(f"Baseline file not found: {diff_baseline}") + return collector_class( + sample_interval_usec, + baseline_binary_path=diff_baseline, + skip_idle=skip_idle + ) + # Binary format requires output file and compression if format_type == "binary": if output_file is None: @@ -663,7 +690,7 @@ def _handle_output(collector, args, pid, mode): collector.export(filename) # Auto-open browser for HTML output if --browser flag is set - if args.format in ('flamegraph', 'heatmap') and getattr(args, 'browser', False): + if args.format in ('flamegraph', 'diff_flamegraph', 'heatmap') and getattr(args, 'browser', False): _open_in_browser(filename) @@ -756,7 +783,7 @@ def _validate_args(args, parser): ) # Validate --opcodes is only used with compatible formats - opcodes_compatible_formats = ("live", "gecko", "flamegraph", "heatmap", "binary") + opcodes_compatible_formats = ("live", "gecko", "flamegraph", "diff_flamegraph", "heatmap", "binary") if getattr(args, 'opcodes', False) and args.format not in opcodes_compatible_formats: parser.error( f"--opcodes is only compatible with {', '.join('--' + f for f in opcodes_compatible_formats)}." @@ -953,7 +980,8 @@ def _handle_attach(args): collector = _create_collector( args.format, args.sample_interval_usec, skip_idle, args.opcodes, output_file=output_file, - compression=getattr(args, 'compression', 'auto') + compression=getattr(args, 'compression', 'auto'), + diff_baseline=args.diff_baseline ) with _get_child_monitor_context(args, args.pid): @@ -1031,7 +1059,8 @@ def _handle_run(args): collector = _create_collector( args.format, args.sample_interval_usec, skip_idle, args.opcodes, output_file=output_file, - compression=getattr(args, 'compression', 'auto') + compression=getattr(args, 'compression', 'auto'), + diff_baseline=args.diff_baseline ) with _get_child_monitor_context(args, process.pid): @@ -1180,7 +1209,10 @@ def _handle_replay(args): print(f" Sample interval: {interval} us") print(f" Compression: {'zstd' if info.get('compression_type', 0) == 1 else 'none'}") - collector = _create_collector(args.format, interval, skip_idle=False) + collector = _create_collector( + args.format, interval, skip_idle=False, + diff_baseline=args.diff_baseline + ) def progress_callback(current, total): if total > 0: @@ -1206,7 +1238,7 @@ def progress_callback(current, total): collector.export(filename) # Auto-open browser for HTML output if --browser flag is set - if args.format in ('flamegraph', 'heatmap') and getattr(args, 'browser', False): + if args.format in ('flamegraph', 'diff_flamegraph', 'heatmap') and getattr(args, 'browser', False): _open_in_browser(filename) print(f"Replayed {count} samples") diff --git a/Lib/profiling/sampling/stack_collector.py b/Lib/profiling/sampling/stack_collector.py index 931bc2c487b..05ebe4d9764 100644 --- a/Lib/profiling/sampling/stack_collector.py +++ b/Lib/profiling/sampling/stack_collector.py @@ -333,7 +333,7 @@ def process_frames(self, frames, thread_id, weight=1): node = current["children"].get(func) if node is None: - node = {"samples": 0, "children": {}, "threads": set(), "opcodes": collections.Counter()} + node = {"samples": 0, "children": {}, "threads": set(), "opcodes": collections.Counter(), "self": 0} current["children"][func] = node node["samples"] += weight node["threads"].add(thread_id) @@ -343,6 +343,9 @@ def process_frames(self, frames, thread_id, weight=1): current = node + if current is not self._root: + current["self"] += weight + def _get_source_lines(self, func): filename, lineno, _ = func @@ -381,6 +384,18 @@ def _create_flamegraph_html(self, data): component_js = (template_dir / "_flamegraph_assets" / "flamegraph.js").read_text(encoding="utf-8") js_content = f"{base_js}\n{component_js}" + # Set title and subtitle based on whether this is a differential flamegraph + is_differential = data.get("stats", {}).get("is_differential", False) + if is_differential: + title = "Tachyon Profiler - Differential Flamegraph Report" + subtitle = "Differential Flamegraph Report" + else: + title = "Tachyon Profiler - Flamegraph Report" + subtitle = "Flamegraph Report" + + html_template = html_template.replace("{{TITLE}}", title) + html_template = html_template.replace("{{SUBTITLE}}", subtitle) + # Inline first-party CSS/JS html_template = html_template.replace( "", f"" @@ -427,3 +442,266 @@ def _create_flamegraph_html(self, data): ) return html_content + + +class DiffFlamegraphCollector(FlamegraphCollector): + """Differential flamegraph collector that compares against a baseline binary profile.""" + + def __init__(self, sample_interval_usec, *, baseline_binary_path, skip_idle=False): + super().__init__(sample_interval_usec, skip_idle=skip_idle) + if not os.path.exists(baseline_binary_path): + raise ValueError(f"Baseline file not found: {baseline_binary_path}") + self.baseline_binary_path = baseline_binary_path + self._baseline_collector = None + self._elided_paths = set() + + def _load_baseline(self): + """Load baseline profile from binary file.""" + from .binary_reader import BinaryReader + + with BinaryReader(self.baseline_binary_path) as reader: + info = reader.get_info() + + baseline_collector = FlamegraphCollector( + sample_interval_usec=info['sample_interval_us'], + skip_idle=self.skip_idle + ) + + reader.replay_samples(baseline_collector) + + self._baseline_collector = baseline_collector + + def _aggregate_path_samples(self, root_node, path=None): + """Aggregate samples by stack path, excluding line numbers for cross-profile matching.""" + if path is None: + path = () + + stats = {} + + for func, node in root_node["children"].items(): + filename, _lineno, funcname = func + func_key = (filename, funcname) + path_key = path + (func_key,) + + total_samples = node.get("samples", 0) + self_samples = node.get("self", 0) + + if path_key in stats: + stats[path_key]["total"] += total_samples + stats[path_key]["self"] += self_samples + else: + stats[path_key] = { + "total": total_samples, + "self": self_samples + } + + child_stats = self._aggregate_path_samples(node, path_key) + for key, data in child_stats.items(): + if key in stats: + stats[key]["total"] += data["total"] + stats[key]["self"] += data["self"] + else: + stats[key] = data + + return stats + + def _convert_to_flamegraph_format(self): + """Convert to flamegraph format with differential annotations.""" + if self._baseline_collector is None: + self._load_baseline() + + current_flamegraph = super()._convert_to_flamegraph_format() + + current_stats = self._aggregate_path_samples(self._root) + baseline_stats = self._aggregate_path_samples(self._baseline_collector._root) + + # Scale baseline values to make them comparable, accounting for both + # sample count differences and sample interval differences. + baseline_total = self._baseline_collector._total_samples + if baseline_total > 0 and self._total_samples > 0: + current_time = self._total_samples * self.sample_interval_usec + baseline_time = baseline_total * self._baseline_collector.sample_interval_usec + scale = current_time / baseline_time + elif baseline_total > 0: + # Current profile is empty - use interval-based scale for elided display + scale = self.sample_interval_usec / self._baseline_collector.sample_interval_usec + else: + scale = 1.0 + + self._annotate_nodes_with_diff(current_flamegraph, current_stats, baseline_stats, scale) + self._add_elided_flamegraph(current_flamegraph, current_stats, baseline_stats, scale) + + return current_flamegraph + + def _annotate_nodes_with_diff(self, current_flamegraph, current_stats, baseline_stats, scale): + """Annotate each node in the tree with diff metadata.""" + if "stats" not in current_flamegraph: + current_flamegraph["stats"] = {} + + current_flamegraph["stats"]["baseline_samples"] = self._baseline_collector._total_samples + current_flamegraph["stats"]["current_samples"] = self._total_samples + current_flamegraph["stats"]["baseline_scale"] = scale + current_flamegraph["stats"]["is_differential"] = True + + if self._is_promoted_root(current_flamegraph): + self._add_diff_data_to_node(current_flamegraph, (), current_stats, baseline_stats, scale) + else: + for child in current_flamegraph["children"]: + self._add_diff_data_to_node(child, (), current_stats, baseline_stats, scale) + + def _add_diff_data_to_node(self, node, path, current_stats, baseline_stats, scale): + """Recursively add diff metadata to nodes.""" + func_key = self._extract_func_key(node, self._string_table) + path_key = path + (func_key,) if func_key else path + + current_data = current_stats.get(path_key, {"total": 0, "self": 0}) + baseline_data = baseline_stats.get(path_key, {"total": 0, "self": 0}) + + current_self = current_data["self"] + baseline_self = baseline_data["self"] * scale + baseline_total = baseline_data["total"] * scale + + diff = current_self - baseline_self + if baseline_self > 0: + diff_pct = (diff / baseline_self) * 100.0 + elif current_self > 0: + diff_pct = 100.0 + else: + diff_pct = 0.0 + + node["baseline"] = baseline_self + node["baseline_total"] = baseline_total + node["self_time"] = current_self + node["diff"] = diff + node["diff_pct"] = diff_pct + + if "children" in node and node["children"]: + for child in node["children"]: + self._add_diff_data_to_node(child, path_key, current_stats, baseline_stats, scale) + + def _is_promoted_root(self, data): + """Check if the data represents a promoted root node.""" + return "filename" in data and "funcname" in data + + def _add_elided_flamegraph(self, current_flamegraph, current_stats, baseline_stats, scale): + """Calculate elided paths and add elided flamegraph to stats.""" + self._elided_paths = baseline_stats.keys() - current_stats.keys() + + current_flamegraph["stats"]["elided_count"] = len(self._elided_paths) + + if self._elided_paths: + elided_flamegraph = self._build_elided_flamegraph(baseline_stats, scale) + if elided_flamegraph: + current_flamegraph["stats"]["elided_flamegraph"] = elided_flamegraph + + def _build_elided_flamegraph(self, baseline_stats, scale): + """Build flamegraph containing only elided paths from baseline. + + This re-runs the base conversion pipeline on the baseline collector + to produce a complete formatted flamegraph, then prunes it to keep + only elided paths. + """ + if not self._baseline_collector or not self._elided_paths: + return None + + # Suppress source line collection for elided nodes - these functions + # no longer exist in the current profile, so source lines from the + # current machine's filesystem would be misleading or unavailable. + orig_get_source = self._baseline_collector._get_source_lines + self._baseline_collector._get_source_lines = lambda func: None + try: + baseline_data = self._baseline_collector._convert_to_flamegraph_format() + finally: + self._baseline_collector._get_source_lines = orig_get_source + + # Remove non-elided nodes and recalculate values + if not self._extract_elided_nodes(baseline_data, path=()): + return None + + self._add_elided_metadata(baseline_data, baseline_stats, scale, path=()) + + # Merge only profiling metadata, not thread-level stats + for key in ("sample_interval_usec", "duration_sec", "sample_rate", + "error_rate", "missed_samples", "mode"): + if key in self.stats: + baseline_data["stats"][key] = self.stats[key] + baseline_data["stats"]["is_differential"] = True + baseline_data["stats"]["baseline_samples"] = self._baseline_collector._total_samples + baseline_data["stats"]["current_samples"] = self._total_samples + + return baseline_data + + def _extract_elided_nodes(self, node, path): + """Remove non-elided nodes and recalculate values bottom-up.""" + if not node: + return False + + func_key = self._extract_func_key(node, self._baseline_collector._string_table) + current_path = path + (func_key,) if func_key else path + + is_elided = current_path in self._elided_paths if func_key else False + + if "children" in node: + # Filter children, keeping only those with elided descendants + elided_children = [] + total_value = 0 + for child in node["children"]: + if self._extract_elided_nodes(child, current_path): + elided_children.append(child) + total_value += child.get("value", 0) + node["children"] = elided_children + + # Recalculate value for structural (non-elided) ancestor nodes; + # elided nodes keep their original value to preserve self-samples + if elided_children and not is_elided: + node["value"] = total_value + + # Keep this node if it's elided or has elided descendants + return is_elided or bool(node.get("children")) + + def _add_elided_metadata(self, node, baseline_stats, scale, path): + """Add differential metadata showing this path disappeared.""" + if not node: + return + + func_key = self._extract_func_key(node, self._baseline_collector._string_table) + current_path = path + (func_key,) if func_key else path + + if func_key and current_path in baseline_stats: + baseline_data = baseline_stats[current_path] + baseline_self = baseline_data["self"] * scale + baseline_total = baseline_data["total"] * scale + + node["baseline"] = baseline_self + node["baseline_total"] = baseline_total + node["diff"] = -baseline_self + else: + node["baseline"] = 0 + node["baseline_total"] = 0 + node["diff"] = 0 + + node["self_time"] = 0 + # Elided paths have zero current self-time, so the change is always + # -100% when there was actual baseline self-time to lose. + # For internal nodes with no baseline self-time, use 0% to avoid + # misleading tooltips. + if baseline_self > 0: + node["diff_pct"] = -100.0 + else: + node["diff_pct"] = 0.0 + + if "children" in node and node["children"]: + for child in node["children"]: + self._add_elided_metadata(child, baseline_stats, scale, current_path) + + def _extract_func_key(self, node, string_table): + """Extract (filename, funcname) key from node, excluding line numbers. + + Line numbers are excluded to match functions even if they moved. + Returns None for root nodes that don't have function information. + """ + if "filename" not in node or "funcname" not in node: + return None + filename = string_table.get_string(node["filename"]) + funcname = string_table.get_string(node["funcname"]) + return (filename, funcname) diff --git a/Lib/test/test_profiling/test_sampling_profiler/mocks.py b/Lib/test/test_profiling/test_sampling_profiler/mocks.py index 4e0f7a87c6d..6ac2d08e898 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/mocks.py +++ b/Lib/test/test_profiling/test_sampling_profiler/mocks.py @@ -91,3 +91,22 @@ def __init__(self, thread_id, awaited_by): def __repr__(self): return f"MockAwaitedInfo(thread_id={self.thread_id}, awaited_by={len(self.awaited_by)} tasks)" + + +def make_diff_collector_with_mock_baseline(baseline_samples): + """Create a DiffFlamegraphCollector with baseline injected directly, + skipping the binary round-trip that _load_baseline normally does.""" + from profiling.sampling.stack_collector import ( + DiffFlamegraphCollector, + FlamegraphCollector, + ) + + baseline = FlamegraphCollector(1000) + for sample in baseline_samples: + baseline.collect(sample) + + # Path is unused since we inject _baseline_collector directly; + # use __file__ as a dummy path that passes the existence check. + diff = DiffFlamegraphCollector(1000, baseline_binary_path=__file__) + diff._baseline_collector = baseline + return diff diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py index 06c9e51e0c9..86fb9d4c05b 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py @@ -37,10 +37,26 @@ from test.support import captured_stdout, captured_stderr -from .mocks import MockFrameInfo, MockThreadInfo, MockInterpreterInfo, LocationInfo +from .mocks import MockFrameInfo, MockThreadInfo, MockInterpreterInfo, LocationInfo, make_diff_collector_with_mock_baseline from .helpers import close_and_unlink +def resolve_name(node, strings): + """Resolve a flamegraph node's name from the string table.""" + idx = node.get("name", 0) + if isinstance(idx, int) and 0 <= idx < len(strings): + return strings[idx] + return str(idx) + + +def find_child_by_name(children, strings, substr): + """Find a child node whose resolved name contains substr.""" + for child in children: + if substr in resolve_name(child, strings): + return child + return None + + class TestSampleProfilerComponents(unittest.TestCase): """Unit tests for individual profiler components.""" @@ -398,13 +414,7 @@ def test_flamegraph_collector_basic(self): data = collector._convert_to_flamegraph_format() # With string table, name is now an index - resolve it using the strings array strings = data.get("strings", []) - name_index = data.get("name", 0) - resolved_name = ( - strings[name_index] - if isinstance(name_index, int) and 0 <= name_index < len(strings) - else str(name_index) - ) - self.assertIn(resolved_name, ("No Data", "No significant data")) + self.assertIn(resolve_name(data, strings), ("No Data", "No significant data")) # Test collecting sample data test_frames = [ @@ -423,26 +433,13 @@ def test_flamegraph_collector_basic(self): data = collector._convert_to_flamegraph_format() # Expect promotion: root is the single child (func2), with func1 as its only child strings = data.get("strings", []) - name_index = data.get("name", 0) - name = ( - strings[name_index] - if isinstance(name_index, int) and 0 <= name_index < len(strings) - else str(name_index) - ) - self.assertIsInstance(name, str) + name = resolve_name(data, strings) self.assertTrue(name.startswith("Program Root: ")) self.assertIn("func2 (file.py:20)", name) # formatted name children = data.get("children", []) self.assertEqual(len(children), 1) child = children[0] - child_name_index = child.get("name", 0) - child_name = ( - strings[child_name_index] - if isinstance(child_name_index, int) - and 0 <= child_name_index < len(strings) - else str(child_name_index) - ) - self.assertIn("func1 (file.py:10)", child_name) # formatted name + self.assertIn("func1 (file.py:10)", resolve_name(child, strings)) self.assertEqual(child["value"], 1) def test_flamegraph_collector_export(self): @@ -1211,6 +1208,463 @@ def test_flamegraph_collector_per_thread_gc_percentage(self): self.assertEqual(collector.per_thread_stats[2]["total"], 6) self.assertAlmostEqual(per_thread_stats[2]["gc_pct"], 10.0, places=1) + def test_diff_flamegraph_identical_profiles(self): + """When baseline and current are identical, diff should be ~0.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames] * 3) + for _ in range(3): + diff.collect(test_frames) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertEqual(data["stats"]["baseline_samples"], 3) + self.assertEqual(data["stats"]["current_samples"], 3) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 1.0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertEqual(child["self_time"], 3) + self.assertAlmostEqual(child["baseline"], 3.0) + self.assertAlmostEqual(child["diff"], 0.0, places=1) + self.assertAlmostEqual(child["diff_pct"], 0.0, places=1) + + self.assertEqual(data["stats"]["elided_count"], 0) + self.assertNotIn("elided_flamegraph", data["stats"]) + + def test_diff_flamegraph_new_function(self): + """A function only in current should have diff_pct=100 and baseline=0.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "new_func"), + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + func1_node = children[0] + self.assertIn("func1", resolve_name(func1_node, strings)) + + func1_children = func1_node.get("children", []) + self.assertEqual(len(func1_children), 1) + new_func_node = func1_children[0] + self.assertIn("new_func", resolve_name(new_func_node, strings)) + self.assertEqual(new_func_node["baseline"], 0) + self.assertGreater(new_func_node["self_time"], 0) + self.assertEqual(new_func_node["diff"], new_func_node["self_time"]) + self.assertAlmostEqual(new_func_node["diff_pct"], 100.0) + + def test_diff_flamegraph_changed_functions(self): + """Functions with different sample counts should have correct diff and diff_pct.""" + hot_leaf_sample = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "hot_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ]) + ]) + ] + cold_leaf_sample = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "cold_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ]) + ]) + ] + + # Baseline: 2 samples, current: 4, scale = 2.0 + diff = make_diff_collector_with_mock_baseline( + [hot_leaf_sample, cold_leaf_sample] + ) + for _ in range(3): + diff.collect(hot_leaf_sample) + diff.collect(cold_leaf_sample) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 2.0) + + children = data.get("children", []) + hot_node = find_child_by_name(children, strings, "hot_leaf") + cold_node = find_child_by_name(children, strings, "cold_leaf") + self.assertIsNotNone(hot_node) + self.assertIsNotNone(cold_node) + + # hot_leaf regressed (+50%) + self.assertAlmostEqual(hot_node["baseline"], 2.0) + self.assertEqual(hot_node["self_time"], 3) + self.assertAlmostEqual(hot_node["diff"], 1.0) + self.assertAlmostEqual(hot_node["diff_pct"], 50.0) + + # cold_leaf improved (-50%) + self.assertAlmostEqual(cold_node["baseline"], 2.0) + self.assertEqual(cold_node["self_time"], 1) + self.assertAlmostEqual(cold_node["diff"], -1.0) + self.assertAlmostEqual(cold_node["diff_pct"], -50.0) + + def test_diff_flamegraph_scale_factor(self): + """Scale factor adjusts when sample counts differ.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + for _ in range(4): + diff.collect(baseline_frames) + + data = diff._convert_to_flamegraph_format() + self.assertAlmostEqual(data["stats"]["baseline_scale"], 4.0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + func1_node = children[0] + self.assertEqual(func1_node["self_time"], 4) + self.assertAlmostEqual(func1_node["baseline"], 4.0) + self.assertAlmostEqual(func1_node["diff"], 0.0) + self.assertAlmostEqual(func1_node["diff_pct"], 0.0) + + def test_diff_flamegraph_elided_stacks(self): + """Paths in baseline but not current produce elided stacks.""" + baseline_frames_1 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + baseline_frames_2 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "old_func"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames_1, baseline_frames_2]) + for _ in range(2): + diff.collect(baseline_frames_1) + + data = diff._convert_to_flamegraph_format() + + self.assertGreater(data["stats"]["elided_count"], 0) + self.assertIn("elided_flamegraph", data["stats"]) + elided = data["stats"]["elided_flamegraph"] + self.assertTrue(elided["stats"]["is_differential"]) + self.assertIn("strings", elided) + + elided_strings = elided.get("strings", []) + children = elided.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("old_func", resolve_name(child, elided_strings)) + self.assertEqual(child["self_time"], 0) + self.assertAlmostEqual(child["diff_pct"], -100.0) + self.assertGreater(child["baseline"], 0) + self.assertAlmostEqual(child["diff"], -child["baseline"]) + + def test_diff_flamegraph_function_matched_despite_line_change(self): + """Functions match by (filename, funcname), ignoring lineno.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + # Same functions but different line numbers + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 99, "func1"), + MockFrameInfo("file.py", 55, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertGreater(child["baseline"], 0) + self.assertGreater(child["self_time"], 0) + self.assertAlmostEqual(child["diff"], 0.0, places=1) + self.assertAlmostEqual(child["diff_pct"], 0.0, places=1) + + def test_diff_flamegraph_empty_current(self): + """Empty current profile still produces differential metadata and elided paths.""" + baseline_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [MockFrameInfo("file.py", 10, "func1")]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames]) + # Don't collect anything in current + + data = diff._convert_to_flamegraph_format() + self.assertIn("name", data) + self.assertEqual(data["value"], 0) + # Differential metadata should still be populated + self.assertTrue(data["stats"]["is_differential"]) + # All baseline paths should be elided since current is empty + self.assertGreater(data["stats"]["elided_count"], 0) + + def test_diff_flamegraph_empty_baseline(self): + """Empty baseline with non-empty current uses scale=1.0 fallback.""" + diff = make_diff_collector_with_mock_baseline([]) + diff.collect([ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ]) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertEqual(data["stats"]["baseline_samples"], 0) + self.assertEqual(data["stats"]["current_samples"], 1) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 1.0) + self.assertEqual(data["stats"]["elided_count"], 0) + + children = data.get("children", []) + self.assertEqual(len(children), 1) + child = children[0] + self.assertIn("func1", resolve_name(child, strings)) + self.assertEqual(child["self_time"], 1) + self.assertAlmostEqual(child["baseline"], 0.0) + self.assertAlmostEqual(child["diff"], 1.0) + self.assertAlmostEqual(child["diff_pct"], 100.0) + + def test_diff_flamegraph_export(self): + """DiffFlamegraphCollector export produces differential HTML.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1"), + MockFrameInfo("file.py", 20, "func2"), + ]) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames]) + diff.collect(test_frames) + + flamegraph_out = tempfile.NamedTemporaryFile( + suffix=".html", delete=False + ) + self.addCleanup(close_and_unlink, flamegraph_out) + + with captured_stdout(), captured_stderr(): + diff.export(flamegraph_out.name) + + self.assertTrue(os.path.exists(flamegraph_out.name)) + self.assertGreater(os.path.getsize(flamegraph_out.name), 0) + + with open(flamegraph_out.name, "r", encoding="utf-8") as f: + content = f.read() + + self.assertIn("", content.lower()) + self.assertIn("Differential Flamegraph", content) + self.assertIn('"is_differential": true', content) + self.assertIn("d3-flame-graph", content) + self.assertIn('id="diff-legend-section"', content) + self.assertIn("Differential Colors", content) + + def test_diff_flamegraph_preserves_metadata(self): + """Differential mode preserves threads and opcodes metadata.""" + test_frames = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [MockFrameInfo("a.py", 10, "func_a", opcode=100)]), + MockThreadInfo(2, [MockFrameInfo("b.py", 20, "func_b", opcode=200)]), + ]) + ] + + diff = make_diff_collector_with_mock_baseline([test_frames]) + diff.collect(test_frames) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + + self.assertIn("threads", data) + self.assertEqual(len(data["threads"]), 2) + + children = data.get("children", []) + self.assertEqual(len(children), 2) + + opcodes_found = set() + for child in children: + self.assertIn("diff", child) + self.assertIn("diff_pct", child) + self.assertIn("baseline", child) + self.assertIn("self_time", child) + self.assertIn("threads", child) + + if "opcodes" in child: + opcodes_found.update(child["opcodes"].keys()) + + self.assertIn(100, opcodes_found) + self.assertIn(200, opcodes_found) + + self.assertIn("per_thread_stats", data["stats"]) + per_thread_stats = data["stats"]["per_thread_stats"] + self.assertIn(1, per_thread_stats) + self.assertIn(2, per_thread_stats) + + def test_diff_flamegraph_elided_preserves_metadata(self): + """Elided flamegraph preserves thread_stats, per_thread_stats, and opcodes.""" + baseline_frames_1 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "func1", opcode=100), + MockFrameInfo("file.py", 20, "func2", opcode=101), + ], status=THREAD_STATUS_HAS_GIL) + ]) + ] + baseline_frames_2 = [ + MockInterpreterInfo(0, [ + MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "old_func", opcode=200), + MockFrameInfo("file.py", 20, "func2", opcode=101), + ], status=THREAD_STATUS_HAS_GIL) + ]) + ] + + diff = make_diff_collector_with_mock_baseline([baseline_frames_1, baseline_frames_2]) + for _ in range(2): + diff.collect(baseline_frames_1) + + data = diff._convert_to_flamegraph_format() + elided = data["stats"]["elided_flamegraph"] + + self.assertTrue(elided["stats"]["is_differential"]) + self.assertIn("thread_stats", elided["stats"]) + self.assertIn("per_thread_stats", elided["stats"]) + self.assertIn("baseline_samples", elided["stats"]) + self.assertIn("current_samples", elided["stats"]) + self.assertIn("strings", elided) + + elided_strings = elided.get("strings", []) + children = elided.get("children", []) + self.assertEqual(len(children), 1) + old_func_node = children[0] + if "opcodes" in old_func_node: + self.assertIn(200, old_func_node["opcodes"]) + self.assertEqual(old_func_node["self_time"], 0) + self.assertAlmostEqual(old_func_node["diff_pct"], -100.0) + + def test_diff_flamegraph_load_baseline(self): + """Diff annotations work when baseline is loaded from a binary file.""" + from profiling.sampling.binary_collector import BinaryCollector + from profiling.sampling.stack_collector import DiffFlamegraphCollector + from .test_binary_format import make_frame, make_thread, make_interpreter + + hot_sample = [make_interpreter(0, [make_thread(1, [ + make_frame("file.py", 10, "hot_leaf"), + make_frame("file.py", 20, "caller"), + ])])] + cold_sample = [make_interpreter(0, [make_thread(1, [ + make_frame("file.py", 30, "cold_leaf"), + make_frame("file.py", 20, "caller"), + ])])] + + # Baseline: 2 samples, current: 4, scale = 2.0 + bin_file = tempfile.NamedTemporaryFile(suffix=".bin", delete=False) + self.addCleanup(close_and_unlink, bin_file) + + writer = BinaryCollector( + bin_file.name, sample_interval_usec=1000, compression='none' + ) + writer.collect(hot_sample) + writer.collect(cold_sample) + writer.export(None) + + diff = DiffFlamegraphCollector( + 1000, baseline_binary_path=bin_file.name + ) + hot_mock = [MockInterpreterInfo(0, [MockThreadInfo(1, [ + MockFrameInfo("file.py", 10, "hot_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ])])] + cold_mock = [MockInterpreterInfo(0, [MockThreadInfo(1, [ + MockFrameInfo("file.py", 30, "cold_leaf"), + MockFrameInfo("file.py", 20, "caller"), + ])])] + for _ in range(3): + diff.collect(hot_mock) + diff.collect(cold_mock) + + data = diff._convert_to_flamegraph_format() + strings = data.get("strings", []) + + self.assertTrue(data["stats"]["is_differential"]) + self.assertAlmostEqual(data["stats"]["baseline_scale"], 2.0) + + children = data.get("children", []) + hot_node = find_child_by_name(children, strings, "hot_leaf") + cold_node = find_child_by_name(children, strings, "cold_leaf") + self.assertIsNotNone(hot_node) + self.assertIsNotNone(cold_node) + + # hot_leaf regressed (+50%) + self.assertAlmostEqual(hot_node["baseline"], 2.0) + self.assertEqual(hot_node["self_time"], 3) + self.assertAlmostEqual(hot_node["diff"], 1.0) + self.assertAlmostEqual(hot_node["diff_pct"], 50.0) + + # cold_leaf improved (-50%) + self.assertAlmostEqual(cold_node["baseline"], 2.0) + self.assertEqual(cold_node["self_time"], 1) + self.assertAlmostEqual(cold_node["diff"], -1.0) + self.assertAlmostEqual(cold_node["diff_pct"], -50.0) + class TestRecursiveFunctionHandling(unittest.TestCase): """Tests for correct handling of recursive functions in cumulative stats.""" diff --git a/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst b/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst new file mode 100644 index 00000000000..2059557e8bb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst @@ -0,0 +1,4 @@ +The ``profiling.sampling`` module now supports differential flamegraph +visualization via ``--diff-flamegraph`` to compare two profiling runs. +Functions are colored red (regressions), blue (improvements), gray (neutral), +or purple (new). Elided stacks show code paths that disappeared between runs. From 8e10bd77ea0b674b47f20b0e80df504b0b55fe5c Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 30 Mar 2026 18:07:38 +0530 Subject: [PATCH 333/775] gh-146587: fix type slot assignment incase of multiple slots for same name (#146593) --- Lib/test/test_descr.py | 25 +++++++++++++++++++ ...-03-29-11-39-05.gh-issue-146587.YJicXt.rst | 1 + Objects/typeobject.c | 23 ++++++++++++----- Tools/c-analyzer/cpython/ignored.tsv | 2 +- 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d6e3719479a..1d7669e4fa5 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -5361,6 +5361,31 @@ def foo(self): with self.assertRaisesRegex(NotImplementedError, "BAR"): B().foo + def test_gh146587(self): + # See https://github.com/python/cpython/issues/146587 + + class A: + def __radd__(self, other): ... + + class B(tuple): ... + + self.assertIsNone(() + A()) + self.assertIsNone(B() + A()) + + from typing import NamedTuple + + class T(NamedTuple): + x: int + + class A: + def __init__(self, *args): + self.lst = list(args) + def __radd__(self, other): + return A(*self.lst, other) + + self.assertEqual(((1,)+A()).lst, [(1,)]) + self.assertEqual((T(x=1)+A()).lst, [T(x=1)]) + class DictProxyTests(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst new file mode 100644 index 00000000000..a33dee5c875 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst @@ -0,0 +1 @@ +Fix type slot assignment incase of multiple slots for same name in type object implementation. Patch by Kumar Aditya. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 3374051c42a..6ceeb7dda08 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -11601,7 +11601,7 @@ static pytype_slotdef slotdefs[] = { /* Stores the number of times where slotdefs has elements with same name. This counter precalculated by _PyType_InitSlotDefs() when the main interpreter starts. */ -static uint8_t slotdefs_name_counts[Py_ARRAY_LENGTH(slotdefs)]; +static uint8_t slotdefs_dups[Py_ARRAY_LENGTH(slotdefs)][1 + MAX_EQUIV]; /* Given a type pointer and an offset gotten from a slotdef entry, return a pointer to the actual slot. This is not quite the same as simply adding @@ -11768,11 +11768,22 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p, ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr; size_t index = (p - slotdefs); - if (slotdefs_name_counts[index] == 1) { - tptr = slotptr(type, p->offset); + if (slotdefs_dups[index][0] > 1) { + tptr = NULL; + for (size_t i = 1; i <= slotdefs_dups[index][0]; i++) { + pytype_slotdef *q = &slotdefs[slotdefs_dups[index][i]]; + void **qptr = slotptr(type, q->offset); + if (qptr == NULL || *qptr == NULL) + continue; + if (tptr != NULL) { + tptr = NULL; + break; + } + tptr = qptr; + } } else { - tptr = NULL; + tptr = slotptr(type, offset); } if (tptr == NULL || tptr == ptr) @@ -12034,7 +12045,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp) Py_CLEAR(bytearray); } - memset(slotdefs_name_counts, 0, sizeof(slotdefs_name_counts)); + memset(slotdefs_dups, -1, sizeof(slotdefs_dups)); Py_ssize_t pos = 0; PyObject *key = NULL; @@ -12044,7 +12055,7 @@ _PyType_InitSlotDefs(PyInterpreterState *interp) uint8_t n = data[0]; for (uint8_t i = 0; i < n; i++) { uint8_t idx = data[i + 1]; - slotdefs_name_counts[idx] = n; + memcpy(&slotdefs_dups[idx], data, sizeof(uint8_t) * (n + 1)); } } diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index cbec0bf262f..d2489387f46 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -351,7 +351,7 @@ Objects/obmalloc.c - obmalloc_state_initialized - Objects/typeobject.c - name_op - Objects/typeobject.c - slotdefs - # It initialized only once when main interpeter starts -Objects/typeobject.c - slotdefs_name_counts - +Objects/typeobject.c - slotdefs_dups - Objects/unicodeobject.c - stripfuncnames - Objects/unicodeobject.c - utf7_category - Objects/unicodeobject.c unicode_decode_call_errorhandler_wchar argparse - From adf2c47911b35134cf108c24a3cc7794b7755aac Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 30 Mar 2026 14:48:18 +0200 Subject: [PATCH 334/775] gh-126835: Fix _PY_IS_SMALL_INT() macro (#146631) --- Include/internal/pycore_long.h | 3 ++- Objects/longobject.c | 2 +- Python/flowgraph.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index d545ba0c3ab..4386e8bcad8 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -64,7 +64,8 @@ PyAPI_FUNC(void) _PyLong_ExactDealloc(PyObject *self); # error "_PY_NSMALLPOSINTS must be greater than or equal to 257" #endif -#define _PY_IS_SMALL_INT(val) ((val) >= 0 && (val) < 256 && (val) < _PY_NSMALLPOSINTS) +#define _PY_IS_SMALL_INT(val) \ + (-_PY_NSMALLNEGINTS <= (val) && (val) < _PY_NSMALLPOSINTS) // Return a reference to the immortal zero singleton. // The function cannot return NULL. diff --git a/Objects/longobject.c b/Objects/longobject.c index f1971f0fca9..0d3ea9bc46c 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -26,7 +26,7 @@ class int "PyObject *" "&PyLong_Type" #define medium_value(x) ((stwodigits)_PyLong_CompactValue(x)) -#define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS) +#define IS_SMALL_INT(ival) _PY_IS_SMALL_INT(ival) #define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS) #define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d digits) for integer string conversion: value has %zd digits; use sys.set_int_max_str_digits() to increase the limit" diff --git a/Python/flowgraph.c b/Python/flowgraph.c index f446a87ee69..e988f445100 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -1411,7 +1411,7 @@ maybe_instr_make_load_smallint(cfg_instr *instr, PyObject *newconst, if (val == -1 && PyErr_Occurred()) { return -1; } - if (!overflow && _PY_IS_SMALL_INT(val)) { + if (!overflow && _PY_IS_SMALL_INT(val) && 0 <= val && val <= 255) { assert(_Py_IsImmortal(newconst)); INSTR_SET_OP1(instr, LOAD_SMALL_INT, (int)val); return 1; From 76c554bcdf53e84c79a53203fbf710e033eed839 Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:55:44 +0200 Subject: [PATCH 335/775] gh-139922: always run MSVC 64-bit tail-calling CI (GH-146570) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- .github/workflows/build.yml | 8 ++++++ .github/workflows/reusable-windows.yml | 14 ++++++++--- .github/workflows/tail-call.yml | 35 -------------------------- 3 files changed, 19 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f8ce2d68460..dd5ccf4b3a5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -165,13 +165,21 @@ jobs: free-threading: - false - true + interpreter: + - switch-case exclude: # Skip Win32 on free-threaded builds - { arch: Win32, free-threading: true } + include: + # msvc::musttail is currently only supported on x64, + # and only supported on 3.15+. + - { arch: x64, free-threading: false, interpreter: tail-call } + - { arch: x64, free-threading: true, interpreter: tail-call } uses: ./.github/workflows/reusable-windows.yml with: arch: ${{ matrix.arch }} free-threading: ${{ matrix.free-threading }} + interpreter: ${{ matrix.interpreter }} build-windows-msi: # ${{ '' } is a hack to nest jobs under the same sidebar category. diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 2f667ace919..8772a04d779 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -12,6 +12,10 @@ on: required: false type: boolean default: false + interpreter: + description: Which interpreter to build (switch-case or tail-call) + required: true + type: string env: FORCE_COLOR: 1 @@ -20,7 +24,7 @@ env: jobs: build: - name: Build and test (${{ inputs.arch }}) + name: Build and test (${{ inputs.arch }}, ${{ inputs.interpreter }}) runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2025-vs2026' }} timeout-minutes: 60 env: @@ -33,9 +37,12 @@ jobs: if: inputs.arch != 'Win32' run: echo "::add-matcher::.github/problem-matchers/msvc.json" - name: Build CPython + # msvc::musttail is not supported for debug builds, so we have to + # switch to release. run: >- .\\PCbuild\\build.bat - -e -d -v + -e -v + ${{ inputs.interpreter == 'switch-case' && '-d' || '--tail-call-interp -c Release' }} -p "${ARCH}" ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }} shell: bash @@ -45,6 +52,7 @@ jobs: run: >- .\\PCbuild\\rt.bat -p "${ARCH}" - -d -q --fast-ci + -q --fast-ci + ${{ inputs.interpreter == 'switch-case' && '-d' || '' }} ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }} shell: bash diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index 88833ea3bb2..08bd986a64a 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -23,41 +23,6 @@ env: LLVM_VERSION: 21 jobs: - windows: - name: ${{ matrix.target }} - runs-on: ${{ matrix.runner }} - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - target: x86_64-pc-windows-msvc/msvc - architecture: x64 - runner: windows-2025-vs2026 - build_flags: "" - run_tests: true - - target: x86_64-pc-windows-msvc/msvc-free-threading - architecture: x64 - runner: windows-2025-vs2026 - build_flags: --disable-gil - run_tests: false - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - uses: actions/setup-python@v6 - with: - python-version: '3.11' - - name: Build - shell: pwsh - run: | - ./PCbuild/build.bat --tail-call-interp ${{ matrix.build_flags }} -c Release -p ${{ matrix.architecture }} - - name: Test - if: matrix.run_tests - shell: pwsh - run: | - ./PCbuild/rt.bat -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - macos: name: ${{ matrix.target }} runs-on: ${{ matrix.runner }} From 8e9d21c64b65edda99a0d38e8d23545b17f8455e Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 30 Mar 2026 19:53:29 +0530 Subject: [PATCH 336/775] gh-146558: JIT optimize dict access for objects with known hash (#146559) --- Include/internal/pycore_dict.h | 3 +- Include/internal/pycore_uop_ids.h | 2490 ++++++++++++------------ Include/internal/pycore_uop_metadata.h | 30 + Lib/test/test_capi/test_opt.py | 50 +- Objects/dictobject.c | 34 +- Python/bytecodes.c | 38 + Python/executor_cases.c.h | 95 + Python/optimizer_analysis.c | 27 + Python/optimizer_bytecodes.c | 10 + Python/optimizer_cases.c.h | 38 + 10 files changed, 1558 insertions(+), 1257 deletions(-) diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index a1d1e10ec5c..d58539fa846 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -138,13 +138,14 @@ extern PyObject *_PyDict_LoadBuiltinsFromGlobals(PyObject *globals); /* Consumes references to key and value */ PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value); +PyAPI_FUNC(int) _PyDict_SetItem_Take2_KnownHash(PyDictObject *op, PyObject *key, PyObject *value, Py_hash_t hash); extern int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash); // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_GetItemRef_KnownHash_LockHeld(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); -extern int _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); +PyAPI_FUNC(int) _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result); extern int _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result); PyAPI_FUNC(int) _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr, PyObject *name, PyObject *value); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index f60859a05f9..dbc7aaab7a7 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -25,17 +25,18 @@ extern "C" { #define _BINARY_OP_MULTIPLY_INT 313 #define _BINARY_OP_SUBSCR_CHECK_FUNC 314 #define _BINARY_OP_SUBSCR_DICT 315 -#define _BINARY_OP_SUBSCR_INIT_CALL 316 -#define _BINARY_OP_SUBSCR_LIST_INT 317 -#define _BINARY_OP_SUBSCR_LIST_SLICE 318 -#define _BINARY_OP_SUBSCR_STR_INT 319 -#define _BINARY_OP_SUBSCR_TUPLE_INT 320 -#define _BINARY_OP_SUBSCR_USTR_INT 321 -#define _BINARY_OP_SUBTRACT_FLOAT 322 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 323 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 324 -#define _BINARY_OP_SUBTRACT_INT 325 -#define _BINARY_SLICE 326 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH 316 +#define _BINARY_OP_SUBSCR_INIT_CALL 317 +#define _BINARY_OP_SUBSCR_LIST_INT 318 +#define _BINARY_OP_SUBSCR_LIST_SLICE 319 +#define _BINARY_OP_SUBSCR_STR_INT 320 +#define _BINARY_OP_SUBSCR_TUPLE_INT 321 +#define _BINARY_OP_SUBSCR_USTR_INT 322 +#define _BINARY_OP_SUBTRACT_FLOAT 323 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 324 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 325 +#define _BINARY_OP_SUBTRACT_INT 326 +#define _BINARY_SLICE 327 #define _BUILD_INTERPOLATION BUILD_INTERPOLATION #define _BUILD_LIST BUILD_LIST #define _BUILD_MAP BUILD_MAP @@ -44,181 +45,181 @@ extern "C" { #define _BUILD_STRING BUILD_STRING #define _BUILD_TEMPLATE BUILD_TEMPLATE #define _BUILD_TUPLE BUILD_TUPLE -#define _CALL_BUILTIN_CLASS 327 -#define _CALL_BUILTIN_FAST 328 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 329 -#define _CALL_BUILTIN_O 330 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL 331 -#define _CALL_INTRINSIC_1 332 -#define _CALL_INTRINSIC_2 333 -#define _CALL_ISINSTANCE 334 -#define _CALL_KW_NON_PY 335 -#define _CALL_LEN 336 -#define _CALL_LIST_APPEND 337 -#define _CALL_METHOD_DESCRIPTOR_FAST 338 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 339 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 340 -#define _CALL_METHOD_DESCRIPTOR_O 341 -#define _CALL_NON_PY_GENERAL 342 -#define _CALL_STR_1 343 -#define _CALL_TUPLE_1 344 -#define _CALL_TYPE_1 345 -#define _CHECK_AND_ALLOCATE_OBJECT 346 -#define _CHECK_ATTR_CLASS 347 -#define _CHECK_ATTR_METHOD_LAZY_DICT 348 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 349 +#define _CALL_BUILTIN_CLASS 328 +#define _CALL_BUILTIN_FAST 329 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 330 +#define _CALL_BUILTIN_O 331 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL 332 +#define _CALL_INTRINSIC_1 333 +#define _CALL_INTRINSIC_2 334 +#define _CALL_ISINSTANCE 335 +#define _CALL_KW_NON_PY 336 +#define _CALL_LEN 337 +#define _CALL_LIST_APPEND 338 +#define _CALL_METHOD_DESCRIPTOR_FAST 339 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 340 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 341 +#define _CALL_METHOD_DESCRIPTOR_O 342 +#define _CALL_NON_PY_GENERAL 343 +#define _CALL_STR_1 344 +#define _CALL_TUPLE_1 345 +#define _CALL_TYPE_1 346 +#define _CHECK_AND_ALLOCATE_OBJECT 347 +#define _CHECK_ATTR_CLASS 348 +#define _CHECK_ATTR_METHOD_LAZY_DICT 349 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 350 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION_EXACT_ARGS 350 -#define _CHECK_FUNCTION_VERSION 351 -#define _CHECK_FUNCTION_VERSION_INLINE 352 -#define _CHECK_FUNCTION_VERSION_KW 353 -#define _CHECK_IS_NOT_PY_CALLABLE 354 -#define _CHECK_IS_NOT_PY_CALLABLE_EX 355 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 356 -#define _CHECK_IS_PY_CALLABLE_EX 357 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 358 -#define _CHECK_METHOD_VERSION 359 -#define _CHECK_METHOD_VERSION_KW 360 -#define _CHECK_PEP_523 361 -#define _CHECK_PERIODIC 362 -#define _CHECK_PERIODIC_AT_END 363 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 364 -#define _CHECK_RECURSION_REMAINING 365 -#define _CHECK_STACK_SPACE 366 -#define _CHECK_STACK_SPACE_OPERAND 367 -#define _CHECK_VALIDITY 368 -#define _COLD_DYNAMIC_EXIT 369 -#define _COLD_EXIT 370 -#define _COMPARE_OP 371 -#define _COMPARE_OP_FLOAT 372 -#define _COMPARE_OP_INT 373 -#define _COMPARE_OP_STR 374 -#define _CONTAINS_OP 375 -#define _CONTAINS_OP_DICT 376 -#define _CONTAINS_OP_SET 377 +#define _CHECK_FUNCTION_EXACT_ARGS 351 +#define _CHECK_FUNCTION_VERSION 352 +#define _CHECK_FUNCTION_VERSION_INLINE 353 +#define _CHECK_FUNCTION_VERSION_KW 354 +#define _CHECK_IS_NOT_PY_CALLABLE 355 +#define _CHECK_IS_NOT_PY_CALLABLE_EX 356 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 357 +#define _CHECK_IS_PY_CALLABLE_EX 358 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 359 +#define _CHECK_METHOD_VERSION 360 +#define _CHECK_METHOD_VERSION_KW 361 +#define _CHECK_PEP_523 362 +#define _CHECK_PERIODIC 363 +#define _CHECK_PERIODIC_AT_END 364 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 365 +#define _CHECK_RECURSION_REMAINING 366 +#define _CHECK_STACK_SPACE 367 +#define _CHECK_STACK_SPACE_OPERAND 368 +#define _CHECK_VALIDITY 369 +#define _COLD_DYNAMIC_EXIT 370 +#define _COLD_EXIT 371 +#define _COMPARE_OP 372 +#define _COMPARE_OP_FLOAT 373 +#define _COMPARE_OP_INT 374 +#define _COMPARE_OP_STR 375 +#define _CONTAINS_OP 376 +#define _CONTAINS_OP_DICT 377 +#define _CONTAINS_OP_SET 378 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 378 -#define _COPY_1 379 -#define _COPY_2 380 -#define _COPY_3 381 +#define _COPY 379 +#define _COPY_1 380 +#define _COPY_2 381 +#define _COPY_3 382 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 382 +#define _CREATE_INIT_FRAME 383 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 383 -#define _DICT_MERGE 384 -#define _DICT_UPDATE 385 -#define _DO_CALL 386 -#define _DO_CALL_FUNCTION_EX 387 -#define _DO_CALL_KW 388 -#define _DYNAMIC_EXIT 389 +#define _DEOPT 384 +#define _DICT_MERGE 385 +#define _DICT_UPDATE 386 +#define _DO_CALL 387 +#define _DO_CALL_FUNCTION_EX 388 +#define _DO_CALL_KW 389 +#define _DYNAMIC_EXIT 390 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 390 +#define _ERROR_POP_N 391 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 391 -#define _EXPAND_METHOD_KW 392 -#define _FATAL_ERROR 393 +#define _EXPAND_METHOD 392 +#define _EXPAND_METHOD_KW 393 +#define _FATAL_ERROR 394 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 394 -#define _FOR_ITER_GEN_FRAME 395 -#define _FOR_ITER_TIER_TWO 396 +#define _FOR_ITER 395 +#define _FOR_ITER_GEN_FRAME 396 +#define _FOR_ITER_TIER_TWO 397 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN -#define _GUARD_BINARY_OP_EXTEND 397 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 398 -#define _GUARD_BIT_IS_SET_POP 399 -#define _GUARD_BIT_IS_SET_POP_4 400 -#define _GUARD_BIT_IS_SET_POP_5 401 -#define _GUARD_BIT_IS_SET_POP_6 402 -#define _GUARD_BIT_IS_SET_POP_7 403 -#define _GUARD_BIT_IS_UNSET_POP 404 -#define _GUARD_BIT_IS_UNSET_POP_4 405 -#define _GUARD_BIT_IS_UNSET_POP_5 406 -#define _GUARD_BIT_IS_UNSET_POP_6 407 -#define _GUARD_BIT_IS_UNSET_POP_7 408 -#define _GUARD_CALLABLE_BUILTIN_FAST 409 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 410 -#define _GUARD_CALLABLE_BUILTIN_O 411 -#define _GUARD_CALLABLE_ISINSTANCE 412 -#define _GUARD_CALLABLE_LEN 413 -#define _GUARD_CALLABLE_LIST_APPEND 414 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 415 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 416 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 417 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 418 -#define _GUARD_CALLABLE_STR_1 419 -#define _GUARD_CALLABLE_TUPLE_1 420 -#define _GUARD_CALLABLE_TYPE_1 421 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR 422 -#define _GUARD_CODE_VERSION_RETURN_VALUE 423 -#define _GUARD_CODE_VERSION_YIELD_VALUE 424 -#define _GUARD_CODE_VERSION__PUSH_FRAME 425 -#define _GUARD_DORV_NO_DICT 426 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 427 -#define _GUARD_GLOBALS_VERSION 428 -#define _GUARD_IP_RETURN_GENERATOR 429 -#define _GUARD_IP_RETURN_VALUE 430 -#define _GUARD_IP_YIELD_VALUE 431 -#define _GUARD_IP__PUSH_FRAME 432 -#define _GUARD_IS_FALSE_POP 433 -#define _GUARD_IS_NONE_POP 434 -#define _GUARD_IS_NOT_NONE_POP 435 -#define _GUARD_IS_TRUE_POP 436 -#define _GUARD_KEYS_VERSION 437 -#define _GUARD_NOS_ANY_DICT 438 -#define _GUARD_NOS_COMPACT_ASCII 439 -#define _GUARD_NOS_DICT 440 -#define _GUARD_NOS_FLOAT 441 -#define _GUARD_NOS_INT 442 -#define _GUARD_NOS_LIST 443 -#define _GUARD_NOS_NOT_NULL 444 -#define _GUARD_NOS_NULL 445 -#define _GUARD_NOS_OVERFLOWED 446 -#define _GUARD_NOS_TUPLE 447 -#define _GUARD_NOS_UNICODE 448 -#define _GUARD_NOT_EXHAUSTED_LIST 449 -#define _GUARD_NOT_EXHAUSTED_RANGE 450 -#define _GUARD_NOT_EXHAUSTED_TUPLE 451 -#define _GUARD_THIRD_NULL 452 -#define _GUARD_TOS_ANY_DICT 453 -#define _GUARD_TOS_ANY_SET 454 -#define _GUARD_TOS_DICT 455 -#define _GUARD_TOS_FLOAT 456 -#define _GUARD_TOS_FROZENDICT 457 -#define _GUARD_TOS_FROZENSET 458 -#define _GUARD_TOS_INT 459 -#define _GUARD_TOS_LIST 460 -#define _GUARD_TOS_OVERFLOWED 461 -#define _GUARD_TOS_SET 462 -#define _GUARD_TOS_SLICE 463 -#define _GUARD_TOS_TUPLE 464 -#define _GUARD_TOS_UNICODE 465 -#define _GUARD_TYPE_VERSION 466 -#define _GUARD_TYPE_VERSION_LOCKED 467 -#define _HANDLE_PENDING_AND_DEOPT 468 +#define _GUARD_BINARY_OP_EXTEND 398 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 399 +#define _GUARD_BIT_IS_SET_POP 400 +#define _GUARD_BIT_IS_SET_POP_4 401 +#define _GUARD_BIT_IS_SET_POP_5 402 +#define _GUARD_BIT_IS_SET_POP_6 403 +#define _GUARD_BIT_IS_SET_POP_7 404 +#define _GUARD_BIT_IS_UNSET_POP 405 +#define _GUARD_BIT_IS_UNSET_POP_4 406 +#define _GUARD_BIT_IS_UNSET_POP_5 407 +#define _GUARD_BIT_IS_UNSET_POP_6 408 +#define _GUARD_BIT_IS_UNSET_POP_7 409 +#define _GUARD_CALLABLE_BUILTIN_FAST 410 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 411 +#define _GUARD_CALLABLE_BUILTIN_O 412 +#define _GUARD_CALLABLE_ISINSTANCE 413 +#define _GUARD_CALLABLE_LEN 414 +#define _GUARD_CALLABLE_LIST_APPEND 415 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 416 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 417 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 418 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 419 +#define _GUARD_CALLABLE_STR_1 420 +#define _GUARD_CALLABLE_TUPLE_1 421 +#define _GUARD_CALLABLE_TYPE_1 422 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR 423 +#define _GUARD_CODE_VERSION_RETURN_VALUE 424 +#define _GUARD_CODE_VERSION_YIELD_VALUE 425 +#define _GUARD_CODE_VERSION__PUSH_FRAME 426 +#define _GUARD_DORV_NO_DICT 427 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 428 +#define _GUARD_GLOBALS_VERSION 429 +#define _GUARD_IP_RETURN_GENERATOR 430 +#define _GUARD_IP_RETURN_VALUE 431 +#define _GUARD_IP_YIELD_VALUE 432 +#define _GUARD_IP__PUSH_FRAME 433 +#define _GUARD_IS_FALSE_POP 434 +#define _GUARD_IS_NONE_POP 435 +#define _GUARD_IS_NOT_NONE_POP 436 +#define _GUARD_IS_TRUE_POP 437 +#define _GUARD_KEYS_VERSION 438 +#define _GUARD_NOS_ANY_DICT 439 +#define _GUARD_NOS_COMPACT_ASCII 440 +#define _GUARD_NOS_DICT 441 +#define _GUARD_NOS_FLOAT 442 +#define _GUARD_NOS_INT 443 +#define _GUARD_NOS_LIST 444 +#define _GUARD_NOS_NOT_NULL 445 +#define _GUARD_NOS_NULL 446 +#define _GUARD_NOS_OVERFLOWED 447 +#define _GUARD_NOS_TUPLE 448 +#define _GUARD_NOS_UNICODE 449 +#define _GUARD_NOT_EXHAUSTED_LIST 450 +#define _GUARD_NOT_EXHAUSTED_RANGE 451 +#define _GUARD_NOT_EXHAUSTED_TUPLE 452 +#define _GUARD_THIRD_NULL 453 +#define _GUARD_TOS_ANY_DICT 454 +#define _GUARD_TOS_ANY_SET 455 +#define _GUARD_TOS_DICT 456 +#define _GUARD_TOS_FLOAT 457 +#define _GUARD_TOS_FROZENDICT 458 +#define _GUARD_TOS_FROZENSET 459 +#define _GUARD_TOS_INT 460 +#define _GUARD_TOS_LIST 461 +#define _GUARD_TOS_OVERFLOWED 462 +#define _GUARD_TOS_SET 463 +#define _GUARD_TOS_SLICE 464 +#define _GUARD_TOS_TUPLE 465 +#define _GUARD_TOS_UNICODE 466 +#define _GUARD_TYPE_VERSION 467 +#define _GUARD_TYPE_VERSION_LOCKED 468 +#define _HANDLE_PENDING_AND_DEOPT 469 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 469 -#define _INIT_CALL_PY_EXACT_ARGS 470 -#define _INIT_CALL_PY_EXACT_ARGS_0 471 -#define _INIT_CALL_PY_EXACT_ARGS_1 472 -#define _INIT_CALL_PY_EXACT_ARGS_2 473 -#define _INIT_CALL_PY_EXACT_ARGS_3 474 -#define _INIT_CALL_PY_EXACT_ARGS_4 475 -#define _INSERT_1_LOAD_CONST_INLINE 476 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 477 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 478 -#define _INSERT_NULL 479 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 470 +#define _INIT_CALL_PY_EXACT_ARGS 471 +#define _INIT_CALL_PY_EXACT_ARGS_0 472 +#define _INIT_CALL_PY_EXACT_ARGS_1 473 +#define _INIT_CALL_PY_EXACT_ARGS_2 474 +#define _INIT_CALL_PY_EXACT_ARGS_3 475 +#define _INIT_CALL_PY_EXACT_ARGS_4 476 +#define _INSERT_1_LOAD_CONST_INLINE 477 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW 478 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW 479 +#define _INSERT_NULL 480 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -228,1125 +229,1128 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 480 -#define _IS_OP 481 -#define _ITER_CHECK_LIST 482 -#define _ITER_CHECK_RANGE 483 -#define _ITER_CHECK_TUPLE 484 -#define _ITER_JUMP_LIST 485 -#define _ITER_JUMP_RANGE 486 -#define _ITER_JUMP_TUPLE 487 -#define _ITER_NEXT_LIST 488 -#define _ITER_NEXT_LIST_TIER_TWO 489 -#define _ITER_NEXT_RANGE 490 -#define _ITER_NEXT_TUPLE 491 +#define _IS_NONE 481 +#define _IS_OP 482 +#define _ITER_CHECK_LIST 483 +#define _ITER_CHECK_RANGE 484 +#define _ITER_CHECK_TUPLE 485 +#define _ITER_JUMP_LIST 486 +#define _ITER_JUMP_RANGE 487 +#define _ITER_JUMP_TUPLE 488 +#define _ITER_NEXT_LIST 489 +#define _ITER_NEXT_LIST_TIER_TWO 490 +#define _ITER_NEXT_RANGE 491 +#define _ITER_NEXT_TUPLE 492 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 492 +#define _JUMP_TO_TOP 493 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND 493 -#define _LOAD_ATTR 494 -#define _LOAD_ATTR_CLASS 495 +#define _LIST_EXTEND 494 +#define _LOAD_ATTR 495 +#define _LOAD_ATTR_CLASS 496 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 496 -#define _LOAD_ATTR_METHOD_LAZY_DICT 497 -#define _LOAD_ATTR_METHOD_NO_DICT 498 -#define _LOAD_ATTR_METHOD_WITH_VALUES 499 -#define _LOAD_ATTR_MODULE 500 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 501 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 502 -#define _LOAD_ATTR_PROPERTY_FRAME 503 -#define _LOAD_ATTR_SLOT 504 -#define _LOAD_ATTR_WITH_HINT 505 +#define _LOAD_ATTR_INSTANCE_VALUE 497 +#define _LOAD_ATTR_METHOD_LAZY_DICT 498 +#define _LOAD_ATTR_METHOD_NO_DICT 499 +#define _LOAD_ATTR_METHOD_WITH_VALUES 500 +#define _LOAD_ATTR_MODULE 501 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 502 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 503 +#define _LOAD_ATTR_PROPERTY_FRAME 504 +#define _LOAD_ATTR_SLOT 505 +#define _LOAD_ATTR_WITH_HINT 506 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 506 +#define _LOAD_BYTECODE 507 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 507 -#define _LOAD_CONST_INLINE_BORROW 508 -#define _LOAD_CONST_UNDER_INLINE 509 -#define _LOAD_CONST_UNDER_INLINE_BORROW 510 +#define _LOAD_CONST_INLINE 508 +#define _LOAD_CONST_INLINE_BORROW 509 +#define _LOAD_CONST_UNDER_INLINE 510 +#define _LOAD_CONST_UNDER_INLINE_BORROW 511 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 511 -#define _LOAD_FAST_0 512 -#define _LOAD_FAST_1 513 -#define _LOAD_FAST_2 514 -#define _LOAD_FAST_3 515 -#define _LOAD_FAST_4 516 -#define _LOAD_FAST_5 517 -#define _LOAD_FAST_6 518 -#define _LOAD_FAST_7 519 +#define _LOAD_FAST 512 +#define _LOAD_FAST_0 513 +#define _LOAD_FAST_1 514 +#define _LOAD_FAST_2 515 +#define _LOAD_FAST_3 516 +#define _LOAD_FAST_4 517 +#define _LOAD_FAST_5 518 +#define _LOAD_FAST_6 519 +#define _LOAD_FAST_7 520 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 520 -#define _LOAD_FAST_BORROW_0 521 -#define _LOAD_FAST_BORROW_1 522 -#define _LOAD_FAST_BORROW_2 523 -#define _LOAD_FAST_BORROW_3 524 -#define _LOAD_FAST_BORROW_4 525 -#define _LOAD_FAST_BORROW_5 526 -#define _LOAD_FAST_BORROW_6 527 -#define _LOAD_FAST_BORROW_7 528 +#define _LOAD_FAST_BORROW 521 +#define _LOAD_FAST_BORROW_0 522 +#define _LOAD_FAST_BORROW_1 523 +#define _LOAD_FAST_BORROW_2 524 +#define _LOAD_FAST_BORROW_3 525 +#define _LOAD_FAST_BORROW_4 526 +#define _LOAD_FAST_BORROW_5 527 +#define _LOAD_FAST_BORROW_6 528 +#define _LOAD_FAST_BORROW_7 529 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 529 -#define _LOAD_GLOBAL_BUILTINS 530 -#define _LOAD_GLOBAL_MODULE 531 +#define _LOAD_GLOBAL 530 +#define _LOAD_GLOBAL_BUILTINS 531 +#define _LOAD_GLOBAL_MODULE 532 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 532 -#define _LOAD_SMALL_INT_0 533 -#define _LOAD_SMALL_INT_1 534 -#define _LOAD_SMALL_INT_2 535 -#define _LOAD_SMALL_INT_3 536 -#define _LOAD_SPECIAL 537 +#define _LOAD_SMALL_INT 533 +#define _LOAD_SMALL_INT_0 534 +#define _LOAD_SMALL_INT_1 535 +#define _LOAD_SMALL_INT_2 536 +#define _LOAD_SMALL_INT_3 537 +#define _LOAD_SPECIAL 538 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _LOCK_OBJECT 538 -#define _MAKE_CALLARGS_A_TUPLE 539 +#define _LOCK_OBJECT 539 +#define _MAKE_CALLARGS_A_TUPLE 540 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_HEAP_SAFE 540 -#define _MAKE_WARM 541 +#define _MAKE_HEAP_SAFE 541 +#define _MAKE_WARM 542 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 542 +#define _MATCH_CLASS 543 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 543 -#define _MAYBE_EXPAND_METHOD_KW 544 -#define _MONITOR_CALL 545 -#define _MONITOR_CALL_KW 546 -#define _MONITOR_JUMP_BACKWARD 547 -#define _MONITOR_RESUME 548 +#define _MAYBE_EXPAND_METHOD 544 +#define _MAYBE_EXPAND_METHOD_KW 545 +#define _MONITOR_CALL 546 +#define _MONITOR_CALL_KW 547 +#define _MONITOR_JUMP_BACKWARD 548 +#define _MONITOR_RESUME 549 #define _NOP NOP -#define _POP_CALL 549 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 550 -#define _POP_CALL_ONE 551 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 552 -#define _POP_CALL_TWO 553 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 554 +#define _POP_CALL 550 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 551 +#define _POP_CALL_ONE 552 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 553 +#define _POP_CALL_TWO 554 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 555 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 555 -#define _POP_JUMP_IF_TRUE 556 +#define _POP_JUMP_IF_FALSE 556 +#define _POP_JUMP_IF_TRUE 557 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 557 -#define _POP_TOP_INT 558 -#define _POP_TOP_LOAD_CONST_INLINE 559 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 560 -#define _POP_TOP_NOP 561 -#define _POP_TOP_UNICODE 562 -#define _POP_TWO 563 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 564 +#define _POP_TOP_FLOAT 558 +#define _POP_TOP_INT 559 +#define _POP_TOP_LOAD_CONST_INLINE 560 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 561 +#define _POP_TOP_NOP 562 +#define _POP_TOP_UNICODE 563 +#define _POP_TWO 564 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 565 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 565 +#define _PUSH_FRAME 566 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 566 -#define _PY_FRAME_EX 567 -#define _PY_FRAME_GENERAL 568 -#define _PY_FRAME_KW 569 -#define _RECORD_3OS_GEN_FUNC 570 -#define _RECORD_4OS 571 -#define _RECORD_BOUND_METHOD 572 -#define _RECORD_CALLABLE 573 -#define _RECORD_CODE 574 -#define _RECORD_NOS 575 -#define _RECORD_NOS_GEN_FUNC 576 -#define _RECORD_TOS 577 -#define _RECORD_TOS_TYPE 578 -#define _REPLACE_WITH_TRUE 579 -#define _RESUME_CHECK 580 +#define _PUSH_NULL_CONDITIONAL 567 +#define _PY_FRAME_EX 568 +#define _PY_FRAME_GENERAL 569 +#define _PY_FRAME_KW 570 +#define _RECORD_3OS_GEN_FUNC 571 +#define _RECORD_4OS 572 +#define _RECORD_BOUND_METHOD 573 +#define _RECORD_CALLABLE 574 +#define _RECORD_CODE 575 +#define _RECORD_NOS 576 +#define _RECORD_NOS_GEN_FUNC 577 +#define _RECORD_TOS 578 +#define _RECORD_TOS_TYPE 579 +#define _REPLACE_WITH_TRUE 580 +#define _RESUME_CHECK 581 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 581 -#define _SAVE_RETURN_OFFSET 582 -#define _SEND 583 -#define _SEND_GEN_FRAME 584 +#define _RETURN_VALUE 582 +#define _SAVE_RETURN_OFFSET 583 +#define _SEND 584 +#define _SEND_GEN_FRAME 585 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 585 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 586 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 587 -#define _SPILL_OR_RELOAD 588 -#define _START_EXECUTOR 589 -#define _STORE_ATTR 590 -#define _STORE_ATTR_INSTANCE_VALUE 591 -#define _STORE_ATTR_SLOT 592 -#define _STORE_ATTR_WITH_HINT 593 +#define _SET_UPDATE 586 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 587 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 588 +#define _SPILL_OR_RELOAD 589 +#define _START_EXECUTOR 590 +#define _STORE_ATTR 591 +#define _STORE_ATTR_INSTANCE_VALUE 592 +#define _STORE_ATTR_SLOT 593 +#define _STORE_ATTR_WITH_HINT 594 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 594 -#define _STORE_SUBSCR 595 -#define _STORE_SUBSCR_DICT 596 -#define _STORE_SUBSCR_LIST_INT 597 -#define _SWAP 598 -#define _SWAP_2 599 -#define _SWAP_3 600 -#define _SWAP_FAST 601 -#define _SWAP_FAST_0 602 -#define _SWAP_FAST_1 603 -#define _SWAP_FAST_2 604 -#define _SWAP_FAST_3 605 -#define _SWAP_FAST_4 606 -#define _SWAP_FAST_5 607 -#define _SWAP_FAST_6 608 -#define _SWAP_FAST_7 609 -#define _TIER2_RESUME_CHECK 610 -#define _TO_BOOL 611 +#define _STORE_SLICE 595 +#define _STORE_SUBSCR 596 +#define _STORE_SUBSCR_DICT 597 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 598 +#define _STORE_SUBSCR_LIST_INT 599 +#define _SWAP 600 +#define _SWAP_2 601 +#define _SWAP_3 602 +#define _SWAP_FAST 603 +#define _SWAP_FAST_0 604 +#define _SWAP_FAST_1 605 +#define _SWAP_FAST_2 606 +#define _SWAP_FAST_3 607 +#define _SWAP_FAST_4 608 +#define _SWAP_FAST_5 609 +#define _SWAP_FAST_6 610 +#define _SWAP_FAST_7 611 +#define _TIER2_RESUME_CHECK 612 +#define _TO_BOOL 613 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 612 -#define _TO_BOOL_LIST 613 +#define _TO_BOOL_INT 614 +#define _TO_BOOL_LIST 615 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 614 +#define _TO_BOOL_STR 616 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 615 -#define _UNARY_NEGATIVE 616 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 617 +#define _UNARY_INVERT 617 +#define _UNARY_NEGATIVE 618 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 619 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 618 -#define _UNPACK_SEQUENCE_LIST 619 -#define _UNPACK_SEQUENCE_TUPLE 620 -#define _UNPACK_SEQUENCE_TWO_TUPLE 621 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 622 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 623 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 624 +#define _UNPACK_SEQUENCE 620 +#define _UNPACK_SEQUENCE_LIST 621 +#define _UNPACK_SEQUENCE_TUPLE 622 +#define _UNPACK_SEQUENCE_TWO_TUPLE 623 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 624 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 625 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 626 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 625 -#define MAX_UOP_ID 625 -#define _BINARY_OP_r23 626 -#define _BINARY_OP_ADD_FLOAT_r03 627 -#define _BINARY_OP_ADD_FLOAT_r13 628 -#define _BINARY_OP_ADD_FLOAT_r23 629 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 630 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 631 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 632 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 633 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 634 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 635 -#define _BINARY_OP_ADD_INT_r03 636 -#define _BINARY_OP_ADD_INT_r13 637 -#define _BINARY_OP_ADD_INT_r23 638 -#define _BINARY_OP_ADD_UNICODE_r03 639 -#define _BINARY_OP_ADD_UNICODE_r13 640 -#define _BINARY_OP_ADD_UNICODE_r23 641 -#define _BINARY_OP_EXTEND_r23 642 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 643 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 644 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 645 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 646 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 647 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 648 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 649 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 650 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 651 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 652 -#define _BINARY_OP_MULTIPLY_INT_r03 653 -#define _BINARY_OP_MULTIPLY_INT_r13 654 -#define _BINARY_OP_MULTIPLY_INT_r23 655 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 656 -#define _BINARY_OP_SUBSCR_DICT_r23 657 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 658 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 659 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 660 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 661 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 662 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 663 -#define _BINARY_OP_SUBSCR_STR_INT_r23 664 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 665 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 666 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 667 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 668 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 669 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 670 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 671 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 672 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 673 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 674 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 675 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 676 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 677 -#define _BINARY_OP_SUBTRACT_INT_r03 678 -#define _BINARY_OP_SUBTRACT_INT_r13 679 -#define _BINARY_OP_SUBTRACT_INT_r23 680 -#define _BINARY_SLICE_r31 681 -#define _BUILD_INTERPOLATION_r01 682 -#define _BUILD_LIST_r01 683 -#define _BUILD_MAP_r01 684 -#define _BUILD_SET_r01 685 -#define _BUILD_SLICE_r01 686 -#define _BUILD_STRING_r01 687 -#define _BUILD_TEMPLATE_r21 688 -#define _BUILD_TUPLE_r01 689 -#define _CALL_BUILTIN_CLASS_r01 690 -#define _CALL_BUILTIN_FAST_r01 691 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 692 -#define _CALL_BUILTIN_O_r03 693 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 694 -#define _CALL_INTRINSIC_1_r12 695 -#define _CALL_INTRINSIC_2_r23 696 -#define _CALL_ISINSTANCE_r31 697 -#define _CALL_KW_NON_PY_r11 698 -#define _CALL_LEN_r33 699 -#define _CALL_LIST_APPEND_r03 700 -#define _CALL_LIST_APPEND_r13 701 -#define _CALL_LIST_APPEND_r23 702 -#define _CALL_LIST_APPEND_r33 703 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 704 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 705 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 706 -#define _CALL_METHOD_DESCRIPTOR_O_r03 707 -#define _CALL_NON_PY_GENERAL_r01 708 -#define _CALL_STR_1_r32 709 -#define _CALL_TUPLE_1_r32 710 -#define _CALL_TYPE_1_r02 711 -#define _CALL_TYPE_1_r12 712 -#define _CALL_TYPE_1_r22 713 -#define _CALL_TYPE_1_r32 714 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 715 -#define _CHECK_ATTR_CLASS_r01 716 -#define _CHECK_ATTR_CLASS_r11 717 -#define _CHECK_ATTR_CLASS_r22 718 -#define _CHECK_ATTR_CLASS_r33 719 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 720 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 721 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 722 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 723 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 724 -#define _CHECK_EG_MATCH_r22 725 -#define _CHECK_EXC_MATCH_r22 726 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 727 -#define _CHECK_FUNCTION_VERSION_r00 728 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 729 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 730 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 731 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 732 -#define _CHECK_FUNCTION_VERSION_KW_r11 733 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 734 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 735 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 736 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 737 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 738 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 739 -#define _CHECK_IS_PY_CALLABLE_EX_r03 740 -#define _CHECK_IS_PY_CALLABLE_EX_r13 741 -#define _CHECK_IS_PY_CALLABLE_EX_r23 742 -#define _CHECK_IS_PY_CALLABLE_EX_r33 743 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 744 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 745 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 746 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 747 -#define _CHECK_METHOD_VERSION_r00 748 -#define _CHECK_METHOD_VERSION_KW_r11 749 -#define _CHECK_PEP_523_r00 750 -#define _CHECK_PEP_523_r11 751 -#define _CHECK_PEP_523_r22 752 -#define _CHECK_PEP_523_r33 753 -#define _CHECK_PERIODIC_r00 754 -#define _CHECK_PERIODIC_AT_END_r00 755 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 756 -#define _CHECK_RECURSION_REMAINING_r00 757 -#define _CHECK_RECURSION_REMAINING_r11 758 -#define _CHECK_RECURSION_REMAINING_r22 759 -#define _CHECK_RECURSION_REMAINING_r33 760 -#define _CHECK_STACK_SPACE_r00 761 -#define _CHECK_STACK_SPACE_OPERAND_r00 762 -#define _CHECK_STACK_SPACE_OPERAND_r11 763 -#define _CHECK_STACK_SPACE_OPERAND_r22 764 -#define _CHECK_STACK_SPACE_OPERAND_r33 765 -#define _CHECK_VALIDITY_r00 766 -#define _CHECK_VALIDITY_r11 767 -#define _CHECK_VALIDITY_r22 768 -#define _CHECK_VALIDITY_r33 769 -#define _COLD_DYNAMIC_EXIT_r00 770 -#define _COLD_EXIT_r00 771 -#define _COMPARE_OP_r21 772 -#define _COMPARE_OP_FLOAT_r03 773 -#define _COMPARE_OP_FLOAT_r13 774 -#define _COMPARE_OP_FLOAT_r23 775 -#define _COMPARE_OP_INT_r23 776 -#define _COMPARE_OP_STR_r23 777 -#define _CONTAINS_OP_r23 778 -#define _CONTAINS_OP_DICT_r23 779 -#define _CONTAINS_OP_SET_r23 780 -#define _CONVERT_VALUE_r11 781 -#define _COPY_r01 782 -#define _COPY_1_r02 783 -#define _COPY_1_r12 784 -#define _COPY_1_r23 785 -#define _COPY_2_r03 786 -#define _COPY_2_r13 787 -#define _COPY_2_r23 788 -#define _COPY_3_r03 789 -#define _COPY_3_r13 790 -#define _COPY_3_r23 791 -#define _COPY_3_r33 792 -#define _COPY_FREE_VARS_r00 793 -#define _COPY_FREE_VARS_r11 794 -#define _COPY_FREE_VARS_r22 795 -#define _COPY_FREE_VARS_r33 796 -#define _CREATE_INIT_FRAME_r01 797 -#define _DELETE_ATTR_r10 798 -#define _DELETE_DEREF_r00 799 -#define _DELETE_FAST_r00 800 -#define _DELETE_GLOBAL_r00 801 -#define _DELETE_NAME_r00 802 -#define _DELETE_SUBSCR_r20 803 -#define _DEOPT_r00 804 -#define _DEOPT_r10 805 -#define _DEOPT_r20 806 -#define _DEOPT_r30 807 -#define _DICT_MERGE_r11 808 -#define _DICT_UPDATE_r11 809 -#define _DO_CALL_r01 810 -#define _DO_CALL_FUNCTION_EX_r31 811 -#define _DO_CALL_KW_r11 812 -#define _DYNAMIC_EXIT_r00 813 -#define _DYNAMIC_EXIT_r10 814 -#define _DYNAMIC_EXIT_r20 815 -#define _DYNAMIC_EXIT_r30 816 -#define _END_FOR_r10 817 -#define _END_SEND_r31 818 -#define _ERROR_POP_N_r00 819 -#define _EXIT_INIT_CHECK_r10 820 -#define _EXIT_TRACE_r00 821 -#define _EXIT_TRACE_r10 822 -#define _EXIT_TRACE_r20 823 -#define _EXIT_TRACE_r30 824 -#define _EXPAND_METHOD_r00 825 -#define _EXPAND_METHOD_KW_r11 826 -#define _FATAL_ERROR_r00 827 -#define _FATAL_ERROR_r11 828 -#define _FATAL_ERROR_r22 829 -#define _FATAL_ERROR_r33 830 -#define _FORMAT_SIMPLE_r11 831 -#define _FORMAT_WITH_SPEC_r21 832 -#define _FOR_ITER_r23 833 -#define _FOR_ITER_GEN_FRAME_r03 834 -#define _FOR_ITER_GEN_FRAME_r13 835 -#define _FOR_ITER_GEN_FRAME_r23 836 -#define _FOR_ITER_TIER_TWO_r23 837 -#define _GET_AITER_r11 838 -#define _GET_ANEXT_r12 839 -#define _GET_AWAITABLE_r11 840 -#define _GET_ITER_r12 841 -#define _GET_LEN_r12 842 -#define _GUARD_BINARY_OP_EXTEND_r22 843 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 844 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 845 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 846 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 847 -#define _GUARD_BIT_IS_SET_POP_r00 848 -#define _GUARD_BIT_IS_SET_POP_r10 849 -#define _GUARD_BIT_IS_SET_POP_r21 850 -#define _GUARD_BIT_IS_SET_POP_r32 851 -#define _GUARD_BIT_IS_SET_POP_4_r00 852 -#define _GUARD_BIT_IS_SET_POP_4_r10 853 -#define _GUARD_BIT_IS_SET_POP_4_r21 854 -#define _GUARD_BIT_IS_SET_POP_4_r32 855 -#define _GUARD_BIT_IS_SET_POP_5_r00 856 -#define _GUARD_BIT_IS_SET_POP_5_r10 857 -#define _GUARD_BIT_IS_SET_POP_5_r21 858 -#define _GUARD_BIT_IS_SET_POP_5_r32 859 -#define _GUARD_BIT_IS_SET_POP_6_r00 860 -#define _GUARD_BIT_IS_SET_POP_6_r10 861 -#define _GUARD_BIT_IS_SET_POP_6_r21 862 -#define _GUARD_BIT_IS_SET_POP_6_r32 863 -#define _GUARD_BIT_IS_SET_POP_7_r00 864 -#define _GUARD_BIT_IS_SET_POP_7_r10 865 -#define _GUARD_BIT_IS_SET_POP_7_r21 866 -#define _GUARD_BIT_IS_SET_POP_7_r32 867 -#define _GUARD_BIT_IS_UNSET_POP_r00 868 -#define _GUARD_BIT_IS_UNSET_POP_r10 869 -#define _GUARD_BIT_IS_UNSET_POP_r21 870 -#define _GUARD_BIT_IS_UNSET_POP_r32 871 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 872 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 873 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 874 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 875 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 876 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 877 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 878 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 879 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 880 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 881 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 882 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 883 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 884 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 885 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 886 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 887 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 888 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 889 -#define _GUARD_CALLABLE_BUILTIN_O_r00 890 -#define _GUARD_CALLABLE_ISINSTANCE_r03 891 -#define _GUARD_CALLABLE_ISINSTANCE_r13 892 -#define _GUARD_CALLABLE_ISINSTANCE_r23 893 -#define _GUARD_CALLABLE_ISINSTANCE_r33 894 -#define _GUARD_CALLABLE_LEN_r03 895 -#define _GUARD_CALLABLE_LEN_r13 896 -#define _GUARD_CALLABLE_LEN_r23 897 -#define _GUARD_CALLABLE_LEN_r33 898 -#define _GUARD_CALLABLE_LIST_APPEND_r03 899 -#define _GUARD_CALLABLE_LIST_APPEND_r13 900 -#define _GUARD_CALLABLE_LIST_APPEND_r23 901 -#define _GUARD_CALLABLE_LIST_APPEND_r33 902 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 903 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 904 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 905 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 906 -#define _GUARD_CALLABLE_STR_1_r03 907 -#define _GUARD_CALLABLE_STR_1_r13 908 -#define _GUARD_CALLABLE_STR_1_r23 909 -#define _GUARD_CALLABLE_STR_1_r33 910 -#define _GUARD_CALLABLE_TUPLE_1_r03 911 -#define _GUARD_CALLABLE_TUPLE_1_r13 912 -#define _GUARD_CALLABLE_TUPLE_1_r23 913 -#define _GUARD_CALLABLE_TUPLE_1_r33 914 -#define _GUARD_CALLABLE_TYPE_1_r03 915 -#define _GUARD_CALLABLE_TYPE_1_r13 916 -#define _GUARD_CALLABLE_TYPE_1_r23 917 -#define _GUARD_CALLABLE_TYPE_1_r33 918 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 919 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 920 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 921 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 922 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 923 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 924 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 925 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 926 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 927 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 928 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 929 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 930 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 931 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 932 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 933 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 934 -#define _GUARD_DORV_NO_DICT_r01 935 -#define _GUARD_DORV_NO_DICT_r11 936 -#define _GUARD_DORV_NO_DICT_r22 937 -#define _GUARD_DORV_NO_DICT_r33 938 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 939 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 940 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 941 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 942 -#define _GUARD_GLOBALS_VERSION_r00 943 -#define _GUARD_GLOBALS_VERSION_r11 944 -#define _GUARD_GLOBALS_VERSION_r22 945 -#define _GUARD_GLOBALS_VERSION_r33 946 -#define _GUARD_IP_RETURN_GENERATOR_r00 947 -#define _GUARD_IP_RETURN_GENERATOR_r11 948 -#define _GUARD_IP_RETURN_GENERATOR_r22 949 -#define _GUARD_IP_RETURN_GENERATOR_r33 950 -#define _GUARD_IP_RETURN_VALUE_r00 951 -#define _GUARD_IP_RETURN_VALUE_r11 952 -#define _GUARD_IP_RETURN_VALUE_r22 953 -#define _GUARD_IP_RETURN_VALUE_r33 954 -#define _GUARD_IP_YIELD_VALUE_r00 955 -#define _GUARD_IP_YIELD_VALUE_r11 956 -#define _GUARD_IP_YIELD_VALUE_r22 957 -#define _GUARD_IP_YIELD_VALUE_r33 958 -#define _GUARD_IP__PUSH_FRAME_r00 959 -#define _GUARD_IP__PUSH_FRAME_r11 960 -#define _GUARD_IP__PUSH_FRAME_r22 961 -#define _GUARD_IP__PUSH_FRAME_r33 962 -#define _GUARD_IS_FALSE_POP_r00 963 -#define _GUARD_IS_FALSE_POP_r10 964 -#define _GUARD_IS_FALSE_POP_r21 965 -#define _GUARD_IS_FALSE_POP_r32 966 -#define _GUARD_IS_NONE_POP_r00 967 -#define _GUARD_IS_NONE_POP_r10 968 -#define _GUARD_IS_NONE_POP_r21 969 -#define _GUARD_IS_NONE_POP_r32 970 -#define _GUARD_IS_NOT_NONE_POP_r10 971 -#define _GUARD_IS_TRUE_POP_r00 972 -#define _GUARD_IS_TRUE_POP_r10 973 -#define _GUARD_IS_TRUE_POP_r21 974 -#define _GUARD_IS_TRUE_POP_r32 975 -#define _GUARD_KEYS_VERSION_r01 976 -#define _GUARD_KEYS_VERSION_r11 977 -#define _GUARD_KEYS_VERSION_r22 978 -#define _GUARD_KEYS_VERSION_r33 979 -#define _GUARD_NOS_ANY_DICT_r02 980 -#define _GUARD_NOS_ANY_DICT_r12 981 -#define _GUARD_NOS_ANY_DICT_r22 982 -#define _GUARD_NOS_ANY_DICT_r33 983 -#define _GUARD_NOS_COMPACT_ASCII_r02 984 -#define _GUARD_NOS_COMPACT_ASCII_r12 985 -#define _GUARD_NOS_COMPACT_ASCII_r22 986 -#define _GUARD_NOS_COMPACT_ASCII_r33 987 -#define _GUARD_NOS_DICT_r02 988 -#define _GUARD_NOS_DICT_r12 989 -#define _GUARD_NOS_DICT_r22 990 -#define _GUARD_NOS_DICT_r33 991 -#define _GUARD_NOS_FLOAT_r02 992 -#define _GUARD_NOS_FLOAT_r12 993 -#define _GUARD_NOS_FLOAT_r22 994 -#define _GUARD_NOS_FLOAT_r33 995 -#define _GUARD_NOS_INT_r02 996 -#define _GUARD_NOS_INT_r12 997 -#define _GUARD_NOS_INT_r22 998 -#define _GUARD_NOS_INT_r33 999 -#define _GUARD_NOS_LIST_r02 1000 -#define _GUARD_NOS_LIST_r12 1001 -#define _GUARD_NOS_LIST_r22 1002 -#define _GUARD_NOS_LIST_r33 1003 -#define _GUARD_NOS_NOT_NULL_r02 1004 -#define _GUARD_NOS_NOT_NULL_r12 1005 -#define _GUARD_NOS_NOT_NULL_r22 1006 -#define _GUARD_NOS_NOT_NULL_r33 1007 -#define _GUARD_NOS_NULL_r02 1008 -#define _GUARD_NOS_NULL_r12 1009 -#define _GUARD_NOS_NULL_r22 1010 -#define _GUARD_NOS_NULL_r33 1011 -#define _GUARD_NOS_OVERFLOWED_r02 1012 -#define _GUARD_NOS_OVERFLOWED_r12 1013 -#define _GUARD_NOS_OVERFLOWED_r22 1014 -#define _GUARD_NOS_OVERFLOWED_r33 1015 -#define _GUARD_NOS_TUPLE_r02 1016 -#define _GUARD_NOS_TUPLE_r12 1017 -#define _GUARD_NOS_TUPLE_r22 1018 -#define _GUARD_NOS_TUPLE_r33 1019 -#define _GUARD_NOS_UNICODE_r02 1020 -#define _GUARD_NOS_UNICODE_r12 1021 -#define _GUARD_NOS_UNICODE_r22 1022 -#define _GUARD_NOS_UNICODE_r33 1023 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1024 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1025 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1026 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1027 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1028 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1029 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1030 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1031 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1032 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1033 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1034 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1035 -#define _GUARD_THIRD_NULL_r03 1036 -#define _GUARD_THIRD_NULL_r13 1037 -#define _GUARD_THIRD_NULL_r23 1038 -#define _GUARD_THIRD_NULL_r33 1039 -#define _GUARD_TOS_ANY_DICT_r01 1040 -#define _GUARD_TOS_ANY_DICT_r11 1041 -#define _GUARD_TOS_ANY_DICT_r22 1042 -#define _GUARD_TOS_ANY_DICT_r33 1043 -#define _GUARD_TOS_ANY_SET_r01 1044 -#define _GUARD_TOS_ANY_SET_r11 1045 -#define _GUARD_TOS_ANY_SET_r22 1046 -#define _GUARD_TOS_ANY_SET_r33 1047 -#define _GUARD_TOS_DICT_r01 1048 -#define _GUARD_TOS_DICT_r11 1049 -#define _GUARD_TOS_DICT_r22 1050 -#define _GUARD_TOS_DICT_r33 1051 -#define _GUARD_TOS_FLOAT_r01 1052 -#define _GUARD_TOS_FLOAT_r11 1053 -#define _GUARD_TOS_FLOAT_r22 1054 -#define _GUARD_TOS_FLOAT_r33 1055 -#define _GUARD_TOS_FROZENDICT_r01 1056 -#define _GUARD_TOS_FROZENDICT_r11 1057 -#define _GUARD_TOS_FROZENDICT_r22 1058 -#define _GUARD_TOS_FROZENDICT_r33 1059 -#define _GUARD_TOS_FROZENSET_r01 1060 -#define _GUARD_TOS_FROZENSET_r11 1061 -#define _GUARD_TOS_FROZENSET_r22 1062 -#define _GUARD_TOS_FROZENSET_r33 1063 -#define _GUARD_TOS_INT_r01 1064 -#define _GUARD_TOS_INT_r11 1065 -#define _GUARD_TOS_INT_r22 1066 -#define _GUARD_TOS_INT_r33 1067 -#define _GUARD_TOS_LIST_r01 1068 -#define _GUARD_TOS_LIST_r11 1069 -#define _GUARD_TOS_LIST_r22 1070 -#define _GUARD_TOS_LIST_r33 1071 -#define _GUARD_TOS_OVERFLOWED_r01 1072 -#define _GUARD_TOS_OVERFLOWED_r11 1073 -#define _GUARD_TOS_OVERFLOWED_r22 1074 -#define _GUARD_TOS_OVERFLOWED_r33 1075 -#define _GUARD_TOS_SET_r01 1076 -#define _GUARD_TOS_SET_r11 1077 -#define _GUARD_TOS_SET_r22 1078 -#define _GUARD_TOS_SET_r33 1079 -#define _GUARD_TOS_SLICE_r01 1080 -#define _GUARD_TOS_SLICE_r11 1081 -#define _GUARD_TOS_SLICE_r22 1082 -#define _GUARD_TOS_SLICE_r33 1083 -#define _GUARD_TOS_TUPLE_r01 1084 -#define _GUARD_TOS_TUPLE_r11 1085 -#define _GUARD_TOS_TUPLE_r22 1086 -#define _GUARD_TOS_TUPLE_r33 1087 -#define _GUARD_TOS_UNICODE_r01 1088 -#define _GUARD_TOS_UNICODE_r11 1089 -#define _GUARD_TOS_UNICODE_r22 1090 -#define _GUARD_TOS_UNICODE_r33 1091 -#define _GUARD_TYPE_VERSION_r01 1092 -#define _GUARD_TYPE_VERSION_r11 1093 -#define _GUARD_TYPE_VERSION_r22 1094 -#define _GUARD_TYPE_VERSION_r33 1095 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1096 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1097 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1098 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1099 -#define _HANDLE_PENDING_AND_DEOPT_r00 1100 -#define _HANDLE_PENDING_AND_DEOPT_r10 1101 -#define _HANDLE_PENDING_AND_DEOPT_r20 1102 -#define _HANDLE_PENDING_AND_DEOPT_r30 1103 -#define _IMPORT_FROM_r12 1104 -#define _IMPORT_NAME_r21 1105 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1106 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1107 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1108 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1109 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1110 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1111 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1112 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1113 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1114 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1115 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1116 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1117 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1118 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1119 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1120 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1121 -#define _INSERT_NULL_r10 1122 -#define _INSTRUMENTED_FOR_ITER_r23 1123 -#define _INSTRUMENTED_INSTRUCTION_r00 1124 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1125 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1126 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1127 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1128 -#define _INSTRUMENTED_LINE_r00 1129 -#define _INSTRUMENTED_NOT_TAKEN_r00 1130 -#define _INSTRUMENTED_NOT_TAKEN_r11 1131 -#define _INSTRUMENTED_NOT_TAKEN_r22 1132 -#define _INSTRUMENTED_NOT_TAKEN_r33 1133 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1134 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1135 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1136 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1137 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1138 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1139 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1140 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1141 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1142 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1143 -#define _IS_NONE_r11 1144 -#define _IS_OP_r03 1145 -#define _IS_OP_r13 1146 -#define _IS_OP_r23 1147 -#define _ITER_CHECK_LIST_r02 1148 -#define _ITER_CHECK_LIST_r12 1149 -#define _ITER_CHECK_LIST_r22 1150 -#define _ITER_CHECK_LIST_r33 1151 -#define _ITER_CHECK_RANGE_r02 1152 -#define _ITER_CHECK_RANGE_r12 1153 -#define _ITER_CHECK_RANGE_r22 1154 -#define _ITER_CHECK_RANGE_r33 1155 -#define _ITER_CHECK_TUPLE_r02 1156 -#define _ITER_CHECK_TUPLE_r12 1157 -#define _ITER_CHECK_TUPLE_r22 1158 -#define _ITER_CHECK_TUPLE_r33 1159 -#define _ITER_JUMP_LIST_r02 1160 -#define _ITER_JUMP_LIST_r12 1161 -#define _ITER_JUMP_LIST_r22 1162 -#define _ITER_JUMP_LIST_r33 1163 -#define _ITER_JUMP_RANGE_r02 1164 -#define _ITER_JUMP_RANGE_r12 1165 -#define _ITER_JUMP_RANGE_r22 1166 -#define _ITER_JUMP_RANGE_r33 1167 -#define _ITER_JUMP_TUPLE_r02 1168 -#define _ITER_JUMP_TUPLE_r12 1169 -#define _ITER_JUMP_TUPLE_r22 1170 -#define _ITER_JUMP_TUPLE_r33 1171 -#define _ITER_NEXT_LIST_r23 1172 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1173 -#define _ITER_NEXT_RANGE_r03 1174 -#define _ITER_NEXT_RANGE_r13 1175 -#define _ITER_NEXT_RANGE_r23 1176 -#define _ITER_NEXT_TUPLE_r03 1177 -#define _ITER_NEXT_TUPLE_r13 1178 -#define _ITER_NEXT_TUPLE_r23 1179 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1180 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1181 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1182 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1183 -#define _JUMP_TO_TOP_r00 1184 -#define _LIST_APPEND_r10 1185 -#define _LIST_EXTEND_r11 1186 -#define _LOAD_ATTR_r10 1187 -#define _LOAD_ATTR_CLASS_r11 1188 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1189 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1190 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1191 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1192 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1193 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1194 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1195 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1196 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1197 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1198 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1199 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1200 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1201 -#define _LOAD_ATTR_MODULE_r12 1202 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1203 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1204 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1205 -#define _LOAD_ATTR_SLOT_r02 1206 -#define _LOAD_ATTR_SLOT_r12 1207 -#define _LOAD_ATTR_SLOT_r23 1208 -#define _LOAD_ATTR_WITH_HINT_r12 1209 -#define _LOAD_BUILD_CLASS_r01 1210 -#define _LOAD_BYTECODE_r00 1211 -#define _LOAD_COMMON_CONSTANT_r01 1212 -#define _LOAD_COMMON_CONSTANT_r12 1213 -#define _LOAD_COMMON_CONSTANT_r23 1214 -#define _LOAD_CONST_r01 1215 -#define _LOAD_CONST_r12 1216 -#define _LOAD_CONST_r23 1217 -#define _LOAD_CONST_INLINE_r01 1218 -#define _LOAD_CONST_INLINE_r12 1219 -#define _LOAD_CONST_INLINE_r23 1220 -#define _LOAD_CONST_INLINE_BORROW_r01 1221 -#define _LOAD_CONST_INLINE_BORROW_r12 1222 -#define _LOAD_CONST_INLINE_BORROW_r23 1223 -#define _LOAD_CONST_UNDER_INLINE_r02 1224 -#define _LOAD_CONST_UNDER_INLINE_r12 1225 -#define _LOAD_CONST_UNDER_INLINE_r23 1226 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1227 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1228 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1229 -#define _LOAD_DEREF_r01 1230 -#define _LOAD_FAST_r01 1231 -#define _LOAD_FAST_r12 1232 -#define _LOAD_FAST_r23 1233 -#define _LOAD_FAST_0_r01 1234 -#define _LOAD_FAST_0_r12 1235 -#define _LOAD_FAST_0_r23 1236 -#define _LOAD_FAST_1_r01 1237 -#define _LOAD_FAST_1_r12 1238 -#define _LOAD_FAST_1_r23 1239 -#define _LOAD_FAST_2_r01 1240 -#define _LOAD_FAST_2_r12 1241 -#define _LOAD_FAST_2_r23 1242 -#define _LOAD_FAST_3_r01 1243 -#define _LOAD_FAST_3_r12 1244 -#define _LOAD_FAST_3_r23 1245 -#define _LOAD_FAST_4_r01 1246 -#define _LOAD_FAST_4_r12 1247 -#define _LOAD_FAST_4_r23 1248 -#define _LOAD_FAST_5_r01 1249 -#define _LOAD_FAST_5_r12 1250 -#define _LOAD_FAST_5_r23 1251 -#define _LOAD_FAST_6_r01 1252 -#define _LOAD_FAST_6_r12 1253 -#define _LOAD_FAST_6_r23 1254 -#define _LOAD_FAST_7_r01 1255 -#define _LOAD_FAST_7_r12 1256 -#define _LOAD_FAST_7_r23 1257 -#define _LOAD_FAST_AND_CLEAR_r01 1258 -#define _LOAD_FAST_AND_CLEAR_r12 1259 -#define _LOAD_FAST_AND_CLEAR_r23 1260 -#define _LOAD_FAST_BORROW_r01 1261 -#define _LOAD_FAST_BORROW_r12 1262 -#define _LOAD_FAST_BORROW_r23 1263 -#define _LOAD_FAST_BORROW_0_r01 1264 -#define _LOAD_FAST_BORROW_0_r12 1265 -#define _LOAD_FAST_BORROW_0_r23 1266 -#define _LOAD_FAST_BORROW_1_r01 1267 -#define _LOAD_FAST_BORROW_1_r12 1268 -#define _LOAD_FAST_BORROW_1_r23 1269 -#define _LOAD_FAST_BORROW_2_r01 1270 -#define _LOAD_FAST_BORROW_2_r12 1271 -#define _LOAD_FAST_BORROW_2_r23 1272 -#define _LOAD_FAST_BORROW_3_r01 1273 -#define _LOAD_FAST_BORROW_3_r12 1274 -#define _LOAD_FAST_BORROW_3_r23 1275 -#define _LOAD_FAST_BORROW_4_r01 1276 -#define _LOAD_FAST_BORROW_4_r12 1277 -#define _LOAD_FAST_BORROW_4_r23 1278 -#define _LOAD_FAST_BORROW_5_r01 1279 -#define _LOAD_FAST_BORROW_5_r12 1280 -#define _LOAD_FAST_BORROW_5_r23 1281 -#define _LOAD_FAST_BORROW_6_r01 1282 -#define _LOAD_FAST_BORROW_6_r12 1283 -#define _LOAD_FAST_BORROW_6_r23 1284 -#define _LOAD_FAST_BORROW_7_r01 1285 -#define _LOAD_FAST_BORROW_7_r12 1286 -#define _LOAD_FAST_BORROW_7_r23 1287 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1288 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1289 -#define _LOAD_FAST_CHECK_r01 1290 -#define _LOAD_FAST_CHECK_r12 1291 -#define _LOAD_FAST_CHECK_r23 1292 -#define _LOAD_FAST_LOAD_FAST_r02 1293 -#define _LOAD_FAST_LOAD_FAST_r13 1294 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1295 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1296 -#define _LOAD_GLOBAL_r00 1297 -#define _LOAD_GLOBAL_BUILTINS_r01 1298 -#define _LOAD_GLOBAL_MODULE_r01 1299 -#define _LOAD_LOCALS_r01 1300 -#define _LOAD_LOCALS_r12 1301 -#define _LOAD_LOCALS_r23 1302 -#define _LOAD_NAME_r01 1303 -#define _LOAD_SMALL_INT_r01 1304 -#define _LOAD_SMALL_INT_r12 1305 -#define _LOAD_SMALL_INT_r23 1306 -#define _LOAD_SMALL_INT_0_r01 1307 -#define _LOAD_SMALL_INT_0_r12 1308 -#define _LOAD_SMALL_INT_0_r23 1309 -#define _LOAD_SMALL_INT_1_r01 1310 -#define _LOAD_SMALL_INT_1_r12 1311 -#define _LOAD_SMALL_INT_1_r23 1312 -#define _LOAD_SMALL_INT_2_r01 1313 -#define _LOAD_SMALL_INT_2_r12 1314 -#define _LOAD_SMALL_INT_2_r23 1315 -#define _LOAD_SMALL_INT_3_r01 1316 -#define _LOAD_SMALL_INT_3_r12 1317 -#define _LOAD_SMALL_INT_3_r23 1318 -#define _LOAD_SPECIAL_r00 1319 -#define _LOAD_SUPER_ATTR_ATTR_r31 1320 -#define _LOAD_SUPER_ATTR_METHOD_r32 1321 -#define _LOCK_OBJECT_r01 1322 -#define _LOCK_OBJECT_r11 1323 -#define _LOCK_OBJECT_r22 1324 -#define _LOCK_OBJECT_r33 1325 -#define _MAKE_CALLARGS_A_TUPLE_r33 1326 -#define _MAKE_CELL_r00 1327 -#define _MAKE_FUNCTION_r11 1328 -#define _MAKE_HEAP_SAFE_r01 1329 -#define _MAKE_HEAP_SAFE_r11 1330 -#define _MAKE_HEAP_SAFE_r22 1331 -#define _MAKE_HEAP_SAFE_r33 1332 -#define _MAKE_WARM_r00 1333 -#define _MAKE_WARM_r11 1334 -#define _MAKE_WARM_r22 1335 -#define _MAKE_WARM_r33 1336 -#define _MAP_ADD_r20 1337 -#define _MATCH_CLASS_r33 1338 -#define _MATCH_KEYS_r23 1339 -#define _MATCH_MAPPING_r02 1340 -#define _MATCH_MAPPING_r12 1341 -#define _MATCH_MAPPING_r23 1342 -#define _MATCH_SEQUENCE_r02 1343 -#define _MATCH_SEQUENCE_r12 1344 -#define _MATCH_SEQUENCE_r23 1345 -#define _MAYBE_EXPAND_METHOD_r00 1346 -#define _MAYBE_EXPAND_METHOD_KW_r11 1347 -#define _MONITOR_CALL_r00 1348 -#define _MONITOR_CALL_KW_r11 1349 -#define _MONITOR_JUMP_BACKWARD_r00 1350 -#define _MONITOR_JUMP_BACKWARD_r11 1351 -#define _MONITOR_JUMP_BACKWARD_r22 1352 -#define _MONITOR_JUMP_BACKWARD_r33 1353 -#define _MONITOR_RESUME_r00 1354 -#define _NOP_r00 1355 -#define _NOP_r11 1356 -#define _NOP_r22 1357 -#define _NOP_r33 1358 -#define _POP_CALL_r20 1359 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1360 -#define _POP_CALL_ONE_r30 1361 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1362 -#define _POP_CALL_TWO_r30 1363 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1364 -#define _POP_EXCEPT_r10 1365 -#define _POP_ITER_r20 1366 -#define _POP_JUMP_IF_FALSE_r00 1367 -#define _POP_JUMP_IF_FALSE_r10 1368 -#define _POP_JUMP_IF_FALSE_r21 1369 -#define _POP_JUMP_IF_FALSE_r32 1370 -#define _POP_JUMP_IF_TRUE_r00 1371 -#define _POP_JUMP_IF_TRUE_r10 1372 -#define _POP_JUMP_IF_TRUE_r21 1373 -#define _POP_JUMP_IF_TRUE_r32 1374 -#define _POP_TOP_r10 1375 -#define _POP_TOP_FLOAT_r00 1376 -#define _POP_TOP_FLOAT_r10 1377 -#define _POP_TOP_FLOAT_r21 1378 -#define _POP_TOP_FLOAT_r32 1379 -#define _POP_TOP_INT_r00 1380 -#define _POP_TOP_INT_r10 1381 -#define _POP_TOP_INT_r21 1382 -#define _POP_TOP_INT_r32 1383 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1384 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1385 -#define _POP_TOP_NOP_r00 1386 -#define _POP_TOP_NOP_r10 1387 -#define _POP_TOP_NOP_r21 1388 -#define _POP_TOP_NOP_r32 1389 -#define _POP_TOP_UNICODE_r00 1390 -#define _POP_TOP_UNICODE_r10 1391 -#define _POP_TOP_UNICODE_r21 1392 -#define _POP_TOP_UNICODE_r32 1393 -#define _POP_TWO_r20 1394 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1395 -#define _PUSH_EXC_INFO_r02 1396 -#define _PUSH_EXC_INFO_r12 1397 -#define _PUSH_EXC_INFO_r23 1398 -#define _PUSH_FRAME_r10 1399 -#define _PUSH_NULL_r01 1400 -#define _PUSH_NULL_r12 1401 -#define _PUSH_NULL_r23 1402 -#define _PUSH_NULL_CONDITIONAL_r00 1403 -#define _PY_FRAME_EX_r31 1404 -#define _PY_FRAME_GENERAL_r01 1405 -#define _PY_FRAME_KW_r11 1406 -#define _REPLACE_WITH_TRUE_r02 1407 -#define _REPLACE_WITH_TRUE_r12 1408 -#define _REPLACE_WITH_TRUE_r23 1409 -#define _RESUME_CHECK_r00 1410 -#define _RESUME_CHECK_r11 1411 -#define _RESUME_CHECK_r22 1412 -#define _RESUME_CHECK_r33 1413 -#define _RETURN_GENERATOR_r01 1414 -#define _RETURN_VALUE_r11 1415 -#define _SAVE_RETURN_OFFSET_r00 1416 -#define _SAVE_RETURN_OFFSET_r11 1417 -#define _SAVE_RETURN_OFFSET_r22 1418 -#define _SAVE_RETURN_OFFSET_r33 1419 -#define _SEND_r33 1420 -#define _SEND_GEN_FRAME_r33 1421 -#define _SETUP_ANNOTATIONS_r00 1422 -#define _SET_ADD_r10 1423 -#define _SET_FUNCTION_ATTRIBUTE_r01 1424 -#define _SET_FUNCTION_ATTRIBUTE_r11 1425 -#define _SET_FUNCTION_ATTRIBUTE_r21 1426 -#define _SET_FUNCTION_ATTRIBUTE_r32 1427 -#define _SET_IP_r00 1428 -#define _SET_IP_r11 1429 -#define _SET_IP_r22 1430 -#define _SET_IP_r33 1431 -#define _SET_UPDATE_r11 1432 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1433 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1434 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1435 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1436 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1437 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1438 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1439 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1440 -#define _SPILL_OR_RELOAD_r01 1441 -#define _SPILL_OR_RELOAD_r02 1442 -#define _SPILL_OR_RELOAD_r03 1443 -#define _SPILL_OR_RELOAD_r10 1444 -#define _SPILL_OR_RELOAD_r12 1445 -#define _SPILL_OR_RELOAD_r13 1446 -#define _SPILL_OR_RELOAD_r20 1447 -#define _SPILL_OR_RELOAD_r21 1448 -#define _SPILL_OR_RELOAD_r23 1449 -#define _SPILL_OR_RELOAD_r30 1450 -#define _SPILL_OR_RELOAD_r31 1451 -#define _SPILL_OR_RELOAD_r32 1452 -#define _START_EXECUTOR_r00 1453 -#define _STORE_ATTR_r20 1454 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1455 -#define _STORE_ATTR_SLOT_r21 1456 -#define _STORE_ATTR_WITH_HINT_r21 1457 -#define _STORE_DEREF_r10 1458 -#define _STORE_FAST_LOAD_FAST_r11 1459 -#define _STORE_FAST_STORE_FAST_r20 1460 -#define _STORE_GLOBAL_r10 1461 -#define _STORE_NAME_r10 1462 -#define _STORE_SLICE_r30 1463 -#define _STORE_SUBSCR_r30 1464 -#define _STORE_SUBSCR_DICT_r31 1465 -#define _STORE_SUBSCR_LIST_INT_r32 1466 -#define _SWAP_r11 1467 -#define _SWAP_2_r02 1468 -#define _SWAP_2_r12 1469 -#define _SWAP_2_r22 1470 -#define _SWAP_2_r33 1471 -#define _SWAP_3_r03 1472 -#define _SWAP_3_r13 1473 -#define _SWAP_3_r23 1474 -#define _SWAP_3_r33 1475 -#define _SWAP_FAST_r01 1476 -#define _SWAP_FAST_r11 1477 -#define _SWAP_FAST_r22 1478 -#define _SWAP_FAST_r33 1479 -#define _SWAP_FAST_0_r01 1480 -#define _SWAP_FAST_0_r11 1481 -#define _SWAP_FAST_0_r22 1482 -#define _SWAP_FAST_0_r33 1483 -#define _SWAP_FAST_1_r01 1484 -#define _SWAP_FAST_1_r11 1485 -#define _SWAP_FAST_1_r22 1486 -#define _SWAP_FAST_1_r33 1487 -#define _SWAP_FAST_2_r01 1488 -#define _SWAP_FAST_2_r11 1489 -#define _SWAP_FAST_2_r22 1490 -#define _SWAP_FAST_2_r33 1491 -#define _SWAP_FAST_3_r01 1492 -#define _SWAP_FAST_3_r11 1493 -#define _SWAP_FAST_3_r22 1494 -#define _SWAP_FAST_3_r33 1495 -#define _SWAP_FAST_4_r01 1496 -#define _SWAP_FAST_4_r11 1497 -#define _SWAP_FAST_4_r22 1498 -#define _SWAP_FAST_4_r33 1499 -#define _SWAP_FAST_5_r01 1500 -#define _SWAP_FAST_5_r11 1501 -#define _SWAP_FAST_5_r22 1502 -#define _SWAP_FAST_5_r33 1503 -#define _SWAP_FAST_6_r01 1504 -#define _SWAP_FAST_6_r11 1505 -#define _SWAP_FAST_6_r22 1506 -#define _SWAP_FAST_6_r33 1507 -#define _SWAP_FAST_7_r01 1508 -#define _SWAP_FAST_7_r11 1509 -#define _SWAP_FAST_7_r22 1510 -#define _SWAP_FAST_7_r33 1511 -#define _TIER2_RESUME_CHECK_r00 1512 -#define _TIER2_RESUME_CHECK_r11 1513 -#define _TIER2_RESUME_CHECK_r22 1514 -#define _TIER2_RESUME_CHECK_r33 1515 -#define _TO_BOOL_r11 1516 -#define _TO_BOOL_BOOL_r01 1517 -#define _TO_BOOL_BOOL_r11 1518 -#define _TO_BOOL_BOOL_r22 1519 -#define _TO_BOOL_BOOL_r33 1520 -#define _TO_BOOL_INT_r02 1521 -#define _TO_BOOL_INT_r12 1522 -#define _TO_BOOL_INT_r23 1523 -#define _TO_BOOL_LIST_r02 1524 -#define _TO_BOOL_LIST_r12 1525 -#define _TO_BOOL_LIST_r23 1526 -#define _TO_BOOL_NONE_r01 1527 -#define _TO_BOOL_NONE_r11 1528 -#define _TO_BOOL_NONE_r22 1529 -#define _TO_BOOL_NONE_r33 1530 -#define _TO_BOOL_STR_r02 1531 -#define _TO_BOOL_STR_r12 1532 -#define _TO_BOOL_STR_r23 1533 -#define _TRACE_RECORD_r00 1534 -#define _UNARY_INVERT_r12 1535 -#define _UNARY_NEGATIVE_r12 1536 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1537 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1538 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1539 -#define _UNARY_NOT_r01 1540 -#define _UNARY_NOT_r11 1541 -#define _UNARY_NOT_r22 1542 -#define _UNARY_NOT_r33 1543 -#define _UNPACK_EX_r10 1544 -#define _UNPACK_SEQUENCE_r10 1545 -#define _UNPACK_SEQUENCE_LIST_r10 1546 -#define _UNPACK_SEQUENCE_TUPLE_r10 1547 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1548 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1549 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1550 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1551 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1552 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1553 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1554 -#define _WITH_EXCEPT_START_r33 1555 -#define _YIELD_VALUE_r11 1556 -#define MAX_UOP_REGS_ID 1556 +#define _YIELD_VALUE 627 +#define MAX_UOP_ID 627 +#define _BINARY_OP_r23 628 +#define _BINARY_OP_ADD_FLOAT_r03 629 +#define _BINARY_OP_ADD_FLOAT_r13 630 +#define _BINARY_OP_ADD_FLOAT_r23 631 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 632 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 633 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 634 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 635 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 636 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 637 +#define _BINARY_OP_ADD_INT_r03 638 +#define _BINARY_OP_ADD_INT_r13 639 +#define _BINARY_OP_ADD_INT_r23 640 +#define _BINARY_OP_ADD_UNICODE_r03 641 +#define _BINARY_OP_ADD_UNICODE_r13 642 +#define _BINARY_OP_ADD_UNICODE_r23 643 +#define _BINARY_OP_EXTEND_r23 644 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 645 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 646 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 647 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 648 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 649 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 650 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 651 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 652 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 653 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 654 +#define _BINARY_OP_MULTIPLY_INT_r03 655 +#define _BINARY_OP_MULTIPLY_INT_r13 656 +#define _BINARY_OP_MULTIPLY_INT_r23 657 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 658 +#define _BINARY_OP_SUBSCR_DICT_r23 659 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 660 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 661 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 662 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 663 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 664 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 665 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 666 +#define _BINARY_OP_SUBSCR_STR_INT_r23 667 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 668 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 669 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 670 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 671 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 672 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 673 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 674 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 675 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 676 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 677 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 678 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 679 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 680 +#define _BINARY_OP_SUBTRACT_INT_r03 681 +#define _BINARY_OP_SUBTRACT_INT_r13 682 +#define _BINARY_OP_SUBTRACT_INT_r23 683 +#define _BINARY_SLICE_r31 684 +#define _BUILD_INTERPOLATION_r01 685 +#define _BUILD_LIST_r01 686 +#define _BUILD_MAP_r01 687 +#define _BUILD_SET_r01 688 +#define _BUILD_SLICE_r01 689 +#define _BUILD_STRING_r01 690 +#define _BUILD_TEMPLATE_r21 691 +#define _BUILD_TUPLE_r01 692 +#define _CALL_BUILTIN_CLASS_r01 693 +#define _CALL_BUILTIN_FAST_r01 694 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 695 +#define _CALL_BUILTIN_O_r03 696 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 697 +#define _CALL_INTRINSIC_1_r12 698 +#define _CALL_INTRINSIC_2_r23 699 +#define _CALL_ISINSTANCE_r31 700 +#define _CALL_KW_NON_PY_r11 701 +#define _CALL_LEN_r33 702 +#define _CALL_LIST_APPEND_r03 703 +#define _CALL_LIST_APPEND_r13 704 +#define _CALL_LIST_APPEND_r23 705 +#define _CALL_LIST_APPEND_r33 706 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 707 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 708 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 709 +#define _CALL_METHOD_DESCRIPTOR_O_r03 710 +#define _CALL_NON_PY_GENERAL_r01 711 +#define _CALL_STR_1_r32 712 +#define _CALL_TUPLE_1_r32 713 +#define _CALL_TYPE_1_r02 714 +#define _CALL_TYPE_1_r12 715 +#define _CALL_TYPE_1_r22 716 +#define _CALL_TYPE_1_r32 717 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 718 +#define _CHECK_ATTR_CLASS_r01 719 +#define _CHECK_ATTR_CLASS_r11 720 +#define _CHECK_ATTR_CLASS_r22 721 +#define _CHECK_ATTR_CLASS_r33 722 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 723 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 724 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 725 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 726 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 727 +#define _CHECK_EG_MATCH_r22 728 +#define _CHECK_EXC_MATCH_r22 729 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 730 +#define _CHECK_FUNCTION_VERSION_r00 731 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 732 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 733 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 734 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 735 +#define _CHECK_FUNCTION_VERSION_KW_r11 736 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 737 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 738 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 739 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 740 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 741 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 742 +#define _CHECK_IS_PY_CALLABLE_EX_r03 743 +#define _CHECK_IS_PY_CALLABLE_EX_r13 744 +#define _CHECK_IS_PY_CALLABLE_EX_r23 745 +#define _CHECK_IS_PY_CALLABLE_EX_r33 746 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 747 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 748 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 749 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 750 +#define _CHECK_METHOD_VERSION_r00 751 +#define _CHECK_METHOD_VERSION_KW_r11 752 +#define _CHECK_PEP_523_r00 753 +#define _CHECK_PEP_523_r11 754 +#define _CHECK_PEP_523_r22 755 +#define _CHECK_PEP_523_r33 756 +#define _CHECK_PERIODIC_r00 757 +#define _CHECK_PERIODIC_AT_END_r00 758 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 759 +#define _CHECK_RECURSION_REMAINING_r00 760 +#define _CHECK_RECURSION_REMAINING_r11 761 +#define _CHECK_RECURSION_REMAINING_r22 762 +#define _CHECK_RECURSION_REMAINING_r33 763 +#define _CHECK_STACK_SPACE_r00 764 +#define _CHECK_STACK_SPACE_OPERAND_r00 765 +#define _CHECK_STACK_SPACE_OPERAND_r11 766 +#define _CHECK_STACK_SPACE_OPERAND_r22 767 +#define _CHECK_STACK_SPACE_OPERAND_r33 768 +#define _CHECK_VALIDITY_r00 769 +#define _CHECK_VALIDITY_r11 770 +#define _CHECK_VALIDITY_r22 771 +#define _CHECK_VALIDITY_r33 772 +#define _COLD_DYNAMIC_EXIT_r00 773 +#define _COLD_EXIT_r00 774 +#define _COMPARE_OP_r21 775 +#define _COMPARE_OP_FLOAT_r03 776 +#define _COMPARE_OP_FLOAT_r13 777 +#define _COMPARE_OP_FLOAT_r23 778 +#define _COMPARE_OP_INT_r23 779 +#define _COMPARE_OP_STR_r23 780 +#define _CONTAINS_OP_r23 781 +#define _CONTAINS_OP_DICT_r23 782 +#define _CONTAINS_OP_SET_r23 783 +#define _CONVERT_VALUE_r11 784 +#define _COPY_r01 785 +#define _COPY_1_r02 786 +#define _COPY_1_r12 787 +#define _COPY_1_r23 788 +#define _COPY_2_r03 789 +#define _COPY_2_r13 790 +#define _COPY_2_r23 791 +#define _COPY_3_r03 792 +#define _COPY_3_r13 793 +#define _COPY_3_r23 794 +#define _COPY_3_r33 795 +#define _COPY_FREE_VARS_r00 796 +#define _COPY_FREE_VARS_r11 797 +#define _COPY_FREE_VARS_r22 798 +#define _COPY_FREE_VARS_r33 799 +#define _CREATE_INIT_FRAME_r01 800 +#define _DELETE_ATTR_r10 801 +#define _DELETE_DEREF_r00 802 +#define _DELETE_FAST_r00 803 +#define _DELETE_GLOBAL_r00 804 +#define _DELETE_NAME_r00 805 +#define _DELETE_SUBSCR_r20 806 +#define _DEOPT_r00 807 +#define _DEOPT_r10 808 +#define _DEOPT_r20 809 +#define _DEOPT_r30 810 +#define _DICT_MERGE_r11 811 +#define _DICT_UPDATE_r11 812 +#define _DO_CALL_r01 813 +#define _DO_CALL_FUNCTION_EX_r31 814 +#define _DO_CALL_KW_r11 815 +#define _DYNAMIC_EXIT_r00 816 +#define _DYNAMIC_EXIT_r10 817 +#define _DYNAMIC_EXIT_r20 818 +#define _DYNAMIC_EXIT_r30 819 +#define _END_FOR_r10 820 +#define _END_SEND_r31 821 +#define _ERROR_POP_N_r00 822 +#define _EXIT_INIT_CHECK_r10 823 +#define _EXIT_TRACE_r00 824 +#define _EXIT_TRACE_r10 825 +#define _EXIT_TRACE_r20 826 +#define _EXIT_TRACE_r30 827 +#define _EXPAND_METHOD_r00 828 +#define _EXPAND_METHOD_KW_r11 829 +#define _FATAL_ERROR_r00 830 +#define _FATAL_ERROR_r11 831 +#define _FATAL_ERROR_r22 832 +#define _FATAL_ERROR_r33 833 +#define _FORMAT_SIMPLE_r11 834 +#define _FORMAT_WITH_SPEC_r21 835 +#define _FOR_ITER_r23 836 +#define _FOR_ITER_GEN_FRAME_r03 837 +#define _FOR_ITER_GEN_FRAME_r13 838 +#define _FOR_ITER_GEN_FRAME_r23 839 +#define _FOR_ITER_TIER_TWO_r23 840 +#define _GET_AITER_r11 841 +#define _GET_ANEXT_r12 842 +#define _GET_AWAITABLE_r11 843 +#define _GET_ITER_r12 844 +#define _GET_LEN_r12 845 +#define _GUARD_BINARY_OP_EXTEND_r22 846 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 847 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 848 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 849 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 850 +#define _GUARD_BIT_IS_SET_POP_r00 851 +#define _GUARD_BIT_IS_SET_POP_r10 852 +#define _GUARD_BIT_IS_SET_POP_r21 853 +#define _GUARD_BIT_IS_SET_POP_r32 854 +#define _GUARD_BIT_IS_SET_POP_4_r00 855 +#define _GUARD_BIT_IS_SET_POP_4_r10 856 +#define _GUARD_BIT_IS_SET_POP_4_r21 857 +#define _GUARD_BIT_IS_SET_POP_4_r32 858 +#define _GUARD_BIT_IS_SET_POP_5_r00 859 +#define _GUARD_BIT_IS_SET_POP_5_r10 860 +#define _GUARD_BIT_IS_SET_POP_5_r21 861 +#define _GUARD_BIT_IS_SET_POP_5_r32 862 +#define _GUARD_BIT_IS_SET_POP_6_r00 863 +#define _GUARD_BIT_IS_SET_POP_6_r10 864 +#define _GUARD_BIT_IS_SET_POP_6_r21 865 +#define _GUARD_BIT_IS_SET_POP_6_r32 866 +#define _GUARD_BIT_IS_SET_POP_7_r00 867 +#define _GUARD_BIT_IS_SET_POP_7_r10 868 +#define _GUARD_BIT_IS_SET_POP_7_r21 869 +#define _GUARD_BIT_IS_SET_POP_7_r32 870 +#define _GUARD_BIT_IS_UNSET_POP_r00 871 +#define _GUARD_BIT_IS_UNSET_POP_r10 872 +#define _GUARD_BIT_IS_UNSET_POP_r21 873 +#define _GUARD_BIT_IS_UNSET_POP_r32 874 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 875 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 876 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 877 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 878 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 879 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 880 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 881 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 882 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 883 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 884 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 885 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 886 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 887 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 888 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 889 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 890 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 891 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 892 +#define _GUARD_CALLABLE_BUILTIN_O_r00 893 +#define _GUARD_CALLABLE_ISINSTANCE_r03 894 +#define _GUARD_CALLABLE_ISINSTANCE_r13 895 +#define _GUARD_CALLABLE_ISINSTANCE_r23 896 +#define _GUARD_CALLABLE_ISINSTANCE_r33 897 +#define _GUARD_CALLABLE_LEN_r03 898 +#define _GUARD_CALLABLE_LEN_r13 899 +#define _GUARD_CALLABLE_LEN_r23 900 +#define _GUARD_CALLABLE_LEN_r33 901 +#define _GUARD_CALLABLE_LIST_APPEND_r03 902 +#define _GUARD_CALLABLE_LIST_APPEND_r13 903 +#define _GUARD_CALLABLE_LIST_APPEND_r23 904 +#define _GUARD_CALLABLE_LIST_APPEND_r33 905 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 906 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 907 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 908 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 909 +#define _GUARD_CALLABLE_STR_1_r03 910 +#define _GUARD_CALLABLE_STR_1_r13 911 +#define _GUARD_CALLABLE_STR_1_r23 912 +#define _GUARD_CALLABLE_STR_1_r33 913 +#define _GUARD_CALLABLE_TUPLE_1_r03 914 +#define _GUARD_CALLABLE_TUPLE_1_r13 915 +#define _GUARD_CALLABLE_TUPLE_1_r23 916 +#define _GUARD_CALLABLE_TUPLE_1_r33 917 +#define _GUARD_CALLABLE_TYPE_1_r03 918 +#define _GUARD_CALLABLE_TYPE_1_r13 919 +#define _GUARD_CALLABLE_TYPE_1_r23 920 +#define _GUARD_CALLABLE_TYPE_1_r33 921 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 922 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 923 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 924 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 925 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 926 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 927 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 928 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 929 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 930 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 931 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 932 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 933 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 934 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 935 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 936 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 937 +#define _GUARD_DORV_NO_DICT_r01 938 +#define _GUARD_DORV_NO_DICT_r11 939 +#define _GUARD_DORV_NO_DICT_r22 940 +#define _GUARD_DORV_NO_DICT_r33 941 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 942 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 943 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 944 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 945 +#define _GUARD_GLOBALS_VERSION_r00 946 +#define _GUARD_GLOBALS_VERSION_r11 947 +#define _GUARD_GLOBALS_VERSION_r22 948 +#define _GUARD_GLOBALS_VERSION_r33 949 +#define _GUARD_IP_RETURN_GENERATOR_r00 950 +#define _GUARD_IP_RETURN_GENERATOR_r11 951 +#define _GUARD_IP_RETURN_GENERATOR_r22 952 +#define _GUARD_IP_RETURN_GENERATOR_r33 953 +#define _GUARD_IP_RETURN_VALUE_r00 954 +#define _GUARD_IP_RETURN_VALUE_r11 955 +#define _GUARD_IP_RETURN_VALUE_r22 956 +#define _GUARD_IP_RETURN_VALUE_r33 957 +#define _GUARD_IP_YIELD_VALUE_r00 958 +#define _GUARD_IP_YIELD_VALUE_r11 959 +#define _GUARD_IP_YIELD_VALUE_r22 960 +#define _GUARD_IP_YIELD_VALUE_r33 961 +#define _GUARD_IP__PUSH_FRAME_r00 962 +#define _GUARD_IP__PUSH_FRAME_r11 963 +#define _GUARD_IP__PUSH_FRAME_r22 964 +#define _GUARD_IP__PUSH_FRAME_r33 965 +#define _GUARD_IS_FALSE_POP_r00 966 +#define _GUARD_IS_FALSE_POP_r10 967 +#define _GUARD_IS_FALSE_POP_r21 968 +#define _GUARD_IS_FALSE_POP_r32 969 +#define _GUARD_IS_NONE_POP_r00 970 +#define _GUARD_IS_NONE_POP_r10 971 +#define _GUARD_IS_NONE_POP_r21 972 +#define _GUARD_IS_NONE_POP_r32 973 +#define _GUARD_IS_NOT_NONE_POP_r10 974 +#define _GUARD_IS_TRUE_POP_r00 975 +#define _GUARD_IS_TRUE_POP_r10 976 +#define _GUARD_IS_TRUE_POP_r21 977 +#define _GUARD_IS_TRUE_POP_r32 978 +#define _GUARD_KEYS_VERSION_r01 979 +#define _GUARD_KEYS_VERSION_r11 980 +#define _GUARD_KEYS_VERSION_r22 981 +#define _GUARD_KEYS_VERSION_r33 982 +#define _GUARD_NOS_ANY_DICT_r02 983 +#define _GUARD_NOS_ANY_DICT_r12 984 +#define _GUARD_NOS_ANY_DICT_r22 985 +#define _GUARD_NOS_ANY_DICT_r33 986 +#define _GUARD_NOS_COMPACT_ASCII_r02 987 +#define _GUARD_NOS_COMPACT_ASCII_r12 988 +#define _GUARD_NOS_COMPACT_ASCII_r22 989 +#define _GUARD_NOS_COMPACT_ASCII_r33 990 +#define _GUARD_NOS_DICT_r02 991 +#define _GUARD_NOS_DICT_r12 992 +#define _GUARD_NOS_DICT_r22 993 +#define _GUARD_NOS_DICT_r33 994 +#define _GUARD_NOS_FLOAT_r02 995 +#define _GUARD_NOS_FLOAT_r12 996 +#define _GUARD_NOS_FLOAT_r22 997 +#define _GUARD_NOS_FLOAT_r33 998 +#define _GUARD_NOS_INT_r02 999 +#define _GUARD_NOS_INT_r12 1000 +#define _GUARD_NOS_INT_r22 1001 +#define _GUARD_NOS_INT_r33 1002 +#define _GUARD_NOS_LIST_r02 1003 +#define _GUARD_NOS_LIST_r12 1004 +#define _GUARD_NOS_LIST_r22 1005 +#define _GUARD_NOS_LIST_r33 1006 +#define _GUARD_NOS_NOT_NULL_r02 1007 +#define _GUARD_NOS_NOT_NULL_r12 1008 +#define _GUARD_NOS_NOT_NULL_r22 1009 +#define _GUARD_NOS_NOT_NULL_r33 1010 +#define _GUARD_NOS_NULL_r02 1011 +#define _GUARD_NOS_NULL_r12 1012 +#define _GUARD_NOS_NULL_r22 1013 +#define _GUARD_NOS_NULL_r33 1014 +#define _GUARD_NOS_OVERFLOWED_r02 1015 +#define _GUARD_NOS_OVERFLOWED_r12 1016 +#define _GUARD_NOS_OVERFLOWED_r22 1017 +#define _GUARD_NOS_OVERFLOWED_r33 1018 +#define _GUARD_NOS_TUPLE_r02 1019 +#define _GUARD_NOS_TUPLE_r12 1020 +#define _GUARD_NOS_TUPLE_r22 1021 +#define _GUARD_NOS_TUPLE_r33 1022 +#define _GUARD_NOS_UNICODE_r02 1023 +#define _GUARD_NOS_UNICODE_r12 1024 +#define _GUARD_NOS_UNICODE_r22 1025 +#define _GUARD_NOS_UNICODE_r33 1026 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1027 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1028 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1029 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1030 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1031 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1032 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1033 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1034 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1035 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1036 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1037 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1038 +#define _GUARD_THIRD_NULL_r03 1039 +#define _GUARD_THIRD_NULL_r13 1040 +#define _GUARD_THIRD_NULL_r23 1041 +#define _GUARD_THIRD_NULL_r33 1042 +#define _GUARD_TOS_ANY_DICT_r01 1043 +#define _GUARD_TOS_ANY_DICT_r11 1044 +#define _GUARD_TOS_ANY_DICT_r22 1045 +#define _GUARD_TOS_ANY_DICT_r33 1046 +#define _GUARD_TOS_ANY_SET_r01 1047 +#define _GUARD_TOS_ANY_SET_r11 1048 +#define _GUARD_TOS_ANY_SET_r22 1049 +#define _GUARD_TOS_ANY_SET_r33 1050 +#define _GUARD_TOS_DICT_r01 1051 +#define _GUARD_TOS_DICT_r11 1052 +#define _GUARD_TOS_DICT_r22 1053 +#define _GUARD_TOS_DICT_r33 1054 +#define _GUARD_TOS_FLOAT_r01 1055 +#define _GUARD_TOS_FLOAT_r11 1056 +#define _GUARD_TOS_FLOAT_r22 1057 +#define _GUARD_TOS_FLOAT_r33 1058 +#define _GUARD_TOS_FROZENDICT_r01 1059 +#define _GUARD_TOS_FROZENDICT_r11 1060 +#define _GUARD_TOS_FROZENDICT_r22 1061 +#define _GUARD_TOS_FROZENDICT_r33 1062 +#define _GUARD_TOS_FROZENSET_r01 1063 +#define _GUARD_TOS_FROZENSET_r11 1064 +#define _GUARD_TOS_FROZENSET_r22 1065 +#define _GUARD_TOS_FROZENSET_r33 1066 +#define _GUARD_TOS_INT_r01 1067 +#define _GUARD_TOS_INT_r11 1068 +#define _GUARD_TOS_INT_r22 1069 +#define _GUARD_TOS_INT_r33 1070 +#define _GUARD_TOS_LIST_r01 1071 +#define _GUARD_TOS_LIST_r11 1072 +#define _GUARD_TOS_LIST_r22 1073 +#define _GUARD_TOS_LIST_r33 1074 +#define _GUARD_TOS_OVERFLOWED_r01 1075 +#define _GUARD_TOS_OVERFLOWED_r11 1076 +#define _GUARD_TOS_OVERFLOWED_r22 1077 +#define _GUARD_TOS_OVERFLOWED_r33 1078 +#define _GUARD_TOS_SET_r01 1079 +#define _GUARD_TOS_SET_r11 1080 +#define _GUARD_TOS_SET_r22 1081 +#define _GUARD_TOS_SET_r33 1082 +#define _GUARD_TOS_SLICE_r01 1083 +#define _GUARD_TOS_SLICE_r11 1084 +#define _GUARD_TOS_SLICE_r22 1085 +#define _GUARD_TOS_SLICE_r33 1086 +#define _GUARD_TOS_TUPLE_r01 1087 +#define _GUARD_TOS_TUPLE_r11 1088 +#define _GUARD_TOS_TUPLE_r22 1089 +#define _GUARD_TOS_TUPLE_r33 1090 +#define _GUARD_TOS_UNICODE_r01 1091 +#define _GUARD_TOS_UNICODE_r11 1092 +#define _GUARD_TOS_UNICODE_r22 1093 +#define _GUARD_TOS_UNICODE_r33 1094 +#define _GUARD_TYPE_VERSION_r01 1095 +#define _GUARD_TYPE_VERSION_r11 1096 +#define _GUARD_TYPE_VERSION_r22 1097 +#define _GUARD_TYPE_VERSION_r33 1098 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1099 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1100 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1101 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1102 +#define _HANDLE_PENDING_AND_DEOPT_r00 1103 +#define _HANDLE_PENDING_AND_DEOPT_r10 1104 +#define _HANDLE_PENDING_AND_DEOPT_r20 1105 +#define _HANDLE_PENDING_AND_DEOPT_r30 1106 +#define _IMPORT_FROM_r12 1107 +#define _IMPORT_NAME_r21 1108 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1109 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1110 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1111 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1112 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1113 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1114 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1115 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1116 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1117 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1118 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1119 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1120 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1121 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1122 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1123 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1124 +#define _INSERT_NULL_r10 1125 +#define _INSTRUMENTED_FOR_ITER_r23 1126 +#define _INSTRUMENTED_INSTRUCTION_r00 1127 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1128 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1129 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1130 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1131 +#define _INSTRUMENTED_LINE_r00 1132 +#define _INSTRUMENTED_NOT_TAKEN_r00 1133 +#define _INSTRUMENTED_NOT_TAKEN_r11 1134 +#define _INSTRUMENTED_NOT_TAKEN_r22 1135 +#define _INSTRUMENTED_NOT_TAKEN_r33 1136 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1137 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1138 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1139 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1140 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1141 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1142 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1143 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1144 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1145 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1146 +#define _IS_NONE_r11 1147 +#define _IS_OP_r03 1148 +#define _IS_OP_r13 1149 +#define _IS_OP_r23 1150 +#define _ITER_CHECK_LIST_r02 1151 +#define _ITER_CHECK_LIST_r12 1152 +#define _ITER_CHECK_LIST_r22 1153 +#define _ITER_CHECK_LIST_r33 1154 +#define _ITER_CHECK_RANGE_r02 1155 +#define _ITER_CHECK_RANGE_r12 1156 +#define _ITER_CHECK_RANGE_r22 1157 +#define _ITER_CHECK_RANGE_r33 1158 +#define _ITER_CHECK_TUPLE_r02 1159 +#define _ITER_CHECK_TUPLE_r12 1160 +#define _ITER_CHECK_TUPLE_r22 1161 +#define _ITER_CHECK_TUPLE_r33 1162 +#define _ITER_JUMP_LIST_r02 1163 +#define _ITER_JUMP_LIST_r12 1164 +#define _ITER_JUMP_LIST_r22 1165 +#define _ITER_JUMP_LIST_r33 1166 +#define _ITER_JUMP_RANGE_r02 1167 +#define _ITER_JUMP_RANGE_r12 1168 +#define _ITER_JUMP_RANGE_r22 1169 +#define _ITER_JUMP_RANGE_r33 1170 +#define _ITER_JUMP_TUPLE_r02 1171 +#define _ITER_JUMP_TUPLE_r12 1172 +#define _ITER_JUMP_TUPLE_r22 1173 +#define _ITER_JUMP_TUPLE_r33 1174 +#define _ITER_NEXT_LIST_r23 1175 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1176 +#define _ITER_NEXT_RANGE_r03 1177 +#define _ITER_NEXT_RANGE_r13 1178 +#define _ITER_NEXT_RANGE_r23 1179 +#define _ITER_NEXT_TUPLE_r03 1180 +#define _ITER_NEXT_TUPLE_r13 1181 +#define _ITER_NEXT_TUPLE_r23 1182 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1183 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1184 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1185 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1186 +#define _JUMP_TO_TOP_r00 1187 +#define _LIST_APPEND_r10 1188 +#define _LIST_EXTEND_r11 1189 +#define _LOAD_ATTR_r10 1190 +#define _LOAD_ATTR_CLASS_r11 1191 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1192 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1193 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1194 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1195 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1196 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1197 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1198 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1199 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1200 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1201 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1202 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1203 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1204 +#define _LOAD_ATTR_MODULE_r12 1205 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1206 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1207 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1208 +#define _LOAD_ATTR_SLOT_r02 1209 +#define _LOAD_ATTR_SLOT_r12 1210 +#define _LOAD_ATTR_SLOT_r23 1211 +#define _LOAD_ATTR_WITH_HINT_r12 1212 +#define _LOAD_BUILD_CLASS_r01 1213 +#define _LOAD_BYTECODE_r00 1214 +#define _LOAD_COMMON_CONSTANT_r01 1215 +#define _LOAD_COMMON_CONSTANT_r12 1216 +#define _LOAD_COMMON_CONSTANT_r23 1217 +#define _LOAD_CONST_r01 1218 +#define _LOAD_CONST_r12 1219 +#define _LOAD_CONST_r23 1220 +#define _LOAD_CONST_INLINE_r01 1221 +#define _LOAD_CONST_INLINE_r12 1222 +#define _LOAD_CONST_INLINE_r23 1223 +#define _LOAD_CONST_INLINE_BORROW_r01 1224 +#define _LOAD_CONST_INLINE_BORROW_r12 1225 +#define _LOAD_CONST_INLINE_BORROW_r23 1226 +#define _LOAD_CONST_UNDER_INLINE_r02 1227 +#define _LOAD_CONST_UNDER_INLINE_r12 1228 +#define _LOAD_CONST_UNDER_INLINE_r23 1229 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1230 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1231 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1232 +#define _LOAD_DEREF_r01 1233 +#define _LOAD_FAST_r01 1234 +#define _LOAD_FAST_r12 1235 +#define _LOAD_FAST_r23 1236 +#define _LOAD_FAST_0_r01 1237 +#define _LOAD_FAST_0_r12 1238 +#define _LOAD_FAST_0_r23 1239 +#define _LOAD_FAST_1_r01 1240 +#define _LOAD_FAST_1_r12 1241 +#define _LOAD_FAST_1_r23 1242 +#define _LOAD_FAST_2_r01 1243 +#define _LOAD_FAST_2_r12 1244 +#define _LOAD_FAST_2_r23 1245 +#define _LOAD_FAST_3_r01 1246 +#define _LOAD_FAST_3_r12 1247 +#define _LOAD_FAST_3_r23 1248 +#define _LOAD_FAST_4_r01 1249 +#define _LOAD_FAST_4_r12 1250 +#define _LOAD_FAST_4_r23 1251 +#define _LOAD_FAST_5_r01 1252 +#define _LOAD_FAST_5_r12 1253 +#define _LOAD_FAST_5_r23 1254 +#define _LOAD_FAST_6_r01 1255 +#define _LOAD_FAST_6_r12 1256 +#define _LOAD_FAST_6_r23 1257 +#define _LOAD_FAST_7_r01 1258 +#define _LOAD_FAST_7_r12 1259 +#define _LOAD_FAST_7_r23 1260 +#define _LOAD_FAST_AND_CLEAR_r01 1261 +#define _LOAD_FAST_AND_CLEAR_r12 1262 +#define _LOAD_FAST_AND_CLEAR_r23 1263 +#define _LOAD_FAST_BORROW_r01 1264 +#define _LOAD_FAST_BORROW_r12 1265 +#define _LOAD_FAST_BORROW_r23 1266 +#define _LOAD_FAST_BORROW_0_r01 1267 +#define _LOAD_FAST_BORROW_0_r12 1268 +#define _LOAD_FAST_BORROW_0_r23 1269 +#define _LOAD_FAST_BORROW_1_r01 1270 +#define _LOAD_FAST_BORROW_1_r12 1271 +#define _LOAD_FAST_BORROW_1_r23 1272 +#define _LOAD_FAST_BORROW_2_r01 1273 +#define _LOAD_FAST_BORROW_2_r12 1274 +#define _LOAD_FAST_BORROW_2_r23 1275 +#define _LOAD_FAST_BORROW_3_r01 1276 +#define _LOAD_FAST_BORROW_3_r12 1277 +#define _LOAD_FAST_BORROW_3_r23 1278 +#define _LOAD_FAST_BORROW_4_r01 1279 +#define _LOAD_FAST_BORROW_4_r12 1280 +#define _LOAD_FAST_BORROW_4_r23 1281 +#define _LOAD_FAST_BORROW_5_r01 1282 +#define _LOAD_FAST_BORROW_5_r12 1283 +#define _LOAD_FAST_BORROW_5_r23 1284 +#define _LOAD_FAST_BORROW_6_r01 1285 +#define _LOAD_FAST_BORROW_6_r12 1286 +#define _LOAD_FAST_BORROW_6_r23 1287 +#define _LOAD_FAST_BORROW_7_r01 1288 +#define _LOAD_FAST_BORROW_7_r12 1289 +#define _LOAD_FAST_BORROW_7_r23 1290 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1291 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1292 +#define _LOAD_FAST_CHECK_r01 1293 +#define _LOAD_FAST_CHECK_r12 1294 +#define _LOAD_FAST_CHECK_r23 1295 +#define _LOAD_FAST_LOAD_FAST_r02 1296 +#define _LOAD_FAST_LOAD_FAST_r13 1297 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1298 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1299 +#define _LOAD_GLOBAL_r00 1300 +#define _LOAD_GLOBAL_BUILTINS_r01 1301 +#define _LOAD_GLOBAL_MODULE_r01 1302 +#define _LOAD_LOCALS_r01 1303 +#define _LOAD_LOCALS_r12 1304 +#define _LOAD_LOCALS_r23 1305 +#define _LOAD_NAME_r01 1306 +#define _LOAD_SMALL_INT_r01 1307 +#define _LOAD_SMALL_INT_r12 1308 +#define _LOAD_SMALL_INT_r23 1309 +#define _LOAD_SMALL_INT_0_r01 1310 +#define _LOAD_SMALL_INT_0_r12 1311 +#define _LOAD_SMALL_INT_0_r23 1312 +#define _LOAD_SMALL_INT_1_r01 1313 +#define _LOAD_SMALL_INT_1_r12 1314 +#define _LOAD_SMALL_INT_1_r23 1315 +#define _LOAD_SMALL_INT_2_r01 1316 +#define _LOAD_SMALL_INT_2_r12 1317 +#define _LOAD_SMALL_INT_2_r23 1318 +#define _LOAD_SMALL_INT_3_r01 1319 +#define _LOAD_SMALL_INT_3_r12 1320 +#define _LOAD_SMALL_INT_3_r23 1321 +#define _LOAD_SPECIAL_r00 1322 +#define _LOAD_SUPER_ATTR_ATTR_r31 1323 +#define _LOAD_SUPER_ATTR_METHOD_r32 1324 +#define _LOCK_OBJECT_r01 1325 +#define _LOCK_OBJECT_r11 1326 +#define _LOCK_OBJECT_r22 1327 +#define _LOCK_OBJECT_r33 1328 +#define _MAKE_CALLARGS_A_TUPLE_r33 1329 +#define _MAKE_CELL_r00 1330 +#define _MAKE_FUNCTION_r11 1331 +#define _MAKE_HEAP_SAFE_r01 1332 +#define _MAKE_HEAP_SAFE_r11 1333 +#define _MAKE_HEAP_SAFE_r22 1334 +#define _MAKE_HEAP_SAFE_r33 1335 +#define _MAKE_WARM_r00 1336 +#define _MAKE_WARM_r11 1337 +#define _MAKE_WARM_r22 1338 +#define _MAKE_WARM_r33 1339 +#define _MAP_ADD_r20 1340 +#define _MATCH_CLASS_r33 1341 +#define _MATCH_KEYS_r23 1342 +#define _MATCH_MAPPING_r02 1343 +#define _MATCH_MAPPING_r12 1344 +#define _MATCH_MAPPING_r23 1345 +#define _MATCH_SEQUENCE_r02 1346 +#define _MATCH_SEQUENCE_r12 1347 +#define _MATCH_SEQUENCE_r23 1348 +#define _MAYBE_EXPAND_METHOD_r00 1349 +#define _MAYBE_EXPAND_METHOD_KW_r11 1350 +#define _MONITOR_CALL_r00 1351 +#define _MONITOR_CALL_KW_r11 1352 +#define _MONITOR_JUMP_BACKWARD_r00 1353 +#define _MONITOR_JUMP_BACKWARD_r11 1354 +#define _MONITOR_JUMP_BACKWARD_r22 1355 +#define _MONITOR_JUMP_BACKWARD_r33 1356 +#define _MONITOR_RESUME_r00 1357 +#define _NOP_r00 1358 +#define _NOP_r11 1359 +#define _NOP_r22 1360 +#define _NOP_r33 1361 +#define _POP_CALL_r20 1362 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1363 +#define _POP_CALL_ONE_r30 1364 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1365 +#define _POP_CALL_TWO_r30 1366 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1367 +#define _POP_EXCEPT_r10 1368 +#define _POP_ITER_r20 1369 +#define _POP_JUMP_IF_FALSE_r00 1370 +#define _POP_JUMP_IF_FALSE_r10 1371 +#define _POP_JUMP_IF_FALSE_r21 1372 +#define _POP_JUMP_IF_FALSE_r32 1373 +#define _POP_JUMP_IF_TRUE_r00 1374 +#define _POP_JUMP_IF_TRUE_r10 1375 +#define _POP_JUMP_IF_TRUE_r21 1376 +#define _POP_JUMP_IF_TRUE_r32 1377 +#define _POP_TOP_r10 1378 +#define _POP_TOP_FLOAT_r00 1379 +#define _POP_TOP_FLOAT_r10 1380 +#define _POP_TOP_FLOAT_r21 1381 +#define _POP_TOP_FLOAT_r32 1382 +#define _POP_TOP_INT_r00 1383 +#define _POP_TOP_INT_r10 1384 +#define _POP_TOP_INT_r21 1385 +#define _POP_TOP_INT_r32 1386 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1387 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1388 +#define _POP_TOP_NOP_r00 1389 +#define _POP_TOP_NOP_r10 1390 +#define _POP_TOP_NOP_r21 1391 +#define _POP_TOP_NOP_r32 1392 +#define _POP_TOP_UNICODE_r00 1393 +#define _POP_TOP_UNICODE_r10 1394 +#define _POP_TOP_UNICODE_r21 1395 +#define _POP_TOP_UNICODE_r32 1396 +#define _POP_TWO_r20 1397 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1398 +#define _PUSH_EXC_INFO_r02 1399 +#define _PUSH_EXC_INFO_r12 1400 +#define _PUSH_EXC_INFO_r23 1401 +#define _PUSH_FRAME_r10 1402 +#define _PUSH_NULL_r01 1403 +#define _PUSH_NULL_r12 1404 +#define _PUSH_NULL_r23 1405 +#define _PUSH_NULL_CONDITIONAL_r00 1406 +#define _PY_FRAME_EX_r31 1407 +#define _PY_FRAME_GENERAL_r01 1408 +#define _PY_FRAME_KW_r11 1409 +#define _REPLACE_WITH_TRUE_r02 1410 +#define _REPLACE_WITH_TRUE_r12 1411 +#define _REPLACE_WITH_TRUE_r23 1412 +#define _RESUME_CHECK_r00 1413 +#define _RESUME_CHECK_r11 1414 +#define _RESUME_CHECK_r22 1415 +#define _RESUME_CHECK_r33 1416 +#define _RETURN_GENERATOR_r01 1417 +#define _RETURN_VALUE_r11 1418 +#define _SAVE_RETURN_OFFSET_r00 1419 +#define _SAVE_RETURN_OFFSET_r11 1420 +#define _SAVE_RETURN_OFFSET_r22 1421 +#define _SAVE_RETURN_OFFSET_r33 1422 +#define _SEND_r33 1423 +#define _SEND_GEN_FRAME_r33 1424 +#define _SETUP_ANNOTATIONS_r00 1425 +#define _SET_ADD_r10 1426 +#define _SET_FUNCTION_ATTRIBUTE_r01 1427 +#define _SET_FUNCTION_ATTRIBUTE_r11 1428 +#define _SET_FUNCTION_ATTRIBUTE_r21 1429 +#define _SET_FUNCTION_ATTRIBUTE_r32 1430 +#define _SET_IP_r00 1431 +#define _SET_IP_r11 1432 +#define _SET_IP_r22 1433 +#define _SET_IP_r33 1434 +#define _SET_UPDATE_r11 1435 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1436 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1437 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1438 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1439 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1440 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1441 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1442 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1443 +#define _SPILL_OR_RELOAD_r01 1444 +#define _SPILL_OR_RELOAD_r02 1445 +#define _SPILL_OR_RELOAD_r03 1446 +#define _SPILL_OR_RELOAD_r10 1447 +#define _SPILL_OR_RELOAD_r12 1448 +#define _SPILL_OR_RELOAD_r13 1449 +#define _SPILL_OR_RELOAD_r20 1450 +#define _SPILL_OR_RELOAD_r21 1451 +#define _SPILL_OR_RELOAD_r23 1452 +#define _SPILL_OR_RELOAD_r30 1453 +#define _SPILL_OR_RELOAD_r31 1454 +#define _SPILL_OR_RELOAD_r32 1455 +#define _START_EXECUTOR_r00 1456 +#define _STORE_ATTR_r20 1457 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1458 +#define _STORE_ATTR_SLOT_r21 1459 +#define _STORE_ATTR_WITH_HINT_r21 1460 +#define _STORE_DEREF_r10 1461 +#define _STORE_FAST_LOAD_FAST_r11 1462 +#define _STORE_FAST_STORE_FAST_r20 1463 +#define _STORE_GLOBAL_r10 1464 +#define _STORE_NAME_r10 1465 +#define _STORE_SLICE_r30 1466 +#define _STORE_SUBSCR_r30 1467 +#define _STORE_SUBSCR_DICT_r31 1468 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1469 +#define _STORE_SUBSCR_LIST_INT_r32 1470 +#define _SWAP_r11 1471 +#define _SWAP_2_r02 1472 +#define _SWAP_2_r12 1473 +#define _SWAP_2_r22 1474 +#define _SWAP_2_r33 1475 +#define _SWAP_3_r03 1476 +#define _SWAP_3_r13 1477 +#define _SWAP_3_r23 1478 +#define _SWAP_3_r33 1479 +#define _SWAP_FAST_r01 1480 +#define _SWAP_FAST_r11 1481 +#define _SWAP_FAST_r22 1482 +#define _SWAP_FAST_r33 1483 +#define _SWAP_FAST_0_r01 1484 +#define _SWAP_FAST_0_r11 1485 +#define _SWAP_FAST_0_r22 1486 +#define _SWAP_FAST_0_r33 1487 +#define _SWAP_FAST_1_r01 1488 +#define _SWAP_FAST_1_r11 1489 +#define _SWAP_FAST_1_r22 1490 +#define _SWAP_FAST_1_r33 1491 +#define _SWAP_FAST_2_r01 1492 +#define _SWAP_FAST_2_r11 1493 +#define _SWAP_FAST_2_r22 1494 +#define _SWAP_FAST_2_r33 1495 +#define _SWAP_FAST_3_r01 1496 +#define _SWAP_FAST_3_r11 1497 +#define _SWAP_FAST_3_r22 1498 +#define _SWAP_FAST_3_r33 1499 +#define _SWAP_FAST_4_r01 1500 +#define _SWAP_FAST_4_r11 1501 +#define _SWAP_FAST_4_r22 1502 +#define _SWAP_FAST_4_r33 1503 +#define _SWAP_FAST_5_r01 1504 +#define _SWAP_FAST_5_r11 1505 +#define _SWAP_FAST_5_r22 1506 +#define _SWAP_FAST_5_r33 1507 +#define _SWAP_FAST_6_r01 1508 +#define _SWAP_FAST_6_r11 1509 +#define _SWAP_FAST_6_r22 1510 +#define _SWAP_FAST_6_r33 1511 +#define _SWAP_FAST_7_r01 1512 +#define _SWAP_FAST_7_r11 1513 +#define _SWAP_FAST_7_r22 1514 +#define _SWAP_FAST_7_r33 1515 +#define _TIER2_RESUME_CHECK_r00 1516 +#define _TIER2_RESUME_CHECK_r11 1517 +#define _TIER2_RESUME_CHECK_r22 1518 +#define _TIER2_RESUME_CHECK_r33 1519 +#define _TO_BOOL_r11 1520 +#define _TO_BOOL_BOOL_r01 1521 +#define _TO_BOOL_BOOL_r11 1522 +#define _TO_BOOL_BOOL_r22 1523 +#define _TO_BOOL_BOOL_r33 1524 +#define _TO_BOOL_INT_r02 1525 +#define _TO_BOOL_INT_r12 1526 +#define _TO_BOOL_INT_r23 1527 +#define _TO_BOOL_LIST_r02 1528 +#define _TO_BOOL_LIST_r12 1529 +#define _TO_BOOL_LIST_r23 1530 +#define _TO_BOOL_NONE_r01 1531 +#define _TO_BOOL_NONE_r11 1532 +#define _TO_BOOL_NONE_r22 1533 +#define _TO_BOOL_NONE_r33 1534 +#define _TO_BOOL_STR_r02 1535 +#define _TO_BOOL_STR_r12 1536 +#define _TO_BOOL_STR_r23 1537 +#define _TRACE_RECORD_r00 1538 +#define _UNARY_INVERT_r12 1539 +#define _UNARY_NEGATIVE_r12 1540 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1541 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1542 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1543 +#define _UNARY_NOT_r01 1544 +#define _UNARY_NOT_r11 1545 +#define _UNARY_NOT_r22 1546 +#define _UNARY_NOT_r33 1547 +#define _UNPACK_EX_r10 1548 +#define _UNPACK_SEQUENCE_r10 1549 +#define _UNPACK_SEQUENCE_LIST_r10 1550 +#define _UNPACK_SEQUENCE_TUPLE_r10 1551 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1552 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1553 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1554 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1555 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1556 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1557 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1558 +#define _WITH_EXCEPT_START_r33 1559 +#define _YIELD_VALUE_r11 1560 +#define MAX_UOP_REGS_ID 1560 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 6e1883009b1..4e16c3040c7 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -138,6 +138,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GUARD_TOS_ANY_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_FROZENDICT] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_SUBSCR_CHECK_FUNC] = HAS_EXIT_FLAG, [_BINARY_OP_SUBSCR_INIT_CALL] = 0, @@ -146,6 +147,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_STORE_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_STORE_SUBSCR_DICT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SUBSCR_DICT_KNOWN_HASH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DELETE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, @@ -1352,6 +1354,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TOS_FROZENDICT_r33 }, }, }, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 3, 2, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 }, + { -1, -1, -1 }, + }, + }, [_BINARY_OP_SUBSCR_DICT] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -1424,6 +1435,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 1, 3, _STORE_SUBSCR_DICT_r31 }, }, }, + [_STORE_SUBSCR_DICT_KNOWN_HASH] = { + .best = { 3, 3, 3, 3 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { 1, 3, _STORE_SUBSCR_DICT_KNOWN_HASH_r31 }, + }, + }, [_DELETE_SUBSCR] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -4022,6 +4042,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_FROZENDICT_r11] = _GUARD_TOS_FROZENDICT, [_GUARD_TOS_FROZENDICT_r22] = _GUARD_TOS_FROZENDICT, [_GUARD_TOS_FROZENDICT_r33] = _GUARD_TOS_FROZENDICT, + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23] = _BINARY_OP_SUBSCR_DICT_KNOWN_HASH, [_BINARY_OP_SUBSCR_DICT_r23] = _BINARY_OP_SUBSCR_DICT, [_BINARY_OP_SUBSCR_CHECK_FUNC_r23] = _BINARY_OP_SUBSCR_CHECK_FUNC, [_BINARY_OP_SUBSCR_INIT_CALL_r01] = _BINARY_OP_SUBSCR_INIT_CALL, @@ -4033,6 +4054,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_STORE_SUBSCR_r30] = _STORE_SUBSCR, [_STORE_SUBSCR_LIST_INT_r32] = _STORE_SUBSCR_LIST_INT, [_STORE_SUBSCR_DICT_r31] = _STORE_SUBSCR_DICT, + [_STORE_SUBSCR_DICT_KNOWN_HASH_r31] = _STORE_SUBSCR_DICT_KNOWN_HASH, [_DELETE_SUBSCR_r20] = _DELETE_SUBSCR, [_CALL_INTRINSIC_1_r12] = _CALL_INTRINSIC_1, [_CALL_INTRINSIC_2_r23] = _CALL_INTRINSIC_2, @@ -4639,6 +4661,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBSCR_CHECK_FUNC_r23] = "_BINARY_OP_SUBSCR_CHECK_FUNC_r23", [_BINARY_OP_SUBSCR_DICT] = "_BINARY_OP_SUBSCR_DICT", [_BINARY_OP_SUBSCR_DICT_r23] = "_BINARY_OP_SUBSCR_DICT_r23", + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH] = "_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", + [_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23] = "_BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23", [_BINARY_OP_SUBSCR_INIT_CALL] = "_BINARY_OP_SUBSCR_INIT_CALL", [_BINARY_OP_SUBSCR_INIT_CALL_r01] = "_BINARY_OP_SUBSCR_INIT_CALL_r01", [_BINARY_OP_SUBSCR_INIT_CALL_r11] = "_BINARY_OP_SUBSCR_INIT_CALL_r11", @@ -5706,6 +5730,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_STORE_SUBSCR_r30] = "_STORE_SUBSCR_r30", [_STORE_SUBSCR_DICT] = "_STORE_SUBSCR_DICT", [_STORE_SUBSCR_DICT_r31] = "_STORE_SUBSCR_DICT_r31", + [_STORE_SUBSCR_DICT_KNOWN_HASH] = "_STORE_SUBSCR_DICT_KNOWN_HASH", + [_STORE_SUBSCR_DICT_KNOWN_HASH_r31] = "_STORE_SUBSCR_DICT_KNOWN_HASH_r31", [_STORE_SUBSCR_LIST_INT] = "_STORE_SUBSCR_LIST_INT", [_STORE_SUBSCR_LIST_INT_r32] = "_STORE_SUBSCR_LIST_INT_r32", [_SWAP] = "_SWAP", @@ -6040,6 +6066,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GUARD_TOS_FROZENDICT: return 0; + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH: + return 2; case _BINARY_OP_SUBSCR_DICT: return 2; case _BINARY_OP_SUBSCR_CHECK_FUNC: @@ -6056,6 +6084,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 3; case _STORE_SUBSCR_DICT: return 3; + case _STORE_SUBSCR_DICT_KNOWN_HASH: + return 3; case _DELETE_SUBSCR: return 2; case _CALL_INTRINSIC_1: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 60f5cb6edbc..2005dd9b086 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -23,6 +23,11 @@ # For frozendict JIT tests FROZEN_DICT_CONST = frozendict(x=1, y=2) +class _GenericKey: + pass + +_GENERIC_KEY = _GenericKey() + @contextlib.contextmanager def clear_executors(func): @@ -2007,8 +2012,8 @@ def f(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertEqual(uops.count("_GUARD_NOS_DICT"), 0) - self.assertEqual(uops.count("_STORE_SUBSCR_DICT"), 1) - self.assertEqual(uops.count("_BINARY_OP_SUBSCR_DICT"), 1) + self.assertEqual(uops.count("_STORE_SUBSCR_DICT_KNOWN_HASH"), 1) + self.assertEqual(uops.count("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH"), 1) def test_remove_guard_for_known_type_list(self): def f(n): @@ -2312,9 +2317,46 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_BINARY_OP_SUBSCR_DICT", uops) + self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + def test_binary_op_subscr_dict_known_hash(self): + # str, int, bytes, float, complex, tuple and any python object which has generic hash + def testfunc(n): + x = 0 + d = {'a': 1, 1: 2, b'b': 3, (1, 2): 4, _GENERIC_KEY: 5, 1.5: 6, 1+2j: 7} + for _ in range(n): + x += d['a'] + d[1] + d[b'b'] + d[(1, 2)] + d[_GENERIC_KEY] + d[1.5] + d[1+2j] + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 28 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) + + def test_store_subscr_dict_known_hash(self): + # str, int, bytes, float, complex, tuple and any python object which has generic hash + def testfunc(n): + d = {'a': 0, 1: 0, b'b': 0, (1, 2): 0, _GENERIC_KEY: 0, 1.5: 0, 1+2j: 0} + for _ in range(n): + d['a'] += 1 + d[1] += 2 + d[b'b'] += 3 + d[(1, 2)] += 4 + d[_GENERIC_KEY] += 5 + d[1.5] += 6 + d[1+2j] += 7 + return d['a'] + d[1] + d[b'b'] + d[(1, 2)] + d[_GENERIC_KEY] + d[1.5] + d[1+2j] + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 28 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_STORE_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_STORE_SUBSCR_DICT", uops) + def test_contains_op(self): def testfunc(n): x = 0 @@ -3701,7 +3743,7 @@ def testfunc(n): self.assertEqual(res, 10) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_STORE_SUBSCR_DICT", uops) + self.assertIn("_STORE_SUBSCR_DICT_KNOWN_HASH", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 1) self.assertIn("_POP_TOP_NOP", uops) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e392e44267e..67bc4319e0b 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2727,21 +2727,13 @@ _PyDict_LoadBuiltinsFromGlobals(PyObject *globals) /* Consumes references to key and value */ static int -setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) +setitem_take2_lock_held_known_hash(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash) { assert(PyAnyDict_Check(mp)); assert(can_modify_dict(mp)); assert(key); assert(value); - Py_hash_t hash = _PyObject_HashFast(key); - if (hash == -1) { - dict_unhashable_type((PyObject*)mp, key); - Py_DECREF(key); - Py_DECREF(value); - return -1; - } - if (mp->ma_keys == Py_EMPTY_KEYS) { return insert_to_emptydict(mp, key, hash, value); } @@ -2749,6 +2741,20 @@ setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) return insertdict(mp, key, hash, value); } +static int +setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) +{ + Py_hash_t hash = _PyObject_HashFast(key); + if (hash == -1) { + dict_unhashable_type((PyObject*)mp, key); + Py_DECREF(key); + Py_DECREF(value); + return -1; + } + + return setitem_take2_lock_held_known_hash(mp, key, value, hash); +} + int _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) { @@ -2759,6 +2765,16 @@ _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) return res; } +int +_PyDict_SetItem_Take2_KnownHash(PyDictObject *mp, PyObject *key, PyObject *value, Py_hash_t hash) +{ + int res; + Py_BEGIN_CRITICAL_SECTION(mp); + res = setitem_take2_lock_held_known_hash(mp, key, value, hash); + Py_END_CRITICAL_SECTION(); + return res; +} + /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the * dictionary if it's merely replacing the value for an existing key. * This means that it's safe to loop over a dictionary with PyDict_Next() diff --git a/Python/bytecodes.c b/Python/bytecodes.c index ab128661096..18fea9ae4a2 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1175,6 +1175,26 @@ dummy_func( macro(BINARY_OP_SUBSCR_DICT) = _GUARD_NOS_ANY_DICT + unused/5 + _BINARY_OP_SUBSCR_DICT + POP_TOP + POP_TOP; + tier2 op(_BINARY_OP_SUBSCR_DICT_KNOWN_HASH, (dict_st, sub_st, hash/4 -- res, ds, ss)) { + PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + + assert(PyAnyDict_CheckExact(dict)); + STAT_INC(BINARY_OP, hit); + PyObject *res_o; + int rc = _PyDict_GetItemRef_KnownHash((PyDictObject *)dict, sub, (Py_hash_t)hash, &res_o); + if (rc == 0) { + _PyErr_SetKeyError(sub); + } + if (rc <= 0) { + ERROR_NO_POP(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + ds = dict_st; + ss = sub_st; + INPUTS_DEAD(); + } + op(_BINARY_OP_SUBSCR_DICT, (dict_st, sub_st -- res, ds, ss)) { PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); @@ -1319,6 +1339,24 @@ dummy_func( st = dict_st; } + tier2 op(_STORE_SUBSCR_DICT_KNOWN_HASH, (value, dict_st, sub, hash/4 -- st)) { + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + + assert(PyDict_CheckExact(dict)); + STAT_INC(STORE_SUBSCR, hit); + int err = _PyDict_SetItem_Take2_KnownHash((PyDictObject *)dict, + PyStackRef_AsPyObjectSteal(sub), + PyStackRef_AsPyObjectSteal(value), + (Py_hash_t)hash); + + if (err) { + PyStackRef_CLOSE(dict_st); + ERROR_IF(1); + } + DEAD(dict_st); + st = dict_st; + } + inst(DELETE_SUBSCR, (container, sub --)) { /* del container[sub] */ int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 93533e374fd..46740b3954e 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -6906,6 +6906,53 @@ break; } + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef sub_st; + _PyStackRef dict_st; + _PyStackRef res; + _PyStackRef ds; + _PyStackRef ss; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + sub_st = _stack_item_1; + dict_st = _stack_item_0; + PyObject *hash = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + assert(PyAnyDict_CheckExact(dict)); + STAT_INC(BINARY_OP, hit); + PyObject *res_o; + stack_pointer[0] = dict_st; + stack_pointer[1] = sub_st; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + int rc = _PyDict_GetItemRef_KnownHash((PyDictObject *)dict, sub, (Py_hash_t)hash, &res_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (rc == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_SetKeyError(sub); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + if (rc <= 0) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + ds = dict_st; + ss = sub_st; + _tos_cache2 = ss; + _tos_cache1 = ds; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _BINARY_OP_SUBSCR_DICT_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -7315,6 +7362,54 @@ break; } + case _STORE_SUBSCR_DICT_KNOWN_HASH_r31: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef sub; + _PyStackRef dict_st; + _PyStackRef value; + _PyStackRef st; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + sub = _stack_item_2; + dict_st = _stack_item_1; + value = _stack_item_0; + PyObject *hash = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); + assert(PyDict_CheckExact(dict)); + STAT_INC(STORE_SUBSCR, hit); + stack_pointer[0] = value; + stack_pointer[1] = dict_st; + stack_pointer[2] = sub; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _PyDict_SetItem_Take2_KnownHash((PyDictObject *)dict, + PyStackRef_AsPyObjectSteal(sub), + PyStackRef_AsPyObjectSteal(value), + (Py_hash_t)hash); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) { + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(dict_st); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + st = dict_st; + _tos_cache0 = st; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _DELETE_SUBSCR_r20: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 0c25c0c9bc0..4672a272fc9 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -348,6 +348,33 @@ optimize_to_bool( return 0; } +static void +optimize_dict_known_hash( + JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction *this_instr, + PyObject *sub, uint16_t opcode) +{ + if (PyUnicode_CheckExact(sub) || PyLong_CheckExact(sub) || PyBytes_CheckExact(sub) + || PyFloat_CheckExact(sub) || PyComplex_CheckExact(sub)) { + // PyObject_Hash can't fail on these types + ADD_OP(opcode, 0, PyObject_Hash(sub)); + } + else if (PyTuple_CheckExact(sub)) { + // only use known hash variant when hash of tuple is already computed + // since computing it can call arbitrary code + Py_hash_t hash = ((PyTupleObject *)sub)->ob_hash; + if (hash != -1) { + ADD_OP(opcode, 0, hash); + } + } + else if (Py_TYPE(sub)->tp_hash == PyBaseObject_Type.tp_hash) { + // for user-defined objects which don't override tp_hash + Py_hash_t hash = PyObject_Hash(sub); + ADD_OP(opcode, 0, hash); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)Py_TYPE(sub)); + _Py_BloomFilter_Add(dependencies, Py_TYPE(sub)); + } +} + static void eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit) { diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 6702f3c5665..792f83cdbd2 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -165,6 +165,11 @@ dummy_func(void) { } op(_STORE_SUBSCR_DICT, (value, dict_st, sub -- st)) { + PyObject *sub_o = sym_get_const(ctx, sub); + if (sub_o != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub_o, _STORE_SUBSCR_DICT_KNOWN_HASH); + } (void)value; st = dict_st; } @@ -482,6 +487,11 @@ dummy_func(void) { } op(_BINARY_OP_SUBSCR_DICT, (dict_st, sub_st -- res, ds, ss)) { + PyObject *sub = sym_get_const(ctx, sub_st); + if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index dd1d2813a21..7539133fb92 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1316,6 +1316,22 @@ break; } + case _BINARY_OP_SUBSCR_DICT_KNOWN_HASH: { + JitOptRef res; + JitOptRef ds; + JitOptRef ss; + res = sym_new_not_null(ctx); + ds = sym_new_not_null(ctx); + ss = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = ds; + stack_pointer[0] = ss; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _BINARY_OP_SUBSCR_DICT: { JitOptRef sub_st; JitOptRef dict_st; @@ -1324,6 +1340,11 @@ JitOptRef ss; sub_st = stack_pointer[-1]; dict_st = stack_pointer[-2]; + PyObject *sub = sym_get_const(ctx, sub_st); + if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; @@ -1471,11 +1492,18 @@ } case _STORE_SUBSCR_DICT: { + JitOptRef sub; JitOptRef dict_st; JitOptRef value; JitOptRef st; + sub = stack_pointer[-1]; dict_st = stack_pointer[-2]; value = stack_pointer[-3]; + PyObject *sub_o = sym_get_const(ctx, sub); + if (sub_o != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub_o, _STORE_SUBSCR_DICT_KNOWN_HASH); + } (void)value; st = dict_st; CHECK_STACK_BOUNDS(-2); @@ -1485,6 +1513,16 @@ break; } + case _STORE_SUBSCR_DICT_KNOWN_HASH: { + JitOptRef st; + st = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-2); + stack_pointer[-3] = st; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _DELETE_SUBSCR: { CHECK_STACK_BOUNDS(-2); stack_pointer += -2; From afd8113e9d7744e52ae82093628d373d6ecb9897 Mon Sep 17 00:00:00 2001 From: Neko Asakura Date: Tue, 31 Mar 2026 00:42:24 +0800 Subject: [PATCH 337/775] gh-144270: Make SubElement parent and tag positional-only (GH-144845) The C accelerator implementations use PyArg_ParseTuple, which inherently enforces positional-only parameters. The Python fallback allowed these as keyword arguments, creating a behavioral mismatch. Make the tag parameter of Element.__init__ and the parent and tag parameters of SubElement positional-only to align with the C accelerator. --- Doc/library/xml.etree.elementtree.rst | 10 ++++-- Lib/test/test_xml_etree.py | 35 +++++++++++++++++++ Lib/xml/etree/ElementTree.py | 4 +-- ...-02-19-16-34-18.gh-issue-144270.wJRtSr.rst | 3 ++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 919d4c595bf..bbb15ce5e75 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -691,7 +691,7 @@ Functions .. versionadded:: 3.2 -.. function:: SubElement(parent, tag, attrib={}, **extra) +.. function:: SubElement(parent, tag, /, attrib={}, **extra) Subelement factory. This function creates an element instance, and appends it to an existing element. @@ -705,6 +705,9 @@ Functions .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. + .. versionchanged:: next + *parent* and *tag* are now positional-only parameters. + .. function:: tostring(element, encoding="us-ascii", method="xml", *, \ xml_declaration=None, default_namespace=None, \ @@ -880,7 +883,7 @@ Element Objects :noindex: :no-index: -.. class:: Element(tag, attrib={}, **extra) +.. class:: Element(tag, /, attrib={}, **extra) Element class. This class defines the Element interface, and provides a reference implementation of this interface. @@ -893,6 +896,9 @@ Element Objects .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. + .. versionchanged:: next + *tag* is now a positional-only parameter. + .. attribute:: tag diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 5b06e422672..b380d0276b0 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -381,6 +381,19 @@ def test_simpleops(self): self.serialize_check(element, '') + def test_positional_only_parameter(self): + # Test Element positional-only parameters (gh-144846). + + # 'tag' is positional-only + with self.assertRaises(TypeError): + ET.Element(tag='fail') + + # 'tag' and 'attrib' as kwarg/attribute names + e = ET.Element('e', attrib={'attrib': 'foo'}, tag='bar') + self.assertEqual(e.tag, 'e') + self.assertEqual(e.get('attrib'), 'foo') + self.assertEqual(e.get('tag'), 'bar') + def test_cdata(self): # Test CDATA handling (etc). @@ -484,6 +497,28 @@ def test_attrib(self): self.assertEqual(ET.tostring(elem), b'') + def test_subelement_positional_only_parameter(self): + # Test SubElement positional-only parameters (gh-144270). + parent = ET.Element('parent') + + # 'parent' and 'tag' are positional-only + with self.assertRaises(TypeError): + ET.SubElement(parent=parent, tag='fail') + with self.assertRaises(TypeError): + ET.SubElement(parent, tag='fail') + + # 'attrib' can be passed as keyword + sub1 = ET.SubElement(parent, 'sub1', attrib={'key': 'value'}) + self.assertEqual(sub1.get('key'), 'value') + + # 'tag' and 'parent' as kwargs become XML attributes, not func params + sub2 = ET.SubElement(parent, 'sub2', attrib={'attrib': 'foo'}, + tag='bar', parent='baz') + self.assertEqual(sub2.tag, 'sub2') + self.assertEqual(sub2.get('attrib'), 'foo') + self.assertEqual(sub2.get('tag'), 'bar') + self.assertEqual(sub2.get('parent'), 'baz') + def test_makeelement(self): # Test makeelement handling. diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 57c5b64ea3b..85766e02b53 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -164,7 +164,7 @@ class Element: """ - def __init__(self, tag, attrib={}, **extra): + def __init__(self, tag, /, attrib={}, **extra): if not isinstance(attrib, (dict, frozendict)): raise TypeError("attrib must be dict or frozendict, not %s" % ( attrib.__class__.__name__,)) @@ -416,7 +416,7 @@ def itertext(self): yield t -def SubElement(parent, tag, attrib={}, **extra): +def SubElement(parent, tag, /, attrib={}, **extra): """Subelement factory which creates an element instance, and appends it to an existing parent. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst b/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst new file mode 100644 index 00000000000..b8a4374bc2d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst @@ -0,0 +1,3 @@ +Made the *tag* parameter of :class:`xml.etree.ElementTree.Element` and the +*parent* and *tag* parameters of :func:`xml.etree.ElementTree.SubElement` +positional-only, matching the behavior of the C accelerator. From a25e09721af7b9ea55a1a3baf5282bdf7670888e Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Mon, 30 Mar 2026 12:05:18 -0700 Subject: [PATCH 338/775] gh-139633: Run netrc file permission check only once per parse (GH-139634) Change the `.netrc` security check to be run once per parse of the default file rather than once per line inside the file. --- Lib/netrc.py | 37 +++++++++++-------- Lib/test/test_netrc.py | 23 ++++++++++++ ...-10-05-15-38-02.gh-issue-139633.l3P839.rst | 2 + 3 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst diff --git a/Lib/netrc.py b/Lib/netrc.py index 750b5071e3c..a28ea297df8 100644 --- a/Lib/netrc.py +++ b/Lib/netrc.py @@ -152,23 +152,28 @@ def _parse(self, file, fp, default_netrc): else: raise NetrcParseError("bad follower token %r" % tt, file, lexer.lineno) - self._security_check(fp, default_netrc, self.hosts[entryname][0]) - def _security_check(self, fp, default_netrc, login): - if _can_security_check() and default_netrc and login != "anonymous": - prop = os.fstat(fp.fileno()) - current_user_id = os.getuid() - if prop.st_uid != current_user_id: - fowner = _getpwuid(prop.st_uid) - user = _getpwuid(current_user_id) - raise NetrcParseError( - f"~/.netrc file owner ({fowner}) does not match" - f" current user ({user})") - if (prop.st_mode & (stat.S_IRWXG | stat.S_IRWXO)): - raise NetrcParseError( - "~/.netrc access too permissive: access" - " permissions must restrict access to only" - " the owner") + if _can_security_check() and default_netrc: + for entry in self.hosts.values(): + if entry[0] != "anonymous": + # Raises on security issue; once passed once can exit. + self._security_check(fp) + return + + def _security_check(self, fp): + prop = os.fstat(fp.fileno()) + current_user_id = os.getuid() + if prop.st_uid != current_user_id: + fowner = _getpwuid(prop.st_uid) + user = _getpwuid(current_user_id) + raise NetrcParseError( + f"~/.netrc file owner ({fowner}) does not match" + f" current user ({user})") + if (prop.st_mode & (stat.S_IRWXG | stat.S_IRWXO)): + raise NetrcParseError( + "~/.netrc access too permissive: access" + " permissions must restrict access to only" + " the owner") def authenticators(self, host): """Return a (user, account, password) tuple for given host.""" diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py index 9d720f62710..354081e9621 100644 --- a/Lib/test/test_netrc.py +++ b/Lib/test/test_netrc.py @@ -1,6 +1,9 @@ import netrc, os, unittest, sys, textwrap +from pathlib import Path from test import support from test.support import os_helper +from unittest.mock import patch + temp_filename = os_helper.TESTFN @@ -309,6 +312,26 @@ def test_security(self): self.assertEqual(nrc.hosts['foo.domain.com'], ('anonymous', '', 'pass')) + @unittest.skipUnless(os.name == 'posix', 'POSIX only test') + @unittest.skipUnless(hasattr(os, 'getuid'), "os.getuid is required") + @os_helper.skip_unless_working_chmod + def test_security_only_once(self): + # Make sure security check is only run once per parse when multiple + # entries are found. + with patch.object(netrc.netrc, "_security_check") as mock: + with os_helper.temp_dir() as tmp_dir: + netrc_path = Path(tmp_dir) / '.netrc' + netrc_path.write_text("""\ + machine foo.domain.com login bar password pass + machine bar.domain.com login foo password pass + """) + netrc_path.chmod(0o600) + with os_helper.EnvironmentVarGuard() as environ: + environ.set('HOME', tmp_dir) + netrc.netrc() + + mock.assert_called_once() + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst b/Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst new file mode 100644 index 00000000000..94bd18074f8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst @@ -0,0 +1,2 @@ +The :mod:`netrc` security check is now run once per parse rather than once +per entry. From 727890410b71de200f2ab918827bb97e7a3c5a2b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 30 Mar 2026 22:06:44 +0300 Subject: [PATCH 339/775] gh-145056: Fix merging of collections.OrderedDict and frozendict (GH-146466) --- Lib/collections/__init__.py | 4 ++-- Lib/test/test_ordered_dict.py | 6 ++++++ .../Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst | 1 + Objects/odictobject.c | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 2eee4c70955..ba60df037f2 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -328,14 +328,14 @@ def __ior__(self, other): return self def __or__(self, other): - if not isinstance(other, dict): + if not isinstance(other, (dict, frozendict)): return NotImplemented new = self.__class__(self) new.update(other) return new def __ror__(self, other): - if not isinstance(other, dict): + if not isinstance(other, (dict, frozendict)): return NotImplemented new = self.__class__(other) new.update(self) diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index 4204a6a47d2..642c2722711 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -698,6 +698,7 @@ def test_merge_operator(self): d |= list(b.items()) expected = OrderedDict({0: 0, 1: 1, 2: 2, 3: 3}) self.assertEqual(a | dict(b), expected) + self.assertEqual(a | frozendict(b), expected) self.assertEqual(a | b, expected) self.assertEqual(c, expected) self.assertEqual(d, expected) @@ -706,12 +707,17 @@ def test_merge_operator(self): c |= a expected = OrderedDict({1: 1, 2: 1, 3: 3, 0: 0}) self.assertEqual(dict(b) | a, expected) + self.assertEqual(frozendict(b) | a, expected) + self.assertEqual(a.__ror__(frozendict(b)), expected) self.assertEqual(b | a, expected) self.assertEqual(c, expected) self.assertIs(type(a | b), OrderedDict) self.assertIs(type(dict(a) | b), OrderedDict) + self.assertIs(type(frozendict(a) | b), frozendict) + self.assertIs(type(b.__ror__(frozendict(a))), OrderedDict) self.assertIs(type(a | dict(b)), OrderedDict) + self.assertIs(type(a | frozendict(b)), OrderedDict) expected = a.copy() a |= () diff --git a/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst b/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst new file mode 100644 index 00000000000..4eaabfbb9a8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst @@ -0,0 +1 @@ +Fix merging of :class:`collections.OrderedDict` and :class:`frozendict`. diff --git a/Objects/odictobject.c b/Objects/odictobject.c index e3ec0ae470c..b391283e837 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -906,7 +906,7 @@ odict_or(PyObject *left, PyObject *right) type = Py_TYPE(right); other = left; } - if (!PyDict_Check(other)) { + if (!PyAnyDict_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } PyObject *new = PyObject_CallOneArg((PyObject*)type, left); @@ -2268,7 +2268,7 @@ static int mutablemapping_update_arg(PyObject *self, PyObject *arg) { int res = 0; - if (PyDict_CheckExact(arg)) { + if (PyAnyDict_CheckExact(arg)) { PyObject *items = PyDict_Items(arg); if (items == NULL) { return -1; From ec2bc12e54920d6fbd664ffc5af41dfb45a0a7f7 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 30 Mar 2026 22:07:28 +0300 Subject: [PATCH 340/775] gh-145056: Add support for merging collections.UserDict and frozendict (GH-146465) --- Lib/collections/__init__.py | 4 ++-- Lib/test/test_userdict.py | 4 ++-- .../Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index ba60df037f2..febab521629 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1216,14 +1216,14 @@ def __repr__(self): def __or__(self, other): if isinstance(other, UserDict): return self.__class__(self.data | other.data) - if isinstance(other, dict): + if isinstance(other, (dict, frozendict)): return self.__class__(self.data | other) return NotImplemented def __ror__(self, other): if isinstance(other, UserDict): return self.__class__(other.data | self.data) - if isinstance(other, dict): + if isinstance(other, (dict, frozendict)): return self.__class__(other | self.data) return NotImplemented diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py index 13285c9b2a3..c60135ca5a1 100644 --- a/Lib/test/test_userdict.py +++ b/Lib/test/test_userdict.py @@ -245,7 +245,7 @@ class G(collections.UserDict): test_repr_deep = mapping_tests.TestHashMappingProtocol.test_repr_deep def test_mixed_or(self): - for t in UserDict, dict, types.MappingProxyType: + for t in UserDict, dict, frozendict, types.MappingProxyType: with self.subTest(t.__name__): u = UserDict({0: 'a', 1: 'b'}) | t({1: 'c', 2: 'd'}) self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'}) @@ -276,7 +276,7 @@ def test_mixed_or(self): self.assertIs(type(u), UserDictSubclass) def test_mixed_ior(self): - for t in UserDict, dict, types.MappingProxyType: + for t in UserDict, dict, frozendict, types.MappingProxyType: with self.subTest(t.__name__): u = u2 = UserDict({0: 'a', 1: 'b'}) u |= t({1: 'c', 2: 'd'}) diff --git a/Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst b/Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst new file mode 100644 index 00000000000..66e31117e33 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst @@ -0,0 +1 @@ +Add support for merging :class:`collections.UserDict` and :class:`frozendict`. From e79fd603392b9946c671a688da91281f7fdb1e2a Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Mon, 30 Mar 2026 22:48:34 +0300 Subject: [PATCH 341/775] gh-146238: Support half-floats in the array module (#146242) Co-authored-by: Victor Stinner --- Doc/library/array.rst | 17 +++++- Doc/whatsnew/3.15.rst | 4 ++ Lib/test/test_array.py | 13 +++- ...-03-21-10-02-20.gh-issue-146238.2WpMOj.rst | 2 + Modules/arraymodule.c | 60 ++++++++++++++++++- 5 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 6a69361369b..8b0a0c84548 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -42,13 +42,15 @@ defined: +-----------+--------------------+-------------------+-----------------------+-------+ | ``'Q'`` | unsigned long long | int | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ +| ``'e'`` | _Float16 | float | 2 | \(3) | ++-----------+--------------------+-------------------+-----------------------+-------+ | ``'f'`` | float | float | 4 | | +-----------+--------------------+-------------------+-----------------------+-------+ | ``'d'`` | double | float | 8 | | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'F'`` | float complex | complex | 8 | \(3) | +| ``'F'`` | float complex | complex | 8 | \(4) | +-----------+--------------------+-------------------+-----------------------+-------+ -| ``'D'`` | double complex | complex | 16 | \(3) | +| ``'D'`` | double complex | complex | 16 | \(4) | +-----------+--------------------+-------------------+-----------------------+-------+ @@ -69,6 +71,15 @@ Notes: .. versionadded:: 3.13 (3) + The IEEE 754 binary16 "half precision" type was introduced in the 2008 + revision of the `IEEE 754 standard `_. + This type is not widely supported by C compilers. It's available + as :c:expr:`_Float16` type, if the compiler supports the Annex H + of the C23 standard. + + .. versionadded:: next + +(4) Complex types (``F`` and ``D``) are available unconditionally, regardless on support for complex types (the Annex G of the C11 standard) by the C compiler. @@ -304,3 +315,5 @@ Examples:: `NumPy `_ The NumPy package defines another array type. + +.. _ieee 754 standard: https://en.wikipedia.org/wiki/IEEE_754-2008_revision diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 7d13eccb223..462482c8012 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -642,6 +642,10 @@ array formatting characters ``'F'`` and ``'D'`` respectively. (Contributed by Sergey B Kirpichev in :gh:`146151`.) +* Support half-floats (16-bit IEEE 754 binary interchange format): formatting + character ``'e'``. + (Contributed by Sergey B Kirpichev in :gh:`146238`.) + base64 ------ diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index b3561e7650a..4493349798d 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -31,7 +31,7 @@ class ArraySubclassWithKwargs(array.array): def __init__(self, typecode, newarg=None): array.array.__init__(self) -typecodes = 'uwbBhHiIlLfdqQFD' +typecodes = 'uwbBhHiIlLfdqQFDe' class MiscTest(unittest.TestCase): @@ -117,8 +117,10 @@ def __index__(self): IEEE_754_FLOAT_COMPLEX_BE = 23 IEEE_754_DOUBLE_COMPLEX_LE = 24 IEEE_754_DOUBLE_COMPLEX_BE = 25 +IEEE_754_FLOAT16_LE = 26 +IEEE_754_FLOAT16_BE = 27 -MACHINE_FORMAT_CODE_MAX = 25 +MACHINE_FORMAT_CODE_MAX = 27 class ArrayReconstructorTest(unittest.TestCase): @@ -1588,6 +1590,13 @@ def test_byteswap(self): self.assertEqual(a, b) +class HalfFloatTest(FPTest, unittest.TestCase): + example = [-42.0, 0, 42, 1e2, -1e4] + smallerexample = [-42.0, 0, 42, 1e2, -2e4] + biggerexample = [-42.0, 0, 42, 1e2, 1e4] + typecode = 'e' + minitemsize = 2 + class FloatTest(FPTest, unittest.TestCase): typecode = 'f' minitemsize = 4 diff --git a/Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst b/Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst new file mode 100644 index 00000000000..35e951e38e4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst @@ -0,0 +1,2 @@ +Support half-floats (type code ``'e'`` of the :mod:`struct` module) in the +:mod:`array` module. Patch by Sergey B Kirpichev. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 42572833c21..555a35b3fc9 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -119,10 +119,12 @@ enum machine_format_code { IEEE_754_FLOAT_COMPLEX_LE = 22, IEEE_754_FLOAT_COMPLEX_BE = 23, IEEE_754_DOUBLE_COMPLEX_LE = 24, - IEEE_754_DOUBLE_COMPLEX_BE = 25 + IEEE_754_DOUBLE_COMPLEX_BE = 25, + IEEE_754_FLOAT16_LE = 26, + IEEE_754_FLOAT16_BE = 27 }; #define MACHINE_FORMAT_CODE_MIN 0 -#define MACHINE_FORMAT_CODE_MAX 25 +#define MACHINE_FORMAT_CODE_MAX 27 /* @@ -611,6 +613,32 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) return 0; } +static PyObject * +e_getitem(arrayobject *ap, Py_ssize_t i) +{ + double x = PyFloat_Unpack2(ap->ob_item + sizeof(short)*i, + PY_LITTLE_ENDIAN); + + return PyFloat_FromDouble(x); +} + +static int +e_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) +{ + float x; + if (!PyArg_Parse(v, "f;array item must be float", &x)) { + return -1; + } + + CHECK_ARRAY_BOUNDS(ap, i); + + if (i >= 0) { + return PyFloat_Pack2(x, ap->ob_item + sizeof(short)*i, + PY_LITTLE_ENDIAN); + } + return 0; +} + static PyObject * f_getitem(arrayobject *ap, Py_ssize_t i) { @@ -751,6 +779,7 @@ static const struct arraydescr descriptors[] = { {'L', sizeof(long), LL_getitem, LL_setitem, LL_compareitems, "L", 1, 0}, {'q', sizeof(long long), q_getitem, q_setitem, q_compareitems, "q", 1, 1}, {'Q', sizeof(long long), QQ_getitem, QQ_setitem, QQ_compareitems, "Q", 1, 0}, + {'e', sizeof(short), e_getitem, e_setitem, NULL, "e", 0, 0}, {'f', sizeof(float), f_getitem, f_setitem, NULL, "f", 0, 0}, {'d', sizeof(double), d_getitem, d_setitem, NULL, "d", 0, 0}, {'F', 2*sizeof(float), cf_getitem, cf_setitem, NULL, "F", 0, 0}, @@ -2090,6 +2119,8 @@ static const struct mformatdescr { {8, 0, 1}, /* 23: IEEE_754_FLOAT_COMPLEX_BE */ {16, 0, 0}, /* 24: IEEE_754_DOUBLE_COMPLEX_LE */ {16, 0, 1}, /* 25: IEEE_754_DOUBLE_COMPLEX_BE */ + {2, 0, 0}, /* 26: IEEE_754_FLOAT16_LE */ + {2, 0, 1} /* 27: IEEE_754_FLOAT16_BE */ }; @@ -2124,6 +2155,9 @@ typecode_to_mformat_code(char typecode) case 'w': return UTF32_LE + is_big_endian; + case 'e': + return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_FLOAT16_BE : IEEE_754_FLOAT16_LE; + case 'f': return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_FLOAT_BE : IEEE_754_FLOAT_LE; @@ -2309,6 +2343,27 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, return NULL; } switch (mformat_code) { + case IEEE_754_FLOAT16_LE: + case IEEE_754_FLOAT16_BE: { + Py_ssize_t i; + int le = (mformat_code == IEEE_754_FLOAT_LE) ? 1 : 0; + Py_ssize_t itemcount = Py_SIZE(items) / 2; + const char *memstr = PyBytes_AS_STRING(items); + + converted_items = PyList_New(itemcount); + if (converted_items == NULL) + return NULL; + for (i = 0; i < itemcount; i++) { + PyObject *pyfloat = PyFloat_FromDouble( + PyFloat_Unpack2(&memstr[i * 2], le)); + if (pyfloat == NULL) { + Py_DECREF(converted_items); + return NULL; + } + PyList_SET_ITEM(converted_items, i, pyfloat); + } + break; + } case IEEE_754_FLOAT_LE: case IEEE_754_FLOAT_BE: { Py_ssize_t i; @@ -3129,6 +3184,7 @@ The following type codes are defined:\n\ 'L' unsigned integer 4\n\ 'q' signed integer 8 (see note)\n\ 'Q' unsigned integer 8 (see note)\n\ + 'e' 16-bit IEEE floats 2\n\ 'f' floating-point 4\n\ 'd' floating-point 8\n\ 'F' float complex 8\n\ From ca95e979d6c9c62696bf3c162ddc21eae841c804 Mon Sep 17 00:00:00 2001 From: Brandon Date: Mon, 30 Mar 2026 15:04:04 -0500 Subject: [PATCH 342/775] gh-146442: Fix various bugs in compiler pipeline (#146443) Fix null derefs, missing decrefs, and unchecked returns from bug report. --- Python/assemble.c | 1 + Python/codegen.c | 18 ++++++++++++++---- Python/compile.c | 4 ++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Python/assemble.c b/Python/assemble.c index 7c08488092d..3df959c3634 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -418,6 +418,7 @@ assemble_emit_instr(struct assembler *a, instruction *instr) int size = instr_size(instr); if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) { if (len > PY_SSIZE_T_MAX / 2) { + PyErr_NoMemory(); return ERROR; } RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2)); diff --git a/Python/codegen.c b/Python/codegen.c index d300d77e0f7..aca590d055f 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -667,8 +667,8 @@ codegen_unwind_fblock_stack(compiler *c, location *ploc, _PyCompile_PopFBlock(c, top->fb_type, top->fb_block); RETURN_IF_ERROR(codegen_unwind_fblock(c, ploc, ©, preserve_tos)); RETURN_IF_ERROR(codegen_unwind_fblock_stack(c, ploc, preserve_tos, loop)); - _PyCompile_PushFBlock(c, copy.fb_loc, copy.fb_type, copy.fb_block, - copy.fb_exit, copy.fb_datum); + RETURN_IF_ERROR(_PyCompile_PushFBlock(c, copy.fb_loc, copy.fb_type, copy.fb_block, + copy.fb_exit, copy.fb_datum)); return SUCCESS; } @@ -715,10 +715,14 @@ codegen_setup_annotations_scope(compiler *c, location loc, // if .format > VALUE_WITH_FAKE_GLOBALS: raise NotImplementedError PyObject *value_with_fake_globals = PyLong_FromLong(_Py_ANNOTATE_FORMAT_VALUE_WITH_FAKE_GLOBALS); + if (value_with_fake_globals == NULL) { + return ERROR; + } + assert(!SYMTABLE_ENTRY(c)->ste_has_docstring); _Py_DECLARE_STR(format, ".format"); ADDOP_I(c, loc, LOAD_FAST, 0); - ADDOP_LOAD_CONST(c, loc, value_with_fake_globals); + ADDOP_LOAD_CONST_NEW(c, loc, value_with_fake_globals); ADDOP_I(c, loc, COMPARE_OP, (Py_GT << 5) | compare_masks[Py_GT]); NEW_JUMP_TARGET_LABEL(c, body); ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, body); @@ -794,6 +798,9 @@ codegen_deferred_annotations_body(compiler *c, location loc, if (!mangled) { return ERROR; } + // NOTE: ref of mangled can be leaked on ADDOP* and VISIT macros due to early returns + // fixing would require an overhaul of these macros + PyObject *cond_index = PyList_GET_ITEM(conditional_annotation_indices, i); assert(PyLong_CheckExact(cond_index)); long idx = PyLong_AS_LONG(cond_index); @@ -3279,7 +3286,10 @@ codegen_nameop(compiler *c, location loc, } int scope = _PyST_GetScope(SYMTABLE_ENTRY(c), mangled); - RETURN_IF_ERROR(scope); + if (scope == -1) { + goto error; + } + _PyCompile_optype optype; Py_ssize_t arg = 0; if (_PyCompile_ResolveNameop(c, mangled, scope, &optype, &arg) < 0) { diff --git a/Python/compile.c b/Python/compile.c index 4cf178b06ae..365b118cc71 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1100,18 +1100,22 @@ _PyCompile_TweakInlinedComprehensionScopes(compiler *c, location loc, assert(orig == NULL || orig == Py_True || orig == Py_False); if (orig != Py_True) { if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) { + Py_XDECREF(orig); return ERROR; } if (state->fast_hidden == NULL) { state->fast_hidden = PySet_New(NULL); if (state->fast_hidden == NULL) { + Py_XDECREF(orig); return ERROR; } } if (PySet_Add(state->fast_hidden, k) < 0) { + Py_XDECREF(orig); return ERROR; } } + Py_XDECREF(orig); } } } From 70d1b08a4bb52652094c3eb69e36223ecd8b8075 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 30 Mar 2026 22:31:36 +0200 Subject: [PATCH 343/775] gh-146376: Reduce timeout in Emscripten GHA workflow (#146378) --- .github/workflows/reusable-emscripten.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-emscripten.yml b/.github/workflows/reusable-emscripten.yml index fd269df9ead..b79cb5bca29 100644 --- a/.github/workflows/reusable-emscripten.yml +++ b/.github/workflows/reusable-emscripten.yml @@ -10,7 +10,7 @@ jobs: build-emscripten-reusable: name: 'build and test' runs-on: ubuntu-24.04 - timeout-minutes: 60 + timeout-minutes: 40 steps: - uses: actions/checkout@v6 with: From 72d29ea363f1515115753653aeca735a1a817a7f Mon Sep 17 00:00:00 2001 From: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:48:02 +0800 Subject: [PATCH 344/775] gh-146615: Fix crash in __get__() for METH_METHOD descriptors with invalid type argument (GH-146634) --- Lib/test/test_descr.py | 22 +++++++++++++++++++ ...1-06-35.gh-issue-146615.fix-method-get.rst | 3 +++ Objects/descrobject.c | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 1d7669e4fa5..8a8e70214e2 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1803,6 +1803,28 @@ class SubSpam(spam.spamlist): pass spam_cm.__get__(None, list) self.assertEqual(str(cm.exception), expected_errmsg) + @support.cpython_only + def test_method_get_meth_method_invalid_type(self): + # gh-146615: method_get() for METH_METHOD descriptors used to pass + # Py_TYPE(type)->tp_name as the %V fallback instead of the separate + # %s argument, causing a missing argument for %s and a crash. + # Verify the error message is correct when __get__() is called with a + # non-type as the second argument. + # + # METH_METHOD|METH_FASTCALL|METH_KEYWORDS is the only flag combination + # that enters the affected branch in method_get(). + import io + + obj = io.StringIO() + descr = io.TextIOBase.read + + with self.assertRaises(TypeError) as cm: + descr.__get__(obj, "not_a_type") + self.assertEqual( + str(cm.exception), + "descriptor 'read' needs a type, not 'str', as arg 2", + ) + def test_staticmethods(self): # Testing static methods... class C(object): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst new file mode 100644 index 00000000000..7a205f1d6dd --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst @@ -0,0 +1,3 @@ +Fix a crash in :meth:`~object.__get__` for :c:expr:`METH_METHOD` descriptors +when an invalid (non-type) object is passed as the second argument. +Patch by Steven Sun. diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 5ac4fbd8129..517d9e9fa9d 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -150,7 +150,7 @@ method_get(PyObject *self, PyObject *obj, PyObject *type) } else { PyErr_Format(PyExc_TypeError, "descriptor '%V' needs a type, not '%s', as arg 2", - descr_name((PyDescrObject *)descr), + descr_name((PyDescrObject *)descr), "?", Py_TYPE(type)->tp_name); return NULL; } From 1c396e18218daa723b425af0781c5e762d7717c2 Mon Sep 17 00:00:00 2001 From: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:57:37 +0800 Subject: [PATCH 345/775] gh-146615: Fix format specifiers in extension modules (GH-146617) --- Modules/_asynciomodule.c | 6 +++--- Modules/_remote_debugging/asyncio.c | 2 +- Modules/_ssl.c | 14 +++++--------- Modules/_zoneinfo.c | 2 +- Modules/binascii.c | 4 ++-- Modules/socketmodule.c | 3 +-- 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 826c0b25a36..bd294648ca2 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2244,7 +2244,7 @@ enter_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task) PyExc_RuntimeError, "Cannot enter into task %R while another " \ "task %R is being executed.", - task, ts->asyncio_running_task, NULL); + task, ts->asyncio_running_task); return -1; } @@ -2265,7 +2265,7 @@ leave_task(_PyThreadStateImpl *ts, PyObject *loop, PyObject *task) PyExc_RuntimeError, "Invalid attempt to leave task %R while " \ "task %R is entered.", - task, ts->asyncio_running_task ? ts->asyncio_running_task : Py_None, NULL); + task, ts->asyncio_running_task ? ts->asyncio_running_task : Py_None); return -1; } Py_CLEAR(ts->asyncio_running_task); @@ -2328,7 +2328,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop, self->task_log_destroy_pending = 0; PyErr_Format(PyExc_TypeError, "a coroutine was expected, got %R", - coro, NULL); + coro); return -1; } diff --git a/Modules/_remote_debugging/asyncio.c b/Modules/_remote_debugging/asyncio.c index 12a8a9acc13..263c502a857 100644 --- a/Modules/_remote_debugging/asyncio.c +++ b/Modules/_remote_debugging/asyncio.c @@ -212,7 +212,7 @@ parse_task_name( set_exception_cause(unwinder, PyExc_RuntimeError, "Task name PyLong parsing failed"); return NULL; } - return PyUnicode_FromFormat("Task-%d", res); + return PyUnicode_FromFormat("Task-%ld", res); } if(!(GET_MEMBER(unsigned long, type_obj, unwinder->debug_offsets.type_object.tp_flags) & Py_TPFLAGS_UNICODE_SUBCLASS)) { diff --git a/Modules/_ssl.c b/Modules/_ssl.c index d42a4e7f707..b93bbe8ddf5 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -592,7 +592,7 @@ fill_and_set_sslerror(_sslmodulestate *state, } else { if (PyUnicodeWriter_Format( - writer, "unknown error (0x%x)", errcode) < 0) { + writer, "unknown error (0x%lx)", errcode) < 0) { goto fail; } } @@ -4016,15 +4016,11 @@ _ssl__SSLContext_verify_flags_set_impl(PySSLContext *self, PyObject *value) static int set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) { - long v; + int v; int result; - if (!PyArg_Parse(arg, "l", &v)) + if (!PyArg_Parse(arg, "i", &v)) return -1; - if (v > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "Option is too long"); - return -1; - } switch(self->protocol) { case PY_SSL_VERSION_TLS_CLIENT: _Py_FALLTHROUGH; @@ -4059,7 +4055,7 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) break; default: PyErr_Format(PyExc_ValueError, - "Unsupported TLS/SSL version 0x%x", v); + "Unsupported TLS/SSL version 0x%x", (unsigned)v); return -1; } @@ -4093,7 +4089,7 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) } if (result == 0) { PyErr_Format(PyExc_ValueError, - "Unsupported protocol version 0x%x", v); + "Unsupported protocol version 0x%x", (unsigned)v); return -1; } return 0; diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index 159cac3c066..aa0b1302cb2 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -991,7 +991,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) } if (!PyTuple_CheckExact(data_tuple)) { - PyErr_Format(PyExc_TypeError, "Invalid data result type: %r", + PyErr_Format(PyExc_TypeError, "Invalid data result type: %R", data_tuple); goto error; } diff --git a/Modules/binascii.c b/Modules/binascii.c index dbe77ff248d..c51bb9c3c77 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -1350,7 +1350,7 @@ binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, state = get_binascii_state(module); if (state != NULL) { PyErr_Format(state->Error, - "Base85 overflow in hunk starting at byte %d", + "Base85 overflow in hunk starting at byte %zd", (data->len - ascii_len) / 5 * 5); } goto error; @@ -1361,7 +1361,7 @@ binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, else { state = get_binascii_state(module); if (state != NULL) { - PyErr_Format(state->Error, "bad Base85 character at position %d", + PyErr_Format(state->Error, "bad Base85 character at position %zd", data->len - ascii_len); } goto error; diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 1cedd64e0e9..a97b09a4f5d 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3357,8 +3357,7 @@ sock_setsockopt(PyObject *self, PyObject *args) arglen = PyTuple_Size(args); if (arglen == 3 && optval == Py_None) { PyErr_Format(PyExc_TypeError, - "setsockopt() requires 4 arguments when the third argument is None", - arglen); + "setsockopt() requires 4 arguments when the third argument is None"); return NULL; } if (arglen == 4 && optval != Py_None) { From b7055533abc2f7f93e04778fb70664096aa3d3b5 Mon Sep 17 00:00:00 2001 From: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:58:27 +0800 Subject: [PATCH 346/775] gh-146615: Fix format specifiers in test cextensions (GH-146618) --- Modules/_testcapi/watchers.c | 4 ++-- Modules/_testcapimodule.c | 4 ++-- Modules/_testinternalcapi.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_testcapi/watchers.c b/Modules/_testcapi/watchers.c index 6d061bb8d51..5a756a87c15 100644 --- a/Modules/_testcapi/watchers.c +++ b/Modules/_testcapi/watchers.c @@ -364,7 +364,7 @@ add_code_watcher(PyObject *self, PyObject *which_watcher) watcher_id = PyCode_AddWatcher(error_code_event_handler); } else { - PyErr_Format(PyExc_ValueError, "invalid watcher %d", which_l); + PyErr_Format(PyExc_ValueError, "invalid watcher %ld", which_l); return NULL; } if (watcher_id < 0) { @@ -673,7 +673,7 @@ add_context_watcher(PyObject *self, PyObject *which_watcher) assert(PyLong_Check(which_watcher)); long which_l = PyLong_AsLong(which_watcher); if (which_l < 0 || which_l >= (long)Py_ARRAY_LENGTH(callbacks)) { - PyErr_Format(PyExc_ValueError, "invalid watcher %d", which_l); + PyErr_Format(PyExc_ValueError, "invalid watcher %ld", which_l); return NULL; } int watcher_id = PyContext_AddWatcher(callbacks[which_l]); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index a76af1416e0..aa12db20908 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -116,8 +116,8 @@ test_sizeof_c_types(PyObject *self, PyObject *Py_UNUSED(ignored)) do { \ if (EXPECTED != sizeof(TYPE)) { \ PyErr_Format(get_testerror(self), \ - "sizeof(%s) = %u instead of %u", \ - #TYPE, sizeof(TYPE), EXPECTED); \ + "sizeof(%s) = %zu instead of %u", \ + #TYPE, sizeof(TYPE), (unsigned)(EXPECTED)); \ return (PyObject*)NULL; \ } \ } while (0) diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 7f6ea621f87..c00bad46a54 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -417,14 +417,14 @@ test_bswap(PyObject *self, PyObject *Py_UNUSED(args)) uint16_t u16 = _Py_bswap16(UINT16_C(0x3412)); if (u16 != UINT16_C(0x1234)) { PyErr_Format(PyExc_AssertionError, - "_Py_bswap16(0x3412) returns %u", u16); + "_Py_bswap16(0x3412) returns %d", u16); return NULL; } uint32_t u32 = _Py_bswap32(UINT32_C(0x78563412)); if (u32 != UINT32_C(0x12345678)) { PyErr_Format(PyExc_AssertionError, - "_Py_bswap32(0x78563412) returns %lu", u32); + "_Py_bswap32(0x78563412) returns %u", u32); return NULL; } @@ -703,7 +703,7 @@ test_edit_cost(PyObject *self, PyObject *Py_UNUSED(args)) static int check_bytes_find(const char *haystack0, const char *needle0, - int offset, Py_ssize_t expected) + Py_ssize_t offset, Py_ssize_t expected) { Py_ssize_t len_haystack = strlen(haystack0); Py_ssize_t len_needle = strlen(needle0); @@ -1158,7 +1158,7 @@ get_interp_settings(PyObject *self, PyObject *args) } else { PyErr_Format(PyExc_NotImplementedError, - "%zd", interpid); + "%d", interpid); return NULL; } assert(interp != NULL); From dcb260eff2d276976933f78c24a4ebd0ed7dbc36 Mon Sep 17 00:00:00 2001 From: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:59:17 +0800 Subject: [PATCH 347/775] gh-146615: Fix format specifiers in Python/ directory (GH-146619) --- Python/bltinmodule.c | 8 ++++---- Python/ceval.c | 4 ++-- Python/crossinterp_data_lookup.h | 2 +- Python/getargs.c | 6 +++--- Python/interpconfig.c | 2 +- Python/pythonrun.c | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 5680e897157..fec64e1ff9d 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1607,7 +1607,7 @@ map_next(PyObject *self) // ValueError: map() argument 3 is shorter than arguments 1-2 const char* plural = i == 1 ? " " : "s 1-"; PyErr_Format(PyExc_ValueError, - "map() argument %d is shorter than argument%s%d", + "map() argument %zd is shorter than argument%s%zd", i + 1, plural, i); goto exit_no_result; } @@ -1618,7 +1618,7 @@ map_next(PyObject *self) Py_DECREF(val); const char* plural = i == 1 ? " " : "s 1-"; PyErr_Format(PyExc_ValueError, - "map() argument %d is longer than argument%s%d", + "map() argument %zd is longer than argument%s%zd", i + 1, plural, i); goto exit_no_result; } @@ -3307,7 +3307,7 @@ zip_next(PyObject *self) // ValueError: zip() argument 3 is shorter than arguments 1-2 const char* plural = i == 1 ? " " : "s 1-"; return PyErr_Format(PyExc_ValueError, - "zip() argument %d is shorter than argument%s%d", + "zip() argument %zd is shorter than argument%s%zd", i + 1, plural, i); } for (i = 1; i < tuplesize; i++) { @@ -3317,7 +3317,7 @@ zip_next(PyObject *self) Py_DECREF(item); const char* plural = i == 1 ? " " : "s 1-"; return PyErr_Format(PyExc_ValueError, - "zip() argument %d is longer than argument%s%d", + "zip() argument %zd is longer than argument%s%zd", i + 1, plural, i); } if (PyErr_Occurred()) { diff --git a/Python/ceval.c b/Python/ceval.c index 49aeffc3caf..bf550f2da36 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -602,7 +602,7 @@ _PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, if (allowed < nargs) { const char *plural = (allowed == 1) ? "" : "s"; _PyErr_Format(tstate, PyExc_TypeError, - "%s() accepts %d positional sub-pattern%s (%d given)", + "%s() accepts %zd positional sub-pattern%s (%zd given)", ((PyTypeObject*)type)->tp_name, allowed, plural, nargs); goto fail; @@ -1555,7 +1555,7 @@ format_missing(PyThreadState *tstate, const char *kind, if (name_str == NULL) return; _PyErr_Format(tstate, PyExc_TypeError, - "%U() missing %i required %s argument%s: %U", + "%U() missing %zd required %s argument%s: %U", qualname, len, kind, diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index c3c76ae8d9a..cf84633e10e 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -455,7 +455,7 @@ _PyBytes_GetXIDataWrapped(PyThreadState *tstate, return NULL; } if (size < sizeof(_PyBytes_data_t)) { - PyErr_Format(PyExc_ValueError, "expected size >= %d, got %d", + PyErr_Format(PyExc_ValueError, "expected size >= %zu, got %zu", sizeof(_PyBytes_data_t), size); return NULL; } diff --git a/Python/getargs.c b/Python/getargs.c index 31cd4ad3f65..3f423266bff 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2421,7 +2421,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, if (i < parser->min) { /* Less arguments than required */ if (i < pos) { - Py_ssize_t min = Py_MIN(pos, parser->min); + int min = Py_MIN(pos, parser->min); PyErr_Format(PyExc_TypeError, "%.200s%s takes %s %d positional argument%s" " (%zd given)", @@ -2435,7 +2435,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, else { keyword = PyTuple_GET_ITEM(kwtuple, i - pos); PyErr_Format(PyExc_TypeError, "%.200s%s missing required " - "argument '%U' (pos %d)", + "argument '%U' (pos %zd)", (parser->fname == NULL) ? "function" : parser->fname, (parser->fname == NULL) ? "" : "()", keyword, i+1); @@ -2476,7 +2476,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, "argument for %.200s%s given by name ('%U') " - "and position (%d)", + "and position (%zd)", (parser->fname == NULL) ? "function" : parser->fname, (parser->fname == NULL) ? "" : "()", keyword, i+1); diff --git a/Python/interpconfig.c b/Python/interpconfig.c index 1add8a81425..a37bd3f5b23 100644 --- a/Python/interpconfig.c +++ b/Python/interpconfig.c @@ -208,7 +208,7 @@ interp_config_from_dict(PyObject *origdict, PyInterpreterConfig *config, } else if (unused > 0) { PyErr_Format(PyExc_ValueError, - "config dict has %d extra items (%R)", unused, dict); + "config dict has %zd extra items (%R)", unused, dict); goto error; } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 1e327848e65..971ab064777 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1382,11 +1382,11 @@ get_interactive_filename(PyObject *filename, Py_ssize_t count) if (middle == NULL) { return NULL; } - result = PyUnicode_FromFormat("<%U-%d>", middle, count); + result = PyUnicode_FromFormat("<%U-%zd>", middle, count); Py_DECREF(middle); } else { result = PyUnicode_FromFormat( - "%U-%d", filename, count); + "%U-%zd", filename, count); } return result; From bbf7fb2c15a1dc9a54d10937c3d0831b0968257d Mon Sep 17 00:00:00 2001 From: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:59:48 +0800 Subject: [PATCH 348/775] gh-146615: Fix format specifiers in Objects/ directory (GH-146620) --- Objects/descrobject.c | 2 +- Objects/enumobject.c | 2 +- Objects/exceptions.c | 4 ++-- Objects/funcobject.c | 4 ++-- Objects/memoryobject.c | 2 +- Objects/typeobject.c | 8 ++++---- Objects/typevarobject.c | 2 +- Objects/unicodeobject.c | 6 +++--- Objects/unionobject.c | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 517d9e9fa9d..a5926616eeb 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1610,7 +1610,7 @@ property_set_name(PyObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) != 2) { PyErr_Format( PyExc_TypeError, - "__set_name__() takes 2 positional arguments but %d were given", + "__set_name__() takes 2 positional arguments but %zd were given", PyTuple_GET_SIZE(args)); return NULL; } diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 597b4c94dbf..364d508dd01 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -148,7 +148,7 @@ enumerate_vectorcall(PyObject *type, PyObject *const *args, } PyErr_Format(PyExc_TypeError, - "enumerate() takes at most 2 arguments (%d given)", nargs + nkwargs); + "enumerate() takes at most 2 arguments (%zd given)", nargs + nkwargs); return NULL; } diff --git a/Objects/exceptions.c b/Objects/exceptions.c index c4a591e2cf7..5e5e87cd6d7 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -935,7 +935,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!PyExceptionInstance_Check(exc)) { PyErr_Format( PyExc_ValueError, - "Item %d of second argument (exceptions) is not an exception", + "Item %zd of second argument (exceptions) is not an exception", i); goto error; } @@ -1714,7 +1714,7 @@ PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs) PyObject *exc = PyList_GET_ITEM(excs, i); if (exc == NULL || !(PyExceptionInstance_Check(exc) || Py_IsNone(exc))) { PyErr_Format(PyExc_TypeError, - "item %d of excs is not an exception", i); + "item %zd of excs is not an exception", i); return NULL; } } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 585c7b9a854..d47c78b933b 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -657,7 +657,7 @@ func_set_code(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) if (nclosure != nfree) { PyErr_Format(PyExc_ValueError, "%U() requires a code object with %zd free vars," - " not %zd", + " not %d", op->func_name, nclosure, nfree); return -1; @@ -1044,7 +1044,7 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure); if (code->co_nfreevars != nclosure) return PyErr_Format(PyExc_ValueError, - "%U requires closure of length %zd, not %zd", + "%U requires closure of length %d, not %zd", code->co_name, code->co_nfreevars, nclosure); if (nclosure) { Py_ssize_t i; diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 00e7955d151..bca77851ac2 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2472,7 +2472,7 @@ ptr_from_tuple(const Py_buffer *view, PyObject *tup) if (nindices > view->ndim) { PyErr_Format(PyExc_TypeError, - "cannot index %zd-dimension view with %zd-element tuple", + "cannot index %d-dimension view with %zd-element tuple", view->ndim, nindices); return NULL; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 6ceeb7dda08..b19aee6338d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5184,28 +5184,28 @@ check_basicsize_includes_size_and_offsets(PyTypeObject* type) if (type->tp_base && type->tp_base->tp_basicsize > type->tp_basicsize) { PyErr_Format(PyExc_TypeError, - "tp_basicsize for type '%s' (%d) is too small for base '%s' (%d)", + "tp_basicsize for type '%s' (%zd) is too small for base '%s' (%zd)", type->tp_name, type->tp_basicsize, type->tp_base->tp_name, type->tp_base->tp_basicsize); return 0; } if (type->tp_weaklistoffset + (Py_ssize_t)sizeof(PyObject*) > max) { PyErr_Format(PyExc_TypeError, - "weaklist offset %d is out of bounds for type '%s' (tp_basicsize = %d)", + "weaklist offset %zd is out of bounds for type '%s' (tp_basicsize = %zd)", type->tp_weaklistoffset, type->tp_name, type->tp_basicsize); return 0; } if (type->tp_dictoffset + (Py_ssize_t)sizeof(PyObject*) > max) { PyErr_Format(PyExc_TypeError, - "dict offset %d is out of bounds for type '%s' (tp_basicsize = %d)", + "dict offset %zd is out of bounds for type '%s' (tp_basicsize = %zd)", type->tp_dictoffset, type->tp_name, type->tp_basicsize); return 0; } if (type->tp_vectorcall_offset + (Py_ssize_t)sizeof(vectorcallfunc*) > max) { PyErr_Format(PyExc_TypeError, - "vectorcall offset %d is out of bounds for type '%s' (tp_basicsize = %d)", + "vectorcall offset %zd is out of bounds for type '%s' (tp_basicsize = %zd)", type->tp_vectorcall_offset, type->tp_name, type->tp_basicsize); return 0; diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index a206bd7b5dd..b5413ee37a9 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -818,7 +818,7 @@ typevar_typing_prepare_subst_impl(typevarobject *self, PyObject *alias, } Py_DECREF(params); PyErr_Format(PyExc_TypeError, - "Too few arguments for %S; actual %d, expected at least %d", + "Too few arguments for %S; actual %zd, expected at least %zd", alias, args_len, i + 1); return NULL; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index daf4651c431..35bd88d6254 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -8350,7 +8350,7 @@ charmap_decode_mapping(const char *s, goto Undefined; if (value < 0 || value > MAX_UNICODE) { PyErr_Format(PyExc_TypeError, - "character mapping must be in range(0x%x)", + "character mapping must be in range(0x%lx)", (unsigned long)MAX_UNICODE + 1); goto onError; } @@ -9141,8 +9141,8 @@ charmaptranslate_lookup(Py_UCS4 c, PyObject *mapping, PyObject **result, Py_UCS4 long value = PyLong_AsLong(x); if (value < 0 || value > MAX_UNICODE) { PyErr_Format(PyExc_ValueError, - "character mapping must be in range(0x%x)", - MAX_UNICODE+1); + "character mapping must be in range(0x%lx)", + (unsigned long)MAX_UNICODE + 1); Py_DECREF(x); return -1; } diff --git a/Objects/unionobject.c b/Objects/unionobject.c index a47d6193d70..d33d581f049 100644 --- a/Objects/unionobject.c +++ b/Objects/unionobject.c @@ -61,7 +61,7 @@ union_hash(PyObject *self) } // The unhashable values somehow became hashable again. Still raise // an error. - PyErr_Format(PyExc_TypeError, "union contains %d unhashable elements", n); + PyErr_Format(PyExc_TypeError, "union contains %zd unhashable elements", n); return -1; } return PyObject_Hash(alias->hashable_args); From b4fac15613a16f9cd7b2ee32840523b399f4621f Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Tue, 31 Mar 2026 10:57:07 +0200 Subject: [PATCH 349/775] gh-145458: use `self.skip_idle` consistently in the tachyon profiler (#145459) --- Lib/profiling/sampling/stack_collector.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/profiling/sampling/stack_collector.py b/Lib/profiling/sampling/stack_collector.py index 05ebe4d9764..31102d3eb0f 100644 --- a/Lib/profiling/sampling/stack_collector.py +++ b/Lib/profiling/sampling/stack_collector.py @@ -19,9 +19,9 @@ def __init__(self, sample_interval_usec, *, skip_idle=False): self.sample_interval_usec = sample_interval_usec self.skip_idle = skip_idle - def collect(self, stack_frames, timestamps_us=None, skip_idle=False): + def collect(self, stack_frames, timestamps_us=None): weight = len(timestamps_us) if timestamps_us else 1 - for frames, thread_id in self._iter_stacks(stack_frames, skip_idle=skip_idle): + for frames, thread_id in self._iter_stacks(stack_frames, skip_idle=self.skip_idle): self.process_frames(frames, thread_id, weight=weight) def process_frames(self, frames, thread_id, weight=1): @@ -88,7 +88,7 @@ def __init__(self, *args, **kwargs): # Per-thread statistics self.per_thread_stats = {} # {thread_id: {has_gil, on_cpu, gil_requested, unknown, has_exception, total, gc_samples}} - def collect(self, stack_frames, timestamps_us=None, skip_idle=False): + def collect(self, stack_frames, timestamps_us=None): """Override to track thread status statistics before processing frames.""" # Weight is number of timestamps (samples with identical stack) weight = len(timestamps_us) if timestamps_us else 1 @@ -123,7 +123,7 @@ def collect(self, stack_frames, timestamps_us=None, skip_idle=False): self.per_thread_stats[thread_id][key] += value * weight # Call parent collect to process frames - super().collect(stack_frames, timestamps_us, skip_idle=skip_idle) + super().collect(stack_frames, timestamps_us) def set_stats(self, sample_interval_usec, duration_sec, sample_rate, error_rate=None, missed_samples=None, mode=None): From 67354b2925e28b3bcc6e5b52bf92cd5f4cc69d3c Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Tue, 31 Mar 2026 13:02:35 +0200 Subject: [PATCH 350/775] gh-145563: Add thread-safety annotation for PyCapsule C-API (#146612) --- Doc/data/threadsafety.dat | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/Doc/data/threadsafety.dat b/Doc/data/threadsafety.dat index afb053adf5c..82edd1167ef 100644 --- a/Doc/data/threadsafety.dat +++ b/Doc/data/threadsafety.dat @@ -123,4 +123,33 @@ PyByteArray_GET_SIZE:atomic: # Raw data - no locking; mutating it is unsafe if the bytearray object is shared between threads PyByteArray_AsString:compatible: -PyByteArray_AS_STRING:compatible: \ No newline at end of file +PyByteArray_AS_STRING:compatible: + +# Capsule objects (Doc/c-api/capsule.rst) + +# Type check - read ob_type pointer, always safe +PyCapsule_CheckExact:atomic: + +# Creation - pure allocation, no shared state +PyCapsule_New:atomic: + +# Validation - reads pointer and name fields; safe on distinct objects +PyCapsule_IsValid:distinct: + +# Getters - read struct fields; safe on distinct objects but +# concurrent access to the same capsule requires external synchronization +PyCapsule_GetPointer:distinct: +PyCapsule_GetName:distinct: +PyCapsule_GetDestructor:distinct: +PyCapsule_GetContext:distinct: + +# Setters - write struct fields; safe on distinct objects but +# concurrent access to the same capsule requires external synchronization +PyCapsule_SetPointer:distinct: +PyCapsule_SetName:distinct: +PyCapsule_SetDestructor:distinct: +PyCapsule_SetContext:distinct: + +# Import - looks up a capsule from a module attribute and +# calls PyCapsule_GetPointer; may call arbitrary code +PyCapsule_Import:compatible: From 829e4d0b14e077b9a8dac2877483c261aa4bbe1a Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:45:23 +0300 Subject: [PATCH 351/775] gh-141510: Support `frozendict` in `plistlib` (#145590) Co-authored-by: Victor Stinner --- Doc/library/plistlib.rst | 2 +- Doc/whatsnew/3.15.rst | 3 ++- Lib/plistlib.py | 16 ++++++++-------- Lib/test/test_plistlib.py | 19 +++++++++++++++++++ ...-03-21-16-03-16.gh-issue-141510.tKptA7.rst | 2 ++ 5 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst index fa15cd4267e..72140e41675 100644 --- a/Doc/library/plistlib.rst +++ b/Doc/library/plistlib.rst @@ -18,7 +18,7 @@ and XML plist files. The property list (``.plist``) file format is a simple serialization supporting basic object types, like dictionaries, lists, numbers and strings. Usually the -top level object is a dictionary. +top level object is a dictionary or a frozen dictionary. To write out and to parse a plist file, use the :func:`dump` and :func:`load` functions. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 462482c8012..97937892de3 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -217,7 +217,8 @@ For example:: The following standard library modules have been updated to accept :class:`!frozendict`: :mod:`copy`, :mod:`decimal`, :mod:`json`, :mod:`marshal`, -:mod:`pickle`, :mod:`pprint` and :mod:`xml.etree.ElementTree`. +:mod:`plistlib` (only for serialization), :mod:`pickle`, :mod:`pprint` and +:mod:`xml.etree.ElementTree`. :func:`eval` and :func:`exec` accept :class:`!frozendict` for *globals*, and :func:`type` and :meth:`str.maketrans` accept :class:`!frozendict` for *dict*. diff --git a/Lib/plistlib.py b/Lib/plistlib.py index 01c7aa96261..93f3ef5e38a 100644 --- a/Lib/plistlib.py +++ b/Lib/plistlib.py @@ -2,7 +2,7 @@ The property list (.plist) file format is a simple XML pickle supporting basic object types, like dictionaries, lists, numbers and strings. -Usually the top level object is a dictionary. +Usually the top level object is a dictionary or a frozen dictionary. To write out a plist file, use the dump(value, file) function. 'value' is the top level object, 'file' is @@ -357,7 +357,7 @@ def write_value(self, value): elif isinstance(value, float): self.simple_element("real", repr(value)) - elif isinstance(value, dict): + elif isinstance(value, (dict, frozendict)): self.write_dict(value) elif isinstance(value, (bytes, bytearray)): @@ -715,7 +715,7 @@ def _flatten(self, value): self._objidtable[id(value)] = refnum # And finally recurse into containers - if isinstance(value, dict): + if isinstance(value, (dict, frozendict)): keys = [] values = [] items = value.items() @@ -836,7 +836,7 @@ def _write_object(self, value): self._write_size(0xA0, s) self._fp.write(struct.pack('>' + self._ref_format * s, *refs)) - elif isinstance(value, dict): + elif isinstance(value, (dict, frozendict)): keyRefs, valRefs = [], [] if self._sort_keys: @@ -869,18 +869,18 @@ def _is_fmt_binary(header): # Generic bits # -_FORMATS={ - FMT_XML: dict( +_FORMATS=frozendict({ + FMT_XML: frozendict( detect=_is_fmt_xml, parser=_PlistParser, writer=_PlistWriter, ), - FMT_BINARY: dict( + FMT_BINARY: frozendict( detect=_is_fmt_binary, parser=_BinaryPlistParser, writer=_BinaryPlistWriter, ) -} +}) def load(fp, *, fmt=None, dict_type=dict, aware_datetime=False): diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py index d9216be4d95..b9c261310bb 100644 --- a/Lib/test/test_plistlib.py +++ b/Lib/test/test_plistlib.py @@ -792,6 +792,25 @@ def test_dict_members(self): }) self.assertIsNot(pl2['first'], pl2['second']) + def test_frozendict(self): + pl = frozendict( + aString="Doodah", + anInt=728, + aDict=frozendict( + anotherString="hello", + aTrueValue=True, + ), + aList=["A", "B", 12], + ) + + for fmt in ALL_FORMATS: + with self.subTest(fmt=fmt): + data = plistlib.dumps(pl, fmt=fmt) + pl2 = plistlib.loads(data) + self.assertEqual(pl2, dict(pl)) + self.assertIsInstance(pl2, dict) + self.assertIsInstance(pl2['aDict'], dict) + def test_controlcharacters(self): for i in range(128): c = chr(i) diff --git a/Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst b/Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst new file mode 100644 index 00000000000..19c30f11b33 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst @@ -0,0 +1,2 @@ +Support :class:`frozendict` in :mod:`plistlib`, for serialization only. +Patch by Hugo van Kemenade. From db5936c5b89aa19e04d63120e0cf5bbc73bf2420 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 31 Mar 2026 16:17:49 +0300 Subject: [PATCH 352/775] gh-143050: Correct PyLong_FromString() to use _PyLong_Negate() (#145901) The long_from_string_base() might return a small integer, when the _pylong.py is used to do conversion. Hence, we must be careful here to not smash it "small int" bit by using the _PyLong_FlipSign(). Co-authored-by: Victor Stinner --- Include/internal/pycore_long.h | 18 +++++++++++++++++- Lib/test/test_capi/test_long.py | 10 ++++++++++ Modules/_testcapi/immortal.c | 4 ++-- Objects/longobject.c | 20 +++++--------------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 4386e8bcad8..5ef9cc410e4 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -232,6 +232,20 @@ _PyLong_IsPositive(const PyLongObject *op) return (op->long_value.lv_tag & SIGN_MASK) == 0; } +/* Return true if the argument is a small int */ +static inline bool +_PyLong_IsSmallInt(const PyLongObject *op) +{ + assert(PyLong_Check(op)); + bool is_small_int = (op->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; + assert(PyLong_CheckExact(op) || (!is_small_int)); + assert(_Py_IsImmortal(op) || (!is_small_int)); + assert((_PyLong_IsCompact(op) + && _PY_IS_SMALL_INT(_PyLong_CompactValue(op))) + || (!is_small_int)); + return is_small_int; +} + static inline Py_ssize_t _PyLong_DigitCount(const PyLongObject *op) { @@ -293,7 +307,9 @@ _PyLong_SetDigitCount(PyLongObject *op, Py_ssize_t size) #define NON_SIZE_MASK ~(uintptr_t)((1 << NON_SIZE_BITS) - 1) static inline void -_PyLong_FlipSign(PyLongObject *op) { +_PyLong_FlipSign(PyLongObject *op) +{ + assert(!_PyLong_IsSmallInt(op)); unsigned int flipped_sign = 2 - (op->long_value.lv_tag & SIGN_MASK); op->long_value.lv_tag &= NON_SIZE_MASK; op->long_value.lv_tag |= flipped_sign; diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index d3156645eee..fc0454b71cb 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -803,6 +803,16 @@ def to_digits(num): self.assertEqual(pylongwriter_create(negative, digits), num, (negative, digits)) + def test_bug_143050(self): + with support.adjust_int_max_str_digits(0): + # Bug coming from using _pylong.int_from_string(), that + # currently requires > 6000 decimal digits. + int('-' + '0' * 7000, 10) + _testcapi.test_immortal_small_ints() + # Test also nonzero small int + int('-' + '0' * 7000 + '123', 10) + _testcapi.test_immortal_small_ints() + if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapi/immortal.c b/Modules/_testcapi/immortal.c index af510cab655..1c87025594a 100644 --- a/Modules/_testcapi/immortal.c +++ b/Modules/_testcapi/immortal.c @@ -31,13 +31,13 @@ test_immortal_small_ints(PyObject *self, PyObject *Py_UNUSED(ignored)) for (int i = -5; i <= 1024; i++) { PyObject *obj = PyLong_FromLong(i); assert(verify_immortality(obj)); - int has_int_immortal_bit = ((PyLongObject *)obj)->long_value.lv_tag & IMMORTALITY_BIT_MASK; + int has_int_immortal_bit = _PyLong_IsSmallInt((PyLongObject *)obj); assert(has_int_immortal_bit); } for (int i = 1025; i <= 1030; i++) { PyObject *obj = PyLong_FromLong(i); assert(obj); - int has_int_immortal_bit = ((PyLongObject *)obj)->long_value.lv_tag & IMMORTALITY_BIT_MASK; + int has_int_immortal_bit = _PyLong_IsSmallInt((PyLongObject *)obj); assert(!has_int_immortal_bit); Py_DECREF(obj); } diff --git a/Objects/longobject.c b/Objects/longobject.c index 0d3ea9bc46c..d416fc1747e 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3119,11 +3119,11 @@ PyLong_FromString(const char *str, char **pend, int base) } /* Set sign and normalize */ - if (sign < 0) { - _PyLong_FlipSign(z); - } long_normalize(z); z = maybe_small_long(z); + if (sign < 0) { + _PyLong_Negate(&z); + } if (pend != NULL) { *pend = (char *)str; @@ -3623,21 +3623,11 @@ long_richcompare(PyObject *self, PyObject *other, int op) Py_RETURN_RICHCOMPARE(result, 0, op); } -static inline int -/// Return 1 if the object is one of the immortal small ints -_long_is_small_int(PyObject *op) -{ - PyLongObject *long_object = (PyLongObject *)op; - int is_small_int = (long_object->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; - assert((!is_small_int) || PyLong_CheckExact(op)); - return is_small_int; -} - void _PyLong_ExactDealloc(PyObject *self) { assert(PyLong_CheckExact(self)); - if (_long_is_small_int(self)) { + if (_PyLong_IsSmallInt((PyLongObject *)self)) { // See PEP 683, section Accidental De-Immortalizing for details _Py_SetImmortal(self); return; @@ -3652,7 +3642,7 @@ _PyLong_ExactDealloc(PyObject *self) static void long_dealloc(PyObject *self) { - if (_long_is_small_int(self)) { + if (_PyLong_IsSmallInt((PyLongObject *)self)) { /* This should never get called, but we also don't want to SEGV if * we accidentally decref small Ints out of existence. Instead, * since small Ints are immortal, re-set the reference count. From 362145c20ebb08d2f850a49d356ecee858a281ae Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Tue, 31 Mar 2026 23:25:54 +0800 Subject: [PATCH 353/775] gh-139109: Document the trace recording interpreter in internaldocs (GH-146110) --- InternalDocs/jit.md | 57 ++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/InternalDocs/jit.md b/InternalDocs/jit.md index decfccad2d8..1345f2db8b3 100644 --- a/InternalDocs/jit.md +++ b/InternalDocs/jit.md @@ -11,24 +11,54 @@ # The JIT Historically, the adaptive interpreter was referred to as `tier 1` and the JIT as `tier 2`. You will see remnants of this in the code. -## The Optimizer and Executors +## The Trace Recorder and Executors -The program begins running on the adaptive interpreter, until a `JUMP_BACKWARD` -instruction determines that it is "hot" because the counter in its +There are two interpreters in this section: + 1. Adaptive interpreter (the default behavior) + 2. Trace recording interpreter (enabled on JIT builds) + +The program begins running on the adaptive interpreter, until a `JUMP_BACKWARD` or +`RESUME` instruction determines that it is "hot" because the counter in its [inline cache](interpreter.md#inline-cache-entries) indicates that it executed more than some threshold number of times (see [`backoff_counter_triggers`](../Include/internal/pycore_backoff.h)). -It then calls the function `_PyOptimizer_Optimize()` in +It then calls the function `_PyJit_TryInitializeTracing` in [`Python/optimizer.c`](../Python/optimizer.c), passing it the current -[frame](frames.md) and instruction pointer. `_PyOptimizer_Optimize()` -constructs an object of type -[`_PyExecutorObject`](../Include/internal/pycore_optimizer.h) which implements -an optimized version of the instruction trace beginning at this jump. +[frame](frames.md), instruction pointer and state. +The interpreter then switches into "tracing mode" via the macro +`ENTER_TRACING()`. On platforms that support computed goto and tail-calling +interpreters, the dispatch table is swapped out, while other platforms that do +not support either use a single flag in the opcode. +Execution between the normal interpreter and tracing interpreter are +interleaved via this dispatch mechanism. This means that while logically +there are two interpreters, the implementation appears to be a single +interpreter. -The optimizer determines where the trace ends, and the executor is set up +During tracing mode, after each interpreter instruction's `DISPATCH()`, +the interpreter jumps to the `TRACE_RECORD` instruction. This instruction +records the previous instruction executed and also any live values of the next +operation it may require. It then translates the previous instruction to +a sequence of micro-ops using `_PyJit_translate_single_bytecode_to_trace`. +To ensure that the adaptive interpreter instructions +and cache entries are up-to-date, the trace recording interpreter always resets +the adaptive counters of adaptive instructions it sees. +This forces a re-specialization of any new instruction should an instruction +deoptimize. Thus, feeding the trace recorder up-to-date information. +Finally, the `TRACE_RECORD` instruction decides when to stop tracing +using various heuristics. + +Once trace recording concludes, `LEAVE_TRACING()` swaps out the dispatch +table/the opcode flag set earlier by `ENTER_TRACING()` is unset. +`stop_tracing_and_jit()` then calls `_PyOptimizer_Optimize()` which optimizes +the trace and constructs an +[`_PyExecutorObject`](../Include/internal/pycore_optimizer.h). + +JIT execution is set up to either return to the adaptive interpreter and resume execution, or transfer control to another executor (see `_PyExitData` in -Include/internal/pycore_optimizer.h). +Include/internal/pycore_optimizer.h). When resuming to the adaptive interpreter, +a "side exit", generated by an `EXIT_IF` may trigger recording of another trace. +While a "deopt", generated by a `DEOPT_IF`, does not trigger recording. The executor is stored on the [`code object`](code_objects.md) of the frame, in the `co_executors` field which is an array of executors. The start @@ -40,12 +70,7 @@ ## The micro-op optimizer The micro-op (abbreviated `uop` to approximate `μop`) optimizer is defined in [`Python/optimizer.c`](../Python/optimizer.c) as `_PyOptimizer_Optimize`. -It translates an instruction trace into a sequence of micro-ops by replacing -each bytecode by an equivalent sequence of micro-ops (see -`_PyOpcode_macro_expansion` in -[pycore_opcode_metadata.h](../Include/internal/pycore_opcode_metadata.h) -which is generated from [`Python/bytecodes.c`](../Python/bytecodes.c)). -The micro-op sequence is then optimized by +It takes a micro-op sequence from the trace recorder and optimizes with `_Py_uop_analyze_and_optimize` in [`Python/optimizer_analysis.c`](../Python/optimizer_analysis.c) and an instance of `_PyUOpExecutor_Type` is created to contain it. From 62a6e898e017c9878490544f6a227b8a187a949c Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 31 Mar 2026 19:27:52 +0200 Subject: [PATCH 354/775] gh-147856: Allow the 'count' argument of `bytes.replace()` to be a keyword (#147943) --- Doc/library/stdtypes.rst | 12 +++-- Doc/whatsnew/3.15.rst | 3 ++ Lib/test/test_bytes.py | 7 +++ ...-03-31-18-07-53.gh-issue-147856.62Dwee.rst | 1 + Objects/bytearrayobject.c | 9 ++-- Objects/bytesobject.c | 9 ++-- Objects/clinic/bytearrayobject.c.h | 51 +++++++++++++++---- Objects/clinic/bytesobject.c.h | 51 +++++++++++++++---- Objects/clinic/unicodeobject.c.h | 6 +-- Objects/unicodeobject.c | 7 ++- 10 files changed, 115 insertions(+), 41 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 69152788616..2099ef56169 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3735,12 +3735,13 @@ arbitrary binary data. The separator to search for may be any :term:`bytes-like object`. -.. method:: bytes.replace(old, new, count=-1, /) - bytearray.replace(old, new, count=-1, /) +.. method:: bytes.replace(old, new, /, count=-1) + bytearray.replace(old, new, /, count=-1) Return a copy of the sequence with all occurrences of subsequence *old* - replaced by *new*. If the optional argument *count* is given, only the - first *count* occurrences are replaced. + replaced by *new*. If *count* is given, only the first *count* occurrences + are replaced. If *count* is not specified or ``-1``, then all occurrences + are replaced. The subsequence to search for and its replacement may be any :term:`bytes-like object`. @@ -3750,6 +3751,9 @@ arbitrary binary data. The bytearray version of this method does *not* operate in place - it always produces a new object, even if no changes were made. + .. versionchanged:: next + *count* is now supported as a keyword argument. + .. method:: bytes.rfind(sub[, start[, end]]) bytearray.rfind(sub[, start[, end]]) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 97937892de3..c8c28371587 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -605,6 +605,9 @@ Other language changes respectively. (Contributed by Sergey B Kirpichev in :gh:`146151`.) +* Allow the *count* argument of :meth:`bytes.replace` to be a keyword. + (Contributed by Stan Ulbrych in :gh:`147856`.) + New modules =========== diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index df22d5cd96e..120b611ba9c 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -878,6 +878,13 @@ def test_replace(self): self.assertEqual(b.replace(b'i', b'a'), b'massassappa') self.assertEqual(b.replace(b'ss', b'x'), b'mixixippi') + def test_replace_count_keyword(self): + b = self.type2test(b'aa') + self.assertEqual(b.replace(b'a', b'b', count=0), b'aa') + self.assertEqual(b.replace(b'a', b'b', count=1), b'ba') + self.assertEqual(b.replace(b'a', b'b', count=2), b'bb') + self.assertEqual(b.replace(b'a', b'b', count=3), b'bb') + def test_replace_int_error(self): self.assertRaises(TypeError, self.type2test(b'a b').replace, 32, b'') diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst new file mode 100644 index 00000000000..67ebd57b3a5 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst @@ -0,0 +1 @@ +Allow the *count* argument of :meth:`bytes.replace` to be a keyword. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index e2fea94e099..552f7144c0d 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1752,27 +1752,26 @@ bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to) /*[clinic input] -@permit_long_docstring_body @critical_section bytearray.replace old: Py_buffer new: Py_buffer + / count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. - / Return a copy with all occurrences of substring old replaced by new. -If the optional argument count is given, only the first count occurrences are -replaced. +If count is given, only the first count occurrences are replaced. +If count is not specified or -1, then all occurrences are replaced. [clinic start generated code]*/ static PyObject * bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=d39884c4dc59412a input=66afec32f4e095e0]*/ +/*[clinic end generated code: output=d39884c4dc59412a input=e2591806f954aec3]*/ { return stringlib_replace((PyObject *)self, (const char *)old->buf, old->len, diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 00c1c63b8e0..b84ce2b53ef 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2403,26 +2403,25 @@ bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to) /*[clinic input] -@permit_long_docstring_body bytes.replace old: Py_buffer new: Py_buffer + / count: Py_ssize_t = -1 Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences. - / Return a copy with all occurrences of substring old replaced by new. -If the optional argument count is given, only the first count occurrences are -replaced. +If count is given, only the first count occurrences are replaced. +If count is not specified or -1, then all occurrences are replaced. [clinic start generated code]*/ static PyObject * bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=994fa588b6b9c104 input=8b99a9ab32bc06a2]*/ +/*[clinic end generated code: output=994fa588b6b9c104 input=cdf3cf8639297745]*/ { return stringlib_replace((PyObject *)self, (const char *)old->buf, old->len, diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index cf60d0ceadc..d173f45d7be 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -793,7 +793,7 @@ exit: } PyDoc_STRVAR(bytearray_replace__doc__, -"replace($self, old, new, count=-1, /)\n" +"replace($self, old, new, /, count=-1)\n" "--\n" "\n" "Return a copy with all occurrences of substring old replaced by new.\n" @@ -802,25 +802,56 @@ PyDoc_STRVAR(bytearray_replace__doc__, " Maximum number of occurrences to replace.\n" " -1 (the default value) means replace all occurrences.\n" "\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); +"If count is given, only the first count occurrences are replaced.\n" +"If count is not specified or -1, then all occurrences are replaced."); #define BYTEARRAY_REPLACE_METHODDEF \ - {"replace", _PyCFunction_CAST(bytearray_replace), METH_FASTCALL, bytearray_replace__doc__}, + {"replace", _PyCFunction_CAST(bytearray_replace), METH_FASTCALL|METH_KEYWORDS, bytearray_replace__doc__}, static PyObject * bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * -bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(count), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "count", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "replace", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; Py_buffer old = {NULL, NULL}; Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!_PyArg_CheckPositional("replace", nargs, 2, 3)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } if (PyObject_GetBuffer(args[0], &old, PyBUF_SIMPLE) != 0) { @@ -829,8 +860,8 @@ bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } - if (nargs < 3) { - goto skip_optional; + if (!noptargs) { + goto skip_optional_pos; } { Py_ssize_t ival = -1; @@ -844,7 +875,7 @@ bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } count = ival; } -skip_optional: +skip_optional_pos: Py_BEGIN_CRITICAL_SECTION(self); return_value = bytearray_replace_impl((PyByteArrayObject *)self, &old, &new, count); Py_END_CRITICAL_SECTION(); @@ -1835,4 +1866,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl((PyByteArrayObject *)self); } -/*[clinic end generated code: output=2d76ef023928424f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d4976faf6731b8da input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 00cf13d422d..99fcd48898c 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -789,7 +789,7 @@ exit: } PyDoc_STRVAR(bytes_replace__doc__, -"replace($self, old, new, count=-1, /)\n" +"replace($self, old, new, /, count=-1)\n" "--\n" "\n" "Return a copy with all occurrences of substring old replaced by new.\n" @@ -798,25 +798,56 @@ PyDoc_STRVAR(bytes_replace__doc__, " Maximum number of occurrences to replace.\n" " -1 (the default value) means replace all occurrences.\n" "\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); +"If count is given, only the first count occurrences are replaced.\n" +"If count is not specified or -1, then all occurrences are replaced."); #define BYTES_REPLACE_METHODDEF \ - {"replace", _PyCFunction_CAST(bytes_replace), METH_FASTCALL, bytes_replace__doc__}, + {"replace", _PyCFunction_CAST(bytes_replace), METH_FASTCALL|METH_KEYWORDS, bytes_replace__doc__}, static PyObject * bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); static PyObject * -bytes_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +bytes_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(count), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "count", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "replace", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; Py_buffer old = {NULL, NULL}; Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!_PyArg_CheckPositional("replace", nargs, 2, 3)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } if (PyObject_GetBuffer(args[0], &old, PyBUF_SIMPLE) != 0) { @@ -825,8 +856,8 @@ bytes_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) if (PyObject_GetBuffer(args[1], &new, PyBUF_SIMPLE) != 0) { goto exit; } - if (nargs < 3) { - goto skip_optional; + if (!noptargs) { + goto skip_optional_pos; } { Py_ssize_t ival = -1; @@ -840,7 +871,7 @@ bytes_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } count = ival; } -skip_optional: +skip_optional_pos: return_value = bytes_replace_impl((PyBytesObject *)self, &old, &new, count); exit: @@ -1411,4 +1442,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=08b9507244f73638 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5675f7008a84ce6d input=a9049054013a1b77]*/ diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h index 1819fbaea22..4b53e24fb7d 100644 --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -918,8 +918,8 @@ PyDoc_STRVAR(unicode_replace__doc__, " Maximum number of occurrences to replace.\n" " -1 (the default value) means replace all occurrences.\n" "\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); +"If count is given, only the first count occurrences are replaced.\n" +"If count is not specified or -1, then all occurrences are replaced."); #define UNICODE_REPLACE_METHODDEF \ {"replace", _PyCFunction_CAST(unicode_replace), METH_FASTCALL|METH_KEYWORDS, unicode_replace__doc__}, @@ -1908,4 +1908,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=238917fe66120bde input=a9049054013a1b77]*/ +/*[clinic end generated code: output=13eaf65699ea9fc9 input=a9049054013a1b77]*/ diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 35bd88d6254..a0a26a75129 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -12561,7 +12561,6 @@ PyUnicode_Replace(PyObject *str, } /*[clinic input] -@permit_long_docstring_body str.replace as unicode_replace old: unicode @@ -12573,14 +12572,14 @@ str.replace as unicode_replace Return a copy with all occurrences of substring old replaced by new. -If the optional argument count is given, only the first count occurrences are -replaced. +If count is given, only the first count occurrences are replaced. +If count is not specified or -1, then all occurrences are replaced. [clinic start generated code]*/ static PyObject * unicode_replace_impl(PyObject *self, PyObject *old, PyObject *new, Py_ssize_t count) -/*[clinic end generated code: output=b63f1a8b5eebf448 input=f27ca92ac46b65a1]*/ +/*[clinic end generated code: output=b63f1a8b5eebf448 input=d15a6886b05e2edc]*/ { return replace(self, old, new, count); } From 9e1f1644cd7b7661f0748bb37351836e8d6f37e2 Mon Sep 17 00:00:00 2001 From: Boy Steven Date: Wed, 1 Apr 2026 04:52:11 +0700 Subject: [PATCH 355/775] Docs: fill in descriptor C API docs (GH-146644) --- Doc/c-api/descriptor.rst | 89 +++++++++++++++++++++++++++++++++++----- Doc/tools/.nitignore | 1 - 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/Doc/c-api/descriptor.rst b/Doc/c-api/descriptor.rst index e23288c6a58..b913e24b3c7 100644 --- a/Doc/c-api/descriptor.rst +++ b/Doc/c-api/descriptor.rst @@ -8,13 +8,31 @@ Descriptor Objects "Descriptors" are objects that describe some attribute of an object. They are found in the dictionary of type objects. -.. XXX document these! - .. c:function:: PyObject* PyDescr_NewGetSet(PyTypeObject *type, struct PyGetSetDef *getset) + Create a new get-set descriptor for extension type *type* from the + :c:type:`PyGetSetDef` structure *getset*. -.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *meth) + Get-set descriptors expose attributes implemented by C getter and setter + functions rather than stored directly in the instance. This is the same kind + of descriptor created for entries in :c:member:`~PyTypeObject.tp_getset`, and + it appears in Python as a :class:`types.GetSetDescriptorType` object. + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. + +.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *member) + + Create a new member descriptor for extension type *type* from the + :c:type:`PyMemberDef` structure *member*. + + Member descriptors expose fields in the type's C struct as Python + attributes. This is the same kind of descriptor created for entries in + :c:member:`~PyTypeObject.tp_members`, and it appears in Python as a + :class:`types.MemberDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:var:: PyTypeObject PyMemberDescr_Type @@ -30,22 +48,53 @@ found in the dictionary of type objects. The type object for get/set descriptor objects created from :c:type:`PyGetSetDef` structures. These descriptors implement attributes whose value is computed by C getter and setter functions, and are used - for many built-in type attributes. + for many built-in type attributes. They correspond to + :class:`types.GetSetDescriptorType` objects in Python. .. c:function:: PyObject* PyDescr_NewMethod(PyTypeObject *type, struct PyMethodDef *meth) + Create a new method descriptor for extension type *type* from the + :c:type:`PyMethodDef` structure *meth*. + + Method descriptors expose C functions as methods on a type. This is the same + kind of descriptor created for entries in + :c:member:`~PyTypeObject.tp_methods`, and it appears in Python as a + :class:`types.MethodDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:var:: PyTypeObject PyMethodDescr_Type The type object for method descriptor objects created from :c:type:`PyMethodDef` structures. These descriptors expose C functions as - methods on a type, and correspond to :class:`types.MemberDescriptorType` + methods on a type, and correspond to :class:`types.MethodDescriptorType` objects in Python. -.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *wrapper, void *wrapped) +.. c:struct:: wrapperbase + Describes a slot wrapper used by :c:func:`PyDescr_NewWrapper`. + + Each ``wrapperbase`` record stores the Python-visible name and metadata for a + special method implemented by a type slot, together with the wrapper + function used to adapt that slot to Python's calling convention. + +.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped) + + Create a new wrapper descriptor for extension type *type* from the + :c:struct:`wrapperbase` structure *base* and the wrapped slot function + pointer + *wrapped*. + + Wrapper descriptors expose special methods implemented by type slots. This + is the same kind of descriptor that CPython creates for slot-based special + methods such as ``__repr__`` or ``__add__``, and it appears in Python as a + :class:`types.WrapperDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:var:: PyTypeObject PyWrapperDescr_Type @@ -58,6 +107,16 @@ found in the dictionary of type objects. .. c:function:: PyObject* PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method) + Create a new class method descriptor for extension type *type* from the + :c:type:`PyMethodDef` structure *method*. + + Class method descriptors expose C methods that receive the class rather than + an instance when accessed. This is the same kind of descriptor created for + ``METH_CLASS`` entries in :c:member:`~PyTypeObject.tp_methods`, and it + appears in Python as a :class:`types.ClassMethodDescriptorType` object. + + On success, return a :term:`strong reference` to the descriptor. Return + ``NULL`` with an exception set on failure. .. c:function:: int PyDescr_IsData(PyObject *descr) @@ -66,8 +125,18 @@ found in the dictionary of type objects. no error checking. -.. c:function:: PyObject* PyWrapper_New(PyObject *, PyObject *) +.. c:function:: PyObject* PyWrapper_New(PyObject *d, PyObject *self) + Create a new bound wrapper object from the wrapper descriptor *d* and the + instance *self*. + + This is the bound form of a wrapper descriptor created by + :c:func:`PyDescr_NewWrapper`. CPython creates these objects when a slot + wrapper is accessed through an instance, and they appear in Python as + :class:`types.MethodWrapperType` objects. + + On success, return a :term:`strong reference` to the wrapper object. Return + ``NULL`` with an exception set on failure. .. c:macro:: PyDescr_COMMON @@ -104,9 +173,9 @@ Built-in descriptors .. c:var:: PyTypeObject PyClassMethodDescr_Type The type object for C-level class method descriptor objects. - This is the type of the descriptors created for :func:`classmethod` defined in - C extension types, and is the same object as :class:`classmethod` - in Python. + This is the type of the descriptors created for :func:`classmethod` defined + in C extension types, and corresponds to + :class:`types.ClassMethodDescriptorType` objects in Python. .. c:function:: PyObject *PyClassMethod_New(PyObject *callable) diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index ffe98d332d6..189173a5f8a 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -2,7 +2,6 @@ # as tested on the CI via check-warnings.py in reusable-docs.yml. # Keep lines sorted lexicographically to help avoid merge conflicts. -Doc/c-api/descriptor.rst Doc/c-api/init_config.rst Doc/c-api/intro.rst Doc/c-api/stable.rst From 4497cf3aed587593199baadb83d68c3602ee99ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:43:58 +0300 Subject: [PATCH 356/775] build(deps): bump qs from 6.14.0 to 6.15.0 in /Platforms/emscripten/browser_test (#146048) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 42825e63870035f71f705a066e32e08550b593fc Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 1 Apr 2026 10:48:50 +0300 Subject: [PATCH 357/775] gh-146431: Add the wrapcol and ignorechars parameters for more Base XX codec (GH-146434) Add the wrapcol parameter to base64 functions b16encode(), b32encode(), b32hexencode(), b85encode() and z85encode(), and binascii functions b2a_base32() and b2a_base85(). Add the ignorechars parameter to base64 functions b16decode(), b32decode(), b32hexdecode(), b85decode() and z85decode(), and binascii functions a2b_hex(), unhexlify(), a2b_base32() and a2b_base85(). --- Doc/library/base64.rst | 79 +++- Doc/library/binascii.rst | 38 +- Doc/whatsnew/3.15.rst | 31 +- Lib/base64.py | 86 ++-- Lib/test/test_base64.py | 211 +++++++--- Lib/test/test_binascii.py | 143 +++++-- ...-03-25-21-08-51.gh-issue-146431.zERPwe.rst | 11 + Modules/binascii.c | 196 ++++++--- Modules/clinic/binascii.c.h | 395 ++++++++++++------ 9 files changed, 869 insertions(+), 321 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 771628677c3..1a1785cb587 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -146,13 +146,20 @@ POST request. Accepting the ``+`` and ``/`` characters is now deprecated. -.. function:: b32encode(s) +.. function:: b32encode(s, *, wrapcol=0) Encode the :term:`bytes-like object` *s* using Base32 and return the encoded :class:`bytes`. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. -.. function:: b32decode(s, casefold=False, map01=None) + .. versionchanged:: next + Added the *wrapcol* parameter. + + +.. function:: b32decode(s, casefold=False, map01=None, *, ignorechars=b'') Decode the Base32 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -168,20 +175,29 @@ POST request. digit 0 is always mapped to the letter O). For security purposes the default is ``None``, so that 0 and 1 are not allowed in the input. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + A :exc:`binascii.Error` is raised if *s* is incorrectly padded or if there are non-alphabet characters present in the input. + .. versionchanged:: next + Added the *ignorechars* parameter. -.. function:: b32hexencode(s) + +.. function:: b32hexencode(s, *, wrapcol=0) Similar to :func:`b32encode` but uses the Extended Hex Alphabet, as defined in :rfc:`4648`. .. versionadded:: 3.10 + .. versionchanged:: next + Added the *wrapcol* parameter. -.. function:: b32hexdecode(s, casefold=False) + +.. function:: b32hexdecode(s, casefold=False, *, ignorechars=b'') Similar to :func:`b32decode` but uses the Extended Hex Alphabet, as defined in :rfc:`4648`. @@ -193,14 +209,24 @@ POST request. .. versionadded:: 3.10 + .. versionchanged:: next + Added the *ignorechars* parameter. -.. function:: b16encode(s) + +.. function:: b16encode(s, *, wrapcol=0) Encode the :term:`bytes-like object` *s* using Base16 and return the encoded :class:`bytes`. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. -.. function:: b16decode(s, casefold=False) + .. versionchanged:: next + Added the *wrapcol* parameter. + + +.. function:: b16decode(s, casefold=False, *, ignorechars=b'') Decode the Base16 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -209,10 +235,17 @@ POST request. lowercase alphabet is acceptable as input. For security purposes, the default is ``False``. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + A :exc:`binascii.Error` is raised if *s* is incorrectly padded or if there are non-alphabet characters present in the input. + .. versionchanged:: next + Added the *ignorechars* parameter. + + .. _base64-base-85: Base85 Encodings @@ -277,7 +310,7 @@ Refer to the documentation of the individual functions for more information. .. versionadded:: 3.4 -.. function:: b85encode(b, pad=False) +.. function:: b85encode(b, pad=False, *, wrapcol=0) Encode the :term:`bytes-like object` *b* using base85 (as used in e.g. git-style binary diffs) and return the encoded :class:`bytes`. @@ -285,19 +318,32 @@ Refer to the documentation of the individual functions for more information. If *pad* is true, the input is padded with ``b'\0'`` so its length is a multiple of 4 bytes before encoding. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. + .. versionadded:: 3.4 + .. versionchanged:: next + Added the *wrapcol* parameter. -.. function:: b85decode(b) + +.. function:: b85decode(b, *, ignorechars=b'') Decode the base85-encoded :term:`bytes-like object` or ASCII string *b* and return the decoded :class:`bytes`. Padding is implicitly removed, if necessary. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + .. versionadded:: 3.4 + .. versionchanged:: next + Added the *ignorechars* parameter. -.. function:: z85encode(s, pad=False) + +.. function:: z85encode(s, pad=False, *, wrapcol=0) Encode the :term:`bytes-like object` *s* using Z85 (as used in ZeroMQ) and return the encoded :class:`bytes`. See `Z85 specification @@ -306,20 +352,33 @@ Refer to the documentation of the individual functions for more information. If *pad* is true, the input is padded with ``b'\0'`` so its length is a multiple of 4 bytes before encoding. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not add any newlines. + .. versionadded:: 3.13 .. versionchanged:: 3.15 The *pad* parameter was added. + .. versionchanged:: next + Added the *wrapcol* parameter. -.. function:: z85decode(s) + +.. function:: z85decode(s, *, ignorechars=b'') Decode the Z85-encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. See `Z85 specification `_ for more information. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + .. versionadded:: 3.13 + .. versionchanged:: next + Added the *ignorechars* parameter. + .. _base64-legacy: diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 64c1ce948d2..4a82d0742ae 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -101,7 +101,7 @@ The :mod:`!binascii` module defines the following functions: Added the *alphabet* and *wrapcol* parameters. -.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b"") +.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b'') Convert Ascii85 data back to binary and return the binary data. @@ -151,7 +151,7 @@ The :mod:`!binascii` module defines the following functions: .. versionadded:: 3.15 -.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET) +.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET, ignorechars=b'') Convert Base85 data back to binary and return the binary data. More than one line may be passed at a time. @@ -164,12 +164,15 @@ The :mod:`!binascii` module defines the following functions: Optional *alphabet* must be a :class:`bytes` object of length 85 which specifies an alternative alphabet. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + Invalid Base85 data will raise :exc:`binascii.Error`. .. versionadded:: 3.15 -.. function:: b2a_base85(data, /, *, alphabet=BASE85_ALPHABET, pad=False) +.. function:: b2a_base85(data, /, *, alphabet=BASE85_ALPHABET, wrapcol=0, pad=False) Convert binary data to a line of ASCII characters in Base85 coding. The return value is the converted line. @@ -177,13 +180,17 @@ The :mod:`!binascii` module defines the following functions: Optional *alphabet* must be a :term:`bytes-like object` of length 85 which specifies an alternative alphabet. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not insert any newlines. + If *pad* is true, the input is padded with ``b'\0'`` so its length is a multiple of 4 bytes before encoding. .. versionadded:: 3.15 -.. function:: a2b_base32(string, /, *, alphabet=BASE32_ALPHABET) +.. function:: a2b_base32(string, /, *, alphabet=BASE32_ALPHABET, ignorechars=b'') Convert base32 data back to binary and return the binary data. @@ -201,11 +208,17 @@ The :mod:`!binascii` module defines the following functions: Optional *alphabet* must be a :class:`bytes` object of length 32 which specifies an alternative alphabet. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + If *ignorechars* contains the pad character ``'='``, the pad characters + presented before the end of the encoded data and the excess pad characters + will be ignored. + Invalid base32 data will raise :exc:`binascii.Error`. .. versionadded:: next -.. function:: b2a_base32(data, /, *, alphabet=BASE32_ALPHABET) +.. function:: b2a_base32(data, /, *, alphabet=BASE32_ALPHABET, wrapcol=0) Convert binary data to a line of ASCII characters in base32 coding, as specified in :rfc:`4648`. The return value is the converted line. @@ -213,6 +226,10 @@ The :mod:`!binascii` module defines the following functions: Optional *alphabet* must be a :term:`bytes-like object` of length 32 which specifies an alternative alphabet. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character + after at most every *wrapcol* characters. + If *wrapcol* is zero (default), do not insert any newlines. + .. versionadded:: next .. function:: a2b_qp(data, header=False) @@ -288,18 +305,25 @@ The :mod:`!binascii` module defines the following functions: .. versionchanged:: 3.8 The *sep* and *bytes_per_sep* parameters were added. -.. function:: a2b_hex(hexstr) - unhexlify(hexstr) +.. function:: a2b_hex(hexstr, *, ignorechars=b'') + unhexlify(hexstr, *, ignorechars=b'') Return the binary data represented by the hexadecimal string *hexstr*. This function is the inverse of :func:`b2a_hex`. *hexstr* must contain an even number of hexadecimal digits (which can be upper or lower case), otherwise an :exc:`Error` exception is raised. + *ignorechars* should be a :term:`bytes-like object` containing characters + to ignore from the input. + Similar functionality (accepting only text string arguments, but more liberal towards whitespace) is also accessible using the :meth:`bytes.fromhex` class method. + .. versionchanged:: next + Added the *ignorechars* parameter. + + .. exception:: Error Exception raised on errors. These are usually programming errors. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index c8c28371587..6f5d84a3b8c 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -657,16 +657,28 @@ base64 * Added the *pad* parameter in :func:`~base64.z85encode`. (Contributed by Hauke Dämpfling in :gh:`143103`.) -* Added the *wrapcol* parameter in :func:`~base64.b64encode`. - (Contributed by Serhiy Storchaka in :gh:`143214`.) +* Added the *wrapcol* parameter in :func:`~base64.b16encode`, + :func:`~base64.b32encode`, :func:`~base64.b32hexencode`, + :func:`~base64.b64encode`, :func:`~base64.b85encode`, and + :func:`~base64.z85encode`. + (Contributed by Serhiy Storchaka in :gh:`143214` and :gh:`146431`.) -* Added the *ignorechars* parameter in :func:`~base64.b64decode`. - (Contributed by Serhiy Storchaka in :gh:`144001`.) +* Added the *ignorechars* parameter in :func:`~base64.b16decode`, + :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64decode`, :func:`~base64.b85decode`, and + :func:`~base64.z85decode`. + (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) binascii -------- +* Added functions for Base32 encoding: + + - :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32` + + (Contributed by James Seo in :gh:`146192`.) + * Added functions for Ascii85, Base85, and Z85 encoding: - :func:`~binascii.b2a_ascii85` and :func:`~binascii.a2b_ascii85` @@ -681,14 +693,9 @@ binascii :func:`~binascii.a2b_base64`. (Contributed by Serhiy Storchaka in :gh:`145980`.) -* Added the *ignorechars* parameter in :func:`~binascii.a2b_base64`. - (Contributed by Serhiy Storchaka in :gh:`144001`.) - -* Added functions for Base32 encoding: - - - :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32` - - (Contributed by James Seo in :gh:`146192`.) +* Added the *ignorechars* parameter in :func:`~binascii.a2b_hex`, + :func:`~binascii.unhexlify`, and :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.) calendar diff --git a/Lib/base64.py b/Lib/base64.py index 9b57cdfefce..47b90643e8d 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -186,12 +186,18 @@ def urlsafe_b64decode(s): # Base32 encoding/decoding must be done in Python _B32_ENCODE_DOCSTRING = ''' Encode the bytes-like objects using {encoding} and return a bytes object. + +If wrapcol is non-zero, insert a newline (b'\\n') character after at most +every wrapcol characters. ''' _B32_DECODE_DOCSTRING = ''' Decode the {encoding} encoded bytes-like object or ASCII string s. Optional casefold is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default is False. + +ignorechars should be a byte string containing characters to ignore +from the input. {extra_args} The result is returned as a bytes object. A binascii.Error is raised if the input is incorrectly padded or if there are non-alphabet @@ -207,11 +213,11 @@ def urlsafe_b64decode(s): 0 and 1 are not allowed in the input. ''' -def b32encode(s): - return binascii.b2a_base32(s) +def b32encode(s, *, wrapcol=0): + return binascii.b2a_base32(s, wrapcol=wrapcol) b32encode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32') -def b32decode(s, casefold=False, map01=None): +def b32decode(s, casefold=False, map01=None, *, ignorechars=b''): s = _bytes_from_decode_data(s) # Handle section 2.4 zero and one mapping. The flag map01 will be either # False, or the character to map the digit 1 (one) to. It should be @@ -222,20 +228,22 @@ def b32decode(s, casefold=False, map01=None): s = s.translate(bytes.maketrans(b'01', b'O' + map01)) if casefold: s = s.upper() - return binascii.a2b_base32(s) + return binascii.a2b_base32(s, ignorechars=ignorechars) b32decode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32', extra_args=_B32_DECODE_MAP01_DOCSTRING) -def b32hexencode(s): - return binascii.b2a_base32(s, alphabet=binascii.BASE32HEX_ALPHABET) +def b32hexencode(s, *, wrapcol=0): + return binascii.b2a_base32(s, wrapcol=wrapcol, + alphabet=binascii.BASE32HEX_ALPHABET) b32hexencode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32hex') -def b32hexdecode(s, casefold=False): +def b32hexdecode(s, casefold=False, *, ignorechars=b''): s = _bytes_from_decode_data(s) # base32hex does not have the 01 mapping if casefold: s = s.upper() - return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET) + return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET, + ignorechars=ignorechars) b32hexdecode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32hex', extra_args='') @@ -243,28 +251,43 @@ def b32hexdecode(s, casefold=False): # RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns # lowercase. The RFC also recommends against accepting input case # insensitively. -def b16encode(s): +def b16encode(s, *, wrapcol=0): """Encode the bytes-like object s using Base16 and return a bytes object. + + If wrapcol is non-zero, insert a newline (b'\\n') character after at most + every wrapcol characters. """ - return binascii.hexlify(s).upper() + if not wrapcol: + return binascii.hexlify(s).upper() + if wrapcol < 0: + raise ValueError('Negative wrapcol') + if wrapcol < 2: + wrapcol = 2 + return binascii.hexlify(s, bytes_per_sep=-(wrapcol//2), sep=b'\n').upper() -def b16decode(s, casefold=False): +def b16decode(s, casefold=False, *, ignorechars=b''): """Decode the Base16 encoded bytes-like object or ASCII string s. Optional casefold is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default is False. + ignorechars should be a byte string containing characters to ignore + from the input. + The result is returned as a bytes object. A binascii.Error is raised if s is incorrectly padded or if there are non-alphabet characters present in the input. """ - s = _bytes_from_decode_data(s) - if casefold: - s = s.upper() - if s.translate(None, delete=b'0123456789ABCDEF'): - raise binascii.Error('Non-base16 digit found') - return binascii.unhexlify(s) + if not casefold: + s = _bytes_from_decode_data(s) + if not isinstance(ignorechars, bytes): + ignorechars = bytes(memoryview(ignorechars)) + for b in b'abcdef': + if b in s and b not in ignorechars: + raise binascii.Error('Non-base16 digit found') + s = s.translate(None, delete=b'abcdef') + return binascii.unhexlify(s, ignorechars=ignorechars) # # Ascii85 encoding/decoding @@ -307,31 +330,42 @@ def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'): return binascii.a2b_ascii85(b, foldspaces=foldspaces, adobe=adobe, ignorechars=ignorechars) -def b85encode(b, pad=False): +def b85encode(b, pad=False, *, wrapcol=0): """Encode bytes-like object b in base85 format and return a bytes object. + If wrapcol is non-zero, insert a newline (b'\\n') character after at most + every wrapcol characters. + If pad is true, the input is padded with b'\\0' so its length is a multiple of 4 bytes before encoding. """ - return binascii.b2a_base85(b, pad=pad) + return binascii.b2a_base85(b, wrapcol=wrapcol, pad=pad) -def b85decode(b): +def b85decode(b, *, ignorechars=b''): """Decode the base85-encoded bytes-like object or ASCII string b The result is returned as a bytes object. """ - return binascii.a2b_base85(b) + return binascii.a2b_base85(b, ignorechars=ignorechars) -def z85encode(s, pad=False): - """Encode bytes-like object b in z85 format and return a bytes object.""" - return binascii.b2a_base85(s, pad=pad, alphabet=binascii.Z85_ALPHABET) +def z85encode(s, pad=False, *, wrapcol=0): + """Encode bytes-like object b in z85 format and return a bytes object. -def z85decode(s): + If wrapcol is non-zero, insert a newline (b'\\n') character after at most + every wrapcol characters. + + If pad is true, the input is padded with b'\\0' so its length is a multiple of + 4 bytes before encoding. + """ + return binascii.b2a_base85(s, wrapcol=wrapcol, pad=pad, + alphabet=binascii.Z85_ALPHABET) + +def z85decode(s, *, ignorechars=b''): """Decode the z85-encoded bytes-like object or ASCII string b The result is returned as a bytes object. """ - return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET) + return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET, ignorechars=ignorechars) # Legacy interface. This code could be cleaned up since I don't believe # binascii has any line length limitations. It just doesn't seem worth it diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index 9648624b267..bb3b3c1e235 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -209,30 +209,37 @@ def test_b64encode(self): b'\xd3V\xbeo\xf7\x1d', b'01a-b_cd') self.check_encode_type_errors(base64.urlsafe_b64encode) + def _common_test_wrapcol(self, func, data): + eq = self.assertEqual + expected = func(data) + eq(func(data, wrapcol=0), expected) + eq(func(data, wrapcol=80), expected) + eq(func(b'', wrapcol=0), func(b'')) + eq(func(b'', wrapcol=1), func(b'')) + if func is not base64.b16encode: + eq(func(data, wrapcol=sys.maxsize), expected) + if check_impl_detail(): + if func is not base64.b16encode: + eq(func(data, wrapcol=sys.maxsize*2), expected) + with self.assertRaises(OverflowError): + func(data, wrapcol=2**1000) + with self.assertRaises(ValueError): + func(data, wrapcol=-80) + with self.assertRaises(TypeError): + func(data, wrapcol=80.0) + with self.assertRaises(TypeError): + func(data, wrapcol='80') + if func is not base64.b16encode: + with self.assertRaises(TypeError): + func(data, wrapcol=None) + def test_b64encode_wrapcol(self): eq = self.assertEqual b = b'www.python.org' - eq(base64.b64encode(b, wrapcol=0), b'd3d3LnB5dGhvbi5vcmc=') + self._common_test_wrapcol(base64.b64encode, b) eq(base64.b64encode(b, wrapcol=8), b'd3d3LnB5\ndGhvbi5v\ncmc=') eq(base64.b64encode(b, wrapcol=11), b'd3d3LnB5\ndGhvbi5v\ncmc=') - eq(base64.b64encode(b, wrapcol=76), b'd3d3LnB5dGhvbi5vcmc=') eq(base64.b64encode(b, wrapcol=1), b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=') - eq(base64.b64encode(b, wrapcol=sys.maxsize), b'd3d3LnB5dGhvbi5vcmc=') - if check_impl_detail(): - eq(base64.b64encode(b, wrapcol=sys.maxsize*2), - b'd3d3LnB5dGhvbi5vcmc=') - with self.assertRaises(OverflowError): - base64.b64encode(b, wrapcol=2**1000) - with self.assertRaises(ValueError): - base64.b64encode(b, wrapcol=-8) - with self.assertRaises(TypeError): - base64.b64encode(b, wrapcol=8.0) - with self.assertRaises(TypeError): - base64.b64encode(b, wrapcol='8') - with self.assertRaises(TypeError): - base64.b64encode(b, wrapcol=None) - eq(base64.b64encode(b'', wrapcol=0), b'') - eq(base64.b64encode(b'', wrapcol=8), b'') def test_b64decode(self): eq = self.assertEqual @@ -309,6 +316,24 @@ def test_b64decode_padding_error(self): self.assertRaises(binascii.Error, base64.b64decode, b'abc') self.assertRaises(binascii.Error, base64.b64decode, 'abc') + def _common_test_ignorechars(self, func): + eq = self.assertEqual + eq(func(b'', ignorechars=b' \n'), b'') + eq(func(b'', ignorechars=b''), b'') + eq(func(b' \n', ignorechars=b' \n'), b'') + with self.assertRaises(binascii.Error): + func(b' \n', ignorechars=b'') + with self.assertRaises(binascii.Error): + func(b' \n', ignorechars=b' ') + with self.assertRaises(binascii.Error): + func(b' \n', ignorechars=b'\n') + with self.assertRaises(TypeError): + func(b'', ignorechars='') + with self.assertRaises(TypeError): + func(b'', ignorechars=[]) + with self.assertRaises(TypeError): + func(b'', ignorechars=None) + def test_b64decode_invalid_chars(self): # issue 1466065: Test some invalid characters. tests = ((b'%3d==', b'\xdd', b'%$'), @@ -351,12 +376,7 @@ def test_b64decode_invalid_chars(self): r = base64.b64decode(bstr, ignorechars=ignorechars) self.assertEqual(r, res) - with self.assertRaises(TypeError): - base64.b64decode(b'', ignorechars='') - with self.assertRaises(TypeError): - base64.b64decode(b'', ignorechars=[]) - with self.assertRaises(TypeError): - base64.b64decode(b'', ignorechars=None) + self._common_test_ignorechars(base64.b64decode) # Normal alphabet characters will be discarded when alternative given discarded = ("invalid character %a in Base64 data with %s " @@ -469,6 +489,14 @@ def test_b32encode(self): self.check_other_types(base64.b32encode, b'abcd', b'MFRGGZA=') self.check_encode_type_errors(base64.b32encode) + def test_b32encode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.b32encode, b) + eq(base64.b32encode(b, wrapcol=16), b'O53XOLTQPF2GQ33O\nFZXXEZY=') + eq(base64.b32encode(b, wrapcol=23), b'O53XOLTQPF2GQ33O\nFZXXEZY=') + eq(base64.b32encode(b, wrapcol=1), b'O53XOLTQ\nPF2GQ33O\nFZXXEZY=') + def test_b32decode(self): eq = self.assertEqual tests = {b'': b'', @@ -504,6 +532,7 @@ def test_b32decode_casefold(self): for data, res in tests.items(): eq(base64.b32decode(data, True), res) + eq(base64.b32decode(data, casefold=True), res) eq(base64.b32decode(data.decode('ascii'), True), res) self.assertRaises(binascii.Error, base64.b32decode, b'me======') @@ -537,6 +566,31 @@ def test_b32decode_map01(self): eq(base64.b32decode(b'M%c023456' % map01, map01=map01), res) eq(base64.b32decode(b'M%cO23456' % map01, map01=map01), res) + def test_b32decode_ignorechars(self): + self._common_test_ignorechars(base64.b32decode) + eq = self.assertEqual + eq(base64.b32decode(b'MFRG\n GZDF\n', ignorechars=b' \n'), b'abcde') + eq(base64.b32decode(b'MFRG\n GZDF\n', ignorechars=bytearray(b' \n')), b'abcde') + eq(base64.b32decode(b'M=======FRGGZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MF======RGGZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFR=====GGZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRG====GZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGG===ZDF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGGZ==DF', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGGZD=F', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRGGZDF=', ignorechars=b'='), b'abcde') + eq(base64.b32decode(b'MFRA======', ignorechars=b'='), b'ab') + + eq(base64.b32decode(b'mfRggzDfmzTQ====', ignorechars=b'mfgz'), + b'\x88\xe7') + eq(base64.b32decode(b'mfRggzDfmzTQ====', casefold=True, ignorechars=b'mfgz'), + b'abcdefg') + eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', ignorechars=b'01'), b'abcde') + eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', map01=b'L', ignorechars=b'01'), + b'c\x8a\xb8\xb8\xcb3\xb2\xb1\xb8\xab') + eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', map01=b'I', ignorechars=b'01'), + b'c\x8a\x88\xb8\xc83\xb2\x81\xb8\xa8') + def test_b32decode_error(self): tests = [b'abc', b'ABCDEF==', b'==ABCDEF'] prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF'] @@ -585,6 +639,14 @@ def test_b32hexencode_other_types(self): self.check_other_types(base64.b32hexencode, b'abcd', b'C5H66P0=') self.check_encode_type_errors(base64.b32hexencode) + def test_b32hexencode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.b32hexencode, b) + eq(base64.b32hexencode(b, wrapcol=16), b'ETRNEBJGF5Q6GRRE\n5PNN4PO=') + eq(base64.b32hexencode(b, wrapcol=23), b'ETRNEBJGF5Q6GRRE\n5PNN4PO=') + eq(base64.b32hexencode(b, wrapcol=1), b'ETRNEBJG\nF5Q6GRRE\n5PNN4PO=') + def test_b32hexdecode(self): test_cases = [ # to_decode, expected, casefold @@ -619,6 +681,28 @@ def test_b32hexdecode_other_types(self): self.check_other_types(base64.b32hexdecode, b'C5H66===', b'abc') self.check_decode_type_errors(base64.b32hexdecode) + def test_b32hexdecode_ignorechars(self): + self._common_test_ignorechars(base64.b32hexdecode) + eq = self.assertEqual + eq(base64.b32hexdecode(b'C5H6\n 6P35\n', ignorechars=b' \n'), b'abcde') + eq(base64.b32hexdecode(b'C5H6\n 6P35\n', ignorechars=bytearray(b' \n')), b'abcde') + eq(base64.b32hexdecode(b'========C5H66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C=======5H66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5======H66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H=====66P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H6====6P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66===P35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66P==35', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66P3=5', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H66P35=', ignorechars=b'='), b'abcde') + eq(base64.b32hexdecode(b'C5H0======', ignorechars=b'='), b'ab') + + eq(base64.b32hexdecode(b'c5h66p35cpjmg===', ignorechars=b'cghjmp'), + b')\x8c2') + eq(base64.b32hexdecode(b'c5h66p35cpjmg===', casefold=True, + ignorechars=b'cghjmp'), + b'abcdefgh') + def test_b32hexdecode_error(self): tests = [b'abc', b'ABCDEF==', b'==ABCDEF', b'c4======'] prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF'] @@ -654,6 +738,14 @@ def test_b16encode(self): b'0102ABCDEF') self.check_encode_type_errors(base64.b16encode) + def test_b16encode_wrapcol(self): + eq = self.assertEqual + b = b'\x01\x02\xab\xcd\xef' + self._common_test_wrapcol(base64.b16encode, b) + eq(base64.b16encode(b, wrapcol=4), b'0102\nABCD\nEF') + eq(base64.b16encode(b, wrapcol=5), b'0102\nABCD\nEF') + eq(base64.b16encode(b, wrapcol=1), b'01\n02\nAB\nCD\nEF') + def test_b16decode(self): eq = self.assertEqual eq(base64.b16decode(b'0102ABCDEF'), b'\x01\x02\xab\xcd\xef') @@ -681,6 +773,14 @@ def test_b16decode(self): # Incorrect "padding" self.assertRaises(binascii.Error, base64.b16decode, '010') + def test_b16decode_ignorechars(self): + self._common_test_ignorechars(base64.b16decode) + eq = self.assertEqual + eq(base64.b16decode(b'A B\nC D\n', ignorechars=b' \n'), b'\xab\xcd') + eq(base64.b16decode(b'A B\nC D\n', ignorechars=bytearray(b' \n')), b'\xab\xcd') + eq(base64.b16decode(b'aBcD', ignorechars=b'ac'), b'\xbd') + eq(base64.b16decode(b'aBcD', casefold=True, ignorechars=b'ac'), b'\xab\xcd') + @hypothesis.given( payload=hypothesis.strategies.binary(), casefold=hypothesis.strategies.booleans()) @@ -737,7 +837,7 @@ def test_a85encode(self): def test_a85encode_wrapcol(self): eq = self.assertEqual b = b'www.python.org' - eq(base64.a85encode(b, wrapcol=0), b'GB\\6`E-ZP=Df.1GEb>') + self._common_test_wrapcol(base64.a85encode, b) eq(base64.a85encode(b, wrapcol=7), b'GB\\6`E-\nZP=Df.1\nGEb>') eq(base64.a85encode(b"\0\0\0\0www.python.org", wrapcol=7), b'zGB\\6`E\n-ZP=Df.\n1GEb>') @@ -750,24 +850,8 @@ def test_a85encode_wrapcol(self): b'G\nB\n\\\n6\n`\nE\n-\nZ\nP\n=\nD\nf\n.\n1\nG\nE\nb\n>') eq(base64.a85encode(b, wrapcol=1, adobe=True), b'<~\nGB\n\\6\n`E\n-Z\nP=\nDf\n.1\nGE\nb>\n~>') - eq(base64.a85encode(b, wrapcol=sys.maxsize), b'GB\\6`E-ZP=Df.1GEb>') - if check_impl_detail(): - eq(base64.a85encode(b, wrapcol=sys.maxsize*2), - b'GB\\6`E-ZP=Df.1GEb>') - with self.assertRaises(OverflowError): - base64.a85encode(b, wrapcol=2**1000) - with self.assertRaises(ValueError): - base64.a85encode(b, wrapcol=-7) with self.assertRaises(ValueError): base64.a85encode(b, wrapcol=-7, adobe=True) - with self.assertRaises(TypeError): - base64.a85encode(b, wrapcol=7.0) - with self.assertRaises(TypeError): - base64.a85encode(b, wrapcol='7') - with self.assertRaises(TypeError): - base64.a85encode(b, wrapcol=None) - eq(base64.a85encode(b'', wrapcol=0), b'') - eq(base64.a85encode(b'', wrapcol=7), b'') eq(base64.a85encode(b'', wrapcol=1, adobe=True), b'<~\n~>') eq(base64.a85encode(b'', wrapcol=3, adobe=True), b'<~\n~>') eq(base64.a85encode(b'', wrapcol=4, adobe=True), b'<~~>') @@ -806,6 +890,14 @@ def test_b85encode(self): self.check_other_types(base64.b85encode, b"www.python.org", b'cXxL#aCvlSZ*DGca%T') + def test_b85encode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.b85encode, b) + eq(base64.b85encode(b, wrapcol=10), b'cXxL#aCvlS\nZ*DGca%T') + eq(base64.b85encode(b, wrapcol=14), b'cXxL#aCvlS\nZ*DGca%T') + eq(base64.b85encode(b, wrapcol=1), b'cXxL#\naCvlS\nZ*DGc\na%T') + def test_z85encode(self): eq = self.assertEqual @@ -841,6 +933,14 @@ def test_z85encode(self): self.check_other_types(base64.z85encode, b"www.python.org", b'CxXl-AcVLsz/dgCA+t') + def test_z85encode_wrapcol(self): + eq = self.assertEqual + b = b'www.python.org' + self._common_test_wrapcol(base64.z85encode, b) + eq(base64.z85encode(b, wrapcol=10), b'CxXl-AcVLs\nz/dgCA+t') + eq(base64.z85encode(b, wrapcol=14), b'CxXl-AcVLs\nz/dgCA+t') + eq(base64.z85encode(b, wrapcol=1), b'CxXl-\nAcVLs\nz/dgC\nA+t') + def test_a85decode(self): eq = self.assertEqual @@ -1047,24 +1147,20 @@ def test_a85decode_errors(self): self.assertEqual(base64.a85decode(b"a b\nc", ignorechars=b" \n"), b'\xc9\x89') - with self.assertRaises(ValueError): - base64.a85decode(b"a b\nc", ignorechars=b"") - with self.assertRaises(ValueError): - base64.a85decode(b"a b\nc", ignorechars=b" ") - with self.assertRaises(ValueError): - base64.a85decode(b"a b\nc", ignorechars=b"\n") - with self.assertRaises(TypeError): - base64.a85decode(b"a b\nc", ignorechars=" \n") - with self.assertRaises(TypeError): - base64.a85decode(b"a b\nc", ignorechars=None) + self._common_test_ignorechars(base64.a85decode) def test_b85decode_errors(self): illegal = list(range(33)) + \ list(b'"\',./:[\\]') + \ list(range(128, 256)) for c in illegal: - with self.assertRaises(ValueError, msg=bytes([c])): - base64.b85decode(b'0000' + bytes([c])) + b = bytes([c]) + with self.assertRaises(ValueError, msg=b): + base64.b85decode(b'0000' + b) + self.assertEqual(base64.b85decode(b'0000' + b, ignorechars=b), + b'\x00\x00\x00') + + self._common_test_ignorechars(base64.b85decode) self.assertRaises(ValueError, base64.b85decode, b'|') self.assertRaises(ValueError, base64.b85decode, b'|N') @@ -1077,8 +1173,13 @@ def test_z85decode_errors(self): list(b'"\',;_`|\\~') + \ list(range(128, 256)) for c in illegal: - with self.assertRaises(ValueError, msg=bytes([c])): - base64.z85decode(b'0000' + bytes([c])) + b = bytes([c]) + with self.assertRaises(ValueError, msg=b): + base64.z85decode(b'0000' + b) + self.assertEqual(base64.z85decode(b'0000' + b, ignorechars=b), + b'\x00\x00\x00') + + self._common_test_ignorechars(base64.z85decode) # b'\xff\xff\xff\xff' encodes to b'%nSc0', the following will overflow: self.assertRaises(ValueError, base64.z85decode, b'%') diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 1dcd2b25c79..959a61b530b 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -226,8 +226,30 @@ def assertInvalidLength(*args): assertExcessPadding(b'abcd====efgh', b'i\xb7\x1dy\xf8!') assertExcessPadding(b'abcd=====efgh', b'i\xb7\x1dy\xf8!') + def _common_test_ignorechars(self, func): + eq = self.assertEqual + empty = self.type2test(b'') + data = self.type2test(b'\n \n') + ignorechars = self.type2test(b' \n') + eq(func(empty, ignorechars=ignorechars), b'') + eq(func(empty, ignorechars=empty), b'') + eq(func(data, ignorechars=ignorechars), b'') + with self.assertRaises(binascii.Error): + func(data, ignorechars=empty) + with self.assertRaises(binascii.Error): + func(data, ignorechars=ignorechars[1:]) + with self.assertRaises(binascii.Error): + func(data, ignorechars=ignorechars[:-1]) + with self.assertRaises(TypeError): + func(empty, ignorechars='') + with self.assertRaises(TypeError): + func(empty, ignorechars=[]) + with self.assertRaises(TypeError): + func(empty, ignorechars=None) + def test_base64_invalidchars(self): # Test non-base64 data exceptions + self._common_test_ignorechars(binascii.a2b_base64) def assertNonBase64Data(data, expected, ignorechars): data = self.type2test(data) assert_regex = r'(?i)Only base64 data' @@ -253,6 +275,12 @@ def assertNonBase64Data(data, expected, ignorechars): assertNonBase64Data(b'a\nb==', b'i', ignorechars=bytearray(b'\n')) assertNonBase64Data(b'a\nb==', b'i', ignorechars=memoryview(b'\n')) + self.assertEqual(binascii.a2b_base64(b'+A-/B_', ignorechars=b'+/-_'), + b'\xf8\x0f\xc1') + self.assertEqual(binascii.a2b_base64(b'+A-/B_', ignorechars=b'+/-_', + alphabet=binascii.URLSAFE_BASE64_ALPHABET), + b'\x03\xe0\x7f') + # Same cell in the cache: '\r' >> 3 == '\n' >> 3. data = self.type2test(b'\r\n') with self.assertRaises(binascii.Error): @@ -264,14 +292,6 @@ def assertNonBase64Data(data, expected, ignorechars): binascii.a2b_base64(data, ignorechars=b'*') self.assertEqual(binascii.a2b_base64(data, ignorechars=b'*\n'), b'') - data = self.type2test(b'a\nb==') - with self.assertRaises(TypeError): - binascii.a2b_base64(data, ignorechars='') - with self.assertRaises(TypeError): - binascii.a2b_base64(data, ignorechars=[]) - with self.assertRaises(TypeError): - binascii.a2b_base64(data, ignorechars=None) - def test_base64_excess_data(self): # Test excess data exceptions def assertExcessData(data, expected): @@ -495,8 +515,32 @@ def assertInvalidChar(data, **kwargs): assertInvalidChar(b"\tFCb", ignorechars=b"\n") assertInvalidChar(b"xxxB\nP\thU'D v/F+", ignorechars=b" \n\tv") + def _common_test_wrapcol(self, func): + eq = self.assertEqual + data = self.data + expected = func(data) + eq(func(data, wrapcol=0), expected) + eq(func(data, wrapcol=8000), expected) + eq(func(b'', wrapcol=0), func(b'')) + eq(func(b'', wrapcol=1), func(b'')) + eq(func(data, wrapcol=sys.maxsize), expected) + if check_impl_detail(): + eq(func(data, wrapcol=sys.maxsize*2), expected) + with self.assertRaises(OverflowError): + func(data, wrapcol=2**1000) + with self.assertRaises(ValueError): + func(data, wrapcol=-80) + with self.assertRaises(TypeError): + func(data, wrapcol=80.0) + with self.assertRaises(TypeError): + func(data, wrapcol='80') + with self.assertRaises(TypeError): + func(data, wrapcol=None) + def test_ascii85_wrapcol(self): # Test Ascii85 splitting lines + self._common_test_wrapcol(binascii.b2a_ascii85) + def assertEncode(a_expected, data, n, adobe=False): b = self.type2test(data) a = binascii.b2a_ascii85(b, adobe=adobe, wrapcol=n) @@ -635,6 +679,16 @@ def assertOverflow(data): assertOverflow(b"|NsC0~") assertOverflow(b"|NsC0|NsC0|NsD0") + def test_base85_wrapcol(self): + self._common_test_wrapcol(binascii.b2a_base85) + b = self.type2test(b'www.python.org') + self.assertEqual(binascii.b2a_base85(b, wrapcol=10), + b'cXxL#aCvlS\nZ*DGca%T') + self.assertEqual(binascii.b2a_base85(b, wrapcol=14), + b'cXxL#aCvlS\nZ*DGca%T') + self.assertEqual(binascii.b2a_base85(b, wrapcol=1), + b'cXxL#\naCvlS\nZ*DGc\na%T') + def test_base85_pad(self): # Test base85 with encode padding rawdata = b"n1n3Tee\n ch@rAc\te\r$" @@ -646,6 +700,17 @@ def test_base85_pad(self): b_pad_expected = b + b"\0" * padding self.assertEqual(b_pad, b_pad_expected) + def test_base85_ignorechars(self): + a2b_base85 = binascii.a2b_base85 + self._common_test_ignorechars(a2b_base85) + eq = self.assertEqual + eq(a2b_base85(b'VPa\n !s\n', ignorechars=b' \n'), b'abcd') + eq(a2b_base85(b'VPa\n !s\n', ignorechars=bytearray(b' \n')), b'abcd') + + eq(a2b_base85(b'A~[B];C', ignorechars=b';[]~'), b'"1\xa3\x15') + eq(a2b_base85(b'A~[B];C', ignorechars=b';[]~', + alphabet=binascii.Z85_ALPHABET), b'r\xd8dv') + def test_base85_alphabet(self): alphabet = (b'0123456789abcdefghijklmnopqrstuvwxyz' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#') @@ -824,6 +889,36 @@ def assertInvalidLength(*args): assertInvalidLength(b"BEEFCA=K", b"\t\x08Q\x01") assertInvalidLength(b"BEEFCA=====K", b"\t\x08Q\x01") + def test_base32_wrapcol(self): + self._common_test_wrapcol(binascii.b2a_base32) + b = self.type2test(b'www.python.org') + self.assertEqual(binascii.b2a_base32(b, wrapcol=16), + b'O53XOLTQPF2GQ33O\nFZXXEZY=') + self.assertEqual(binascii.b2a_base32(b, wrapcol=23), + b'O53XOLTQPF2GQ33O\nFZXXEZY=') + self.assertEqual(binascii.b2a_base32(b, wrapcol=1), + b'O53XOLTQ\nPF2GQ33O\nFZXXEZY=') + + def test_base32_ignorechars(self): + a2b_base32 = binascii.a2b_base32 + self._common_test_ignorechars(a2b_base32) + eq = self.assertEqual + eq(a2b_base32(b'MFRG\n GZDF\n', ignorechars=b' \n'), b'abcde') + eq(a2b_base32(b'MFRG\n GZDF\n', ignorechars=bytearray(b' \n')), b'abcde') + eq(a2b_base32(b'M=======FRGGZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MF======RGGZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFR=====GGZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRG====GZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGG===ZDF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGGZ==DF', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGGZD=F', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRGGZDF=', ignorechars=b'='), b'abcde') + eq(a2b_base32(b'MFRA======', ignorechars=b'='), b'ab') + + eq(a2b_base32(b'A1B3C5W7Z9', ignorechars=b'19WZ'), b'\x00v.\xdb\xf9') + eq(a2b_base32(b'A1B3C5W7Z9', ignorechars=b'19WZ', + alphabet=binascii.BASE32HEX_ALPHABET), b'PV6\x14\xe9') + def test_base32_alphabet(self): alphabet = b'0Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9JjKk' data = self.type2test(self.rawdata) @@ -951,6 +1046,15 @@ def test_hex_separator(self): expected1 = s.hex(':').encode('ascii') self.assertEqual(binascii.b2a_hex(self.type2test(s), ':'), expected1) + def test_hex_ignorechars(self): + a2b_hex = binascii.a2b_hex + self._common_test_ignorechars(a2b_hex) + self._common_test_ignorechars(binascii.unhexlify) + eq = self.assertEqual + eq(a2b_hex(b'A B\nC D\n', ignorechars=b' \n'), b'\xab\xcd') + eq(a2b_hex(b'A B\nC D\n', ignorechars=bytearray(b' \n')), b'\xab\xcd') + eq(a2b_hex(b'aBcD', ignorechars=b'ac'), b'\xab\xcd') + def test_qp(self): type2test = self.type2test a2b_qp = binascii.a2b_qp @@ -1128,38 +1232,17 @@ def test_b2a_base64_newline(self): self.assertEqual(binascii.b2a_base64(b, newline=False), b'') def test_b2a_base64_wrapcol(self): + self._common_test_wrapcol(binascii.b2a_base64) b = self.type2test(b'www.python.org') - self.assertEqual(binascii.b2a_base64(b), - b'd3d3LnB5dGhvbi5vcmc=\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=0), - b'd3d3LnB5dGhvbi5vcmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8), b'd3d3LnB5\ndGhvbi5v\ncmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=11), b'd3d3LnB5\ndGhvbi5v\ncmc=\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=76), - b'd3d3LnB5dGhvbi5vcmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False), b'd3d3LnB5\ndGhvbi5v\ncmc=') self.assertEqual(binascii.b2a_base64(b, wrapcol=1), b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize), - b'd3d3LnB5dGhvbi5vcmc=\n') - if check_impl_detail(): - self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize*2), - b'd3d3LnB5dGhvbi5vcmc=\n') - with self.assertRaises(OverflowError): - binascii.b2a_base64(b, wrapcol=2**1000) - with self.assertRaises(ValueError): - binascii.b2a_base64(b, wrapcol=-8) - with self.assertRaises(TypeError): - binascii.b2a_base64(b, wrapcol=8.0) - with self.assertRaises(TypeError): - binascii.b2a_base64(b, wrapcol='8') b = self.type2test(b'') - self.assertEqual(binascii.b2a_base64(b), b'\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=0), b'\n') - self.assertEqual(binascii.b2a_base64(b, wrapcol=8), b'\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False), b'') @hypothesis.given( diff --git a/Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst b/Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst new file mode 100644 index 00000000000..6268a52926f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst @@ -0,0 +1,11 @@ +Add the *wrapcol* parameter to :mod:`base64` functions +:func:`~base64.b16encode`, :func:`~base64.b32encode`, +:func:`~base64.b32hexencode`, :func:`~base64.b85encode` and +:func:`~base64.z85encode`, and :mod:`binascii` functions +:func:`~binascii.b2a_base32` and :func:`~binascii.b2a_base85`. Add the +*ignorechars* parameter to :mod:`base64` functions +:func:`~base64.b16decode`, :func:`~base64.b32decode`, +:func:`~base64.b32hexdecode`, :func:`~base64.b85decode` and +:func:`~base64.z85decode`, and :mod:`binascii` functions +:func:`~binascii.a2b_hex`, :func:`~binascii.unhexlify`, +:func:`~binascii.a2b_base32` and :func:`~binascii.a2b_base85`. diff --git a/Modules/binascii.c b/Modules/binascii.c index c51bb9c3c77..3cc67d74561 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -803,7 +803,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, if (quad_pos >= 2 && quad_pos + pads <= 4) { continue; } - // See RFC 4648, section-3.3: "specifications MAY ignore the + // See RFC 4648, section 3.3: "specifications MAY ignore the // pad character, "=", treating it as non-alphabet data, if // it is present before the end of the encoded data" and // "the excess pad characters MAY also be ignored." @@ -826,7 +826,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, unsigned char v = table_a2b[this_ch]; if (v >= 64) { - // See RFC 4648, section-3.3. + // See RFC 4648, section 3.3. if (strict_mode && !ignorechar(this_ch, ignorechars, ignorecache)) { state = get_binascii_state(module); if (state) { @@ -838,7 +838,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, } // Characters that are not '=', in the middle of the padding, are - // not allowed (except when they are). See RFC 4648, section-3.3. + // not allowed (except when they are). See RFC 4648, section 3.3. if (pads && strict_mode && !ignorechar(BASE64_PAD, ignorechars, ignorecache)) { @@ -1294,14 +1294,16 @@ binascii.a2b_base85 / * alphabet: PyBytesObject(c_default="NULL") = BASE85_ALPHABET + ignorechars: Py_buffer = b'' + A byte string containing characters to ignore from the input. Decode a line of Base85 data. [clinic start generated code]*/ static PyObject * binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, - PyBytesObject *alphabet) -/*[clinic end generated code: output=3e114af53812e8ff input=0b6b83b38ad4497c]*/ + PyBytesObject *alphabet, Py_buffer *ignorechars) +/*[clinic end generated code: output=6a8d6eae798818d7 input=04d72a319712bdf3]*/ { const unsigned char *ascii_data = data->buf; Py_ssize_t ascii_len = data->len; @@ -1318,6 +1320,14 @@ binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj); } + if (ignorechars->len == 0) { + ignorechars = NULL; + } + ignorecache_t ignorecache; + if (ignorechars != NULL) { + memset(ignorecache, 0, sizeof(ignorecache)); + } + assert(ascii_len >= 0); /* Allocate output buffer. */ @@ -1333,9 +1343,10 @@ binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, int group_pos = 0; for (; ascii_len > 0 || group_pos != 0; ascii_len--, ascii_data++) { /* Shift (in radix-85) data or padding into our buffer. */ + unsigned char this_ch; unsigned char this_digit; if (ascii_len > 0) { - unsigned char this_ch = *ascii_data; + this_ch = *ascii_data; this_digit = table_a2b[this_ch]; } else { @@ -1358,7 +1369,7 @@ binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, leftchar = leftchar * 85 + this_digit; group_pos++; } - else { + else if (!ignorechar(this_ch, ignorechars, ignorecache)) { state = get_binascii_state(module); if (state != NULL) { PyErr_Format(state->Error, "bad Base85 character at position %zd", @@ -1399,6 +1410,7 @@ binascii.b2a_base85 * pad: bool = False Pad input to a multiple of 4 before encoding. + wrapcol: size_t = 0 alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE85_ALPHABET Base85-code line of data. @@ -1406,8 +1418,8 @@ Base85-code line of data. static PyObject * binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, - Py_buffer *alphabet) -/*[clinic end generated code: output=a59f4f2ff6f0e69f input=30f545c6ff554db7]*/ + size_t wrapcol, Py_buffer *alphabet) +/*[clinic end generated code: output=98b962ed52c776a4 input=1b20b0bd6572691b]*/ { const unsigned char *bin_data = data->buf; Py_ssize_t bin_len = data->len; @@ -1428,6 +1440,11 @@ binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, if (!pad && (bin_len % 4)) { out_len -= 4 - (bin_len % 4); } + if (wrapcol && out_len) { + /* Each line should encode a whole number of bytes. */ + wrapcol = wrapcol < 5 ? 5 : wrapcol / 5 * 5; + out_len += (out_len - 1u) / wrapcol; + } if (out_len > PY_SSIZE_T_MAX) { binascii_state *state = get_binascii_state(module); if (state == NULL) { @@ -1480,6 +1497,11 @@ binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, ascii_data += group_len; } + if (wrapcol && out_len) { + unsigned char *start = PyBytesWriter_GetData(writer); + ascii_data = start + wraplines(start, ascii_data - start, wrapcol); + } + return PyBytesWriter_FinishWithPointer(writer, ascii_data); } @@ -1490,14 +1512,16 @@ binascii.a2b_base32 / * alphabet: PyBytesObject(c_default="NULL") = BASE32_ALPHABET + ignorechars: Py_buffer = b'' + A byte string containing characters to ignore from the input. Decode a line of base32 data. [clinic start generated code]*/ static PyObject * binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, - PyBytesObject *alphabet) -/*[clinic end generated code: output=12cb58bf547237e2 input=426055ea49ac147e]*/ + PyBytesObject *alphabet, Py_buffer *ignorechars) +/*[clinic end generated code: output=2cf7c8c9e6e98b88 input=b0333508aad1b3ac]*/ { const unsigned char *ascii_data = data->buf; Py_ssize_t ascii_len = data->len; @@ -1516,6 +1540,14 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj); } + if (ignorechars->len == 0) { + ignorechars = NULL; + } + ignorecache_t ignorecache; + if (ignorechars != NULL) { + memset(ignorecache, 0, sizeof(ignorecache)); + } + /* Allocate output buffer. */ size_t bin_len = ((size_t)ascii_len + 7) / 8 * 5; PyBytesWriter *writer = PyBytesWriter_Create(bin_len); @@ -1525,6 +1557,7 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, } unsigned char *bin_data = PyBytesWriter_GetData(writer); +fastpath: /* * Fast path: use optimized decoder for complete octas (groups of 8 bytes). * The fast path stops at padding, invalid chars, or incomplete octas. @@ -1555,6 +1588,13 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, { continue; } + // See RFC 4648, section 3.3: "specifications MAY ignore the + // pad character, "=", treating it as non-alphabet data, if + // it is present before the end of the encoded data" and + // "the excess pad characters MAY also be ignored." + if (ignorechar(BASE32_PAD, ignorechars, ignorecache)) { + continue; + } if (octa_pos == 1 || octa_pos == 3 || octa_pos == 6) { /* Set an error below. */ break; @@ -1571,15 +1611,20 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, unsigned char v = table_a2b[this_ch]; if (v >= 32) { - state = get_binascii_state(module); - if (state) { - PyErr_SetString(state->Error, "Only base32 data is allowed"); + // See RFC 4648, section 3.3. + if (!ignorechar(this_ch, ignorechars, ignorecache)) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Only base32 data is allowed"); + } + goto error; } - goto error; + continue; } - /* Data in the middle of/after the padding is not allowed. */ - if (pads) { + // Characters that are not '=', in the middle of the padding, are + // not allowed (except when they are). See RFC 4648, section 3.3. + if (pads && !ignorechar(BASE32_PAD, ignorechars, ignorecache)) { state = get_binascii_state(module); if (state) { PyErr_SetString(state->Error, (octa_pos + pads == 8) @@ -1626,6 +1671,9 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, octa_pos = 0; *bin_data++ = (leftchar << 5) | v; leftchar = 0; + ascii_data++; + ascii_len--; + goto fastpath; } } @@ -1642,9 +1690,7 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, goto error; } - if ((octa_pos != 0 && octa_pos + pads != 8) - || (octa_pos == 0 && pads != 0)) - { + if (octa_pos != 0 && octa_pos + pads < 8) { state = get_binascii_state(module); if (state) { PyErr_SetString(state->Error, "Incorrect padding"); @@ -1667,15 +1713,16 @@ binascii.b2a_base32 data: Py_buffer / * + wrapcol: size_t = 0 alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE32_ALPHABET Base32-code line of data. [clinic start generated code]*/ static PyObject * -binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, +binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, Py_buffer *alphabet) -/*[clinic end generated code: output=058d0d1aeb014d3b input=99cbe7194799d368]*/ +/*[clinic end generated code: output=d41fafbdaf29e280 input=a3d93b73836f2879]*/ { const unsigned char *table_b2a = table_b2a_base32; const unsigned char *bin_data = data->buf; @@ -1697,6 +1744,11 @@ binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, * Use unsigned integer arithmetic to avoid signed integer overflow. */ size_t ascii_len = ((size_t)bin_len + 4u) / 5u * 8u; + if (wrapcol && ascii_len) { + /* Each line should encode a whole number of bytes. */ + wrapcol = wrapcol < 8 ? 8 : wrapcol / 8 * 8; + ascii_len += (ascii_len - 1u) / wrapcol; + } if (ascii_len > PY_SSIZE_T_MAX) { state = get_binascii_state(module); if (state) { @@ -1772,6 +1824,11 @@ binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, *ascii_data++ = BASE32_PAD; } + if (wrapcol && ascii_len) { + unsigned char *start = PyBytesWriter_GetData(writer); + ascii_data = start + wraplines(start, ascii_data - start, wrapcol); + } + return PyBytesWriter_FinishWithPointer(writer, ascii_data); } @@ -2060,6 +2117,9 @@ binascii.a2b_hex hexstr: ascii_buffer / + * + ignorechars: Py_buffer = b'' + A byte string containing characters to ignore from the input. Binary data of hexadecimal representation. @@ -2068,53 +2128,68 @@ This function is also available as "unhexlify()". [clinic start generated code]*/ static PyObject * -binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr) -/*[clinic end generated code: output=0cc1a139af0eeecb input=9e1e7f2f94db24fd]*/ +binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars) +/*[clinic end generated code: output=021a7ed5a742cb20 input=6154b3f4e6e2c0c3]*/ { - const char* argbuf; - Py_ssize_t arglen; - Py_ssize_t i, j; - binascii_state *state; + const unsigned char *ascii_data = hexstr->buf; + size_t ascii_len = hexstr->len; + binascii_state *state = NULL; - argbuf = hexstr->buf; - arglen = hexstr->len; - - assert(arglen >= 0); - - /* XXX What should we do about strings with an odd length? Should - * we add an implicit leading zero, or a trailing zero? For now, - * raise an exception. - */ - if (arglen % 2) { - state = get_binascii_state(module); - if (state == NULL) { - return NULL; - } - PyErr_SetString(state->Error, "Odd-length string"); - return NULL; + if (ignorechars->len == 0) { + ignorechars = NULL; + } + ignorecache_t ignorecache; + if (ignorechars != NULL) { + memset(ignorecache, 0, sizeof(ignorecache)); } - PyBytesWriter *writer = PyBytesWriter_Create(arglen/2); + /* Allocate the buffer */ + Py_ssize_t bin_len = ascii_len/2; + PyBytesWriter *writer = PyBytesWriter_Create(bin_len); if (writer == NULL) { return NULL; } - char *retbuf = PyBytesWriter_GetData(writer); + unsigned char *bin_data = PyBytesWriter_GetData(writer); - for (i=j=0; i < arglen; i += 2) { - unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])]; - unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])]; - if (top >= 16 || bot >= 16) { - state = get_binascii_state(module); - if (state == NULL) { + int pair_pos = 0; + unsigned char leftchar = 0; + for (; ascii_len; ascii_data++, ascii_len--) { + unsigned char this_ch = *ascii_data; + + unsigned char this_digit = _PyLong_DigitValue[this_ch]; + if (this_digit >= 16) { + // See RFC 4648, section 3.3. + if (!ignorechar(this_ch, ignorechars, ignorecache)) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, + "Non-hexadecimal digit found"); + } goto error; } - PyErr_SetString(state->Error, - "Non-hexadecimal digit found"); - goto error; + continue; + } + + if (!pair_pos) { + pair_pos = 1; + leftchar = this_digit; + } + else { + pair_pos = 0; + *bin_data++ = (leftchar << 4) | this_digit; } - retbuf[j++] = (top << 4) + bot; } - return PyBytesWriter_Finish(writer); + + if (pair_pos) { + state = get_binascii_state(module); + if (state) { + PyErr_SetString(state->Error, "Odd number of hexadecimal digits"); + } + goto error; + } + + return PyBytesWriter_FinishWithPointer(writer, bin_data); error: PyBytesWriter_Discard(writer); @@ -2130,10 +2205,11 @@ hexstr must contain an even number of hex digits (upper or lower case). [clinic start generated code]*/ static PyObject * -binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr) -/*[clinic end generated code: output=51a64c06c79629e3 input=dd8c012725f462da]*/ +binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars) +/*[clinic end generated code: output=40e87f8a0ded5880 input=dd8c012725f462da]*/ { - return binascii_a2b_hex_impl(module, hexstr); + return binascii_a2b_hex_impl(module, hexstr, ignorechars); } #define MAXLINESIZE 76 diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index 7a411bfc829..bbddd7121bf 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -544,17 +544,21 @@ exit: } PyDoc_STRVAR(binascii_a2b_base85__doc__, -"a2b_base85($module, data, /, *, alphabet=BASE85_ALPHABET)\n" +"a2b_base85($module, data, /, *, alphabet=BASE85_ALPHABET,\n" +" ignorechars=b\'\')\n" "--\n" "\n" -"Decode a line of Base85 data."); +"Decode a line of Base85 data.\n" +"\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input."); #define BINASCII_A2B_BASE85_METHODDEF \ {"a2b_base85", _PyCFunction_CAST(binascii_a2b_base85), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base85__doc__}, static PyObject * binascii_a2b_base85_impl(PyObject *module, Py_buffer *data, - PyBytesObject *alphabet); + PyBytesObject *alphabet, Py_buffer *ignorechars); static PyObject * binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -562,85 +566,6 @@ binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - Py_hash_t ob_hash; - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_hash = -1, - .ob_item = { &_Py_ID(alphabet), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"", "alphabet", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "a2b_base85", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - Py_buffer data = {NULL, NULL}; - PyBytesObject *alphabet = NULL; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); - if (!args) { - goto exit; - } - if (!ascii_buffer_converter(args[0], &data)) { - goto exit; - } - if (!noptargs) { - goto skip_optional_kwonly; - } - if (!PyBytes_Check(args[1])) { - _PyArg_BadArgument("a2b_base85", "argument 'alphabet'", "bytes", args[1]); - goto exit; - } - alphabet = (PyBytesObject *)args[1]; -skip_optional_kwonly: - return_value = binascii_a2b_base85_impl(module, &data, alphabet); - -exit: - /* Cleanup for data */ - if (data.obj) - PyBuffer_Release(&data); - - return return_value; -} - -PyDoc_STRVAR(binascii_b2a_base85__doc__, -"b2a_base85($module, data, /, *, pad=False, alphabet=BASE85_ALPHABET)\n" -"--\n" -"\n" -"Base85-code line of data.\n" -"\n" -" pad\n" -" Pad input to a multiple of 4 before encoding."); - -#define BINASCII_B2A_BASE85_METHODDEF \ - {"b2a_base85", _PyCFunction_CAST(binascii_b2a_base85), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base85__doc__}, - -static PyObject * -binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, - Py_buffer *alphabet); - -static PyObject * -binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; @@ -650,7 +575,7 @@ binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(pad), &_Py_ID(alphabet), }, + .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -659,17 +584,111 @@ binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "pad", "alphabet", NULL}; + static const char * const _keywords[] = {"", "alphabet", "ignorechars", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, - .fname = "b2a_base85", + .fname = "a2b_base85", .kwtuple = KWTUPLE, }; #undef KWTUPLE PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; + PyBytesObject *alphabet = NULL; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!ascii_buffer_converter(args[0], &data)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + if (!PyBytes_Check(args[1])) { + _PyArg_BadArgument("a2b_base85", "argument 'alphabet'", "bytes", args[1]); + goto exit; + } + alphabet = (PyBytesObject *)args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_a2b_base85_impl(module, &data, alphabet, &ignorechars); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } + + return return_value; +} + +PyDoc_STRVAR(binascii_b2a_base85__doc__, +"b2a_base85($module, data, /, *, pad=False, wrapcol=0,\n" +" alphabet=BASE85_ALPHABET)\n" +"--\n" +"\n" +"Base85-code line of data.\n" +"\n" +" pad\n" +" Pad input to a multiple of 4 before encoding."); + +#define BINASCII_B2A_BASE85_METHODDEF \ + {"b2a_base85", _PyCFunction_CAST(binascii_b2a_base85), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base85__doc__}, + +static PyObject * +binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, + size_t wrapcol, Py_buffer *alphabet); + +static PyObject * +binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(pad), &_Py_ID(wrapcol), &_Py_ID(alphabet), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "pad", "wrapcol", "alphabet", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "b2a_base85", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer data = {NULL, NULL}; int pad = 0; + size_t wrapcol = 0; Py_buffer alphabet = {NULL, NULL}; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, @@ -692,11 +711,19 @@ binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[2], &alphabet, PyBUF_SIMPLE) != 0) { + if (args[2]) { + if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[3], &alphabet, PyBUF_SIMPLE) != 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_b2a_base85_impl(module, &data, pad, &alphabet); + return_value = binascii_b2a_base85_impl(module, &data, pad, wrapcol, &alphabet); exit: /* Cleanup for data */ @@ -712,17 +739,21 @@ exit: } PyDoc_STRVAR(binascii_a2b_base32__doc__, -"a2b_base32($module, data, /, *, alphabet=BASE32_ALPHABET)\n" +"a2b_base32($module, data, /, *, alphabet=BASE32_ALPHABET,\n" +" ignorechars=b\'\')\n" "--\n" "\n" -"Decode a line of base32 data."); +"Decode a line of base32 data.\n" +"\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input."); #define BINASCII_A2B_BASE32_METHODDEF \ {"a2b_base32", _PyCFunction_CAST(binascii_a2b_base32), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base32__doc__}, static PyObject * binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, - PyBytesObject *alphabet); + PyBytesObject *alphabet, Py_buffer *ignorechars); static PyObject * binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -730,7 +761,7 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -739,7 +770,7 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(alphabet), }, + .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -748,17 +779,18 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "alphabet", NULL}; + static const char * const _keywords[] = {"", "alphabet", "ignorechars", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_base32", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[2]; + PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyBytesObject *alphabet = NULL; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -771,24 +803,36 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P if (!noptargs) { goto skip_optional_kwonly; } - if (!PyBytes_Check(args[1])) { - _PyArg_BadArgument("a2b_base32", "argument 'alphabet'", "bytes", args[1]); + if (args[1]) { + if (!PyBytes_Check(args[1])) { + _PyArg_BadArgument("a2b_base32", "argument 'alphabet'", "bytes", args[1]); + goto exit; + } + alphabet = (PyBytesObject *)args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) { goto exit; } - alphabet = (PyBytesObject *)args[1]; skip_optional_kwonly: - return_value = binascii_a2b_base32_impl(module, &data, alphabet); + return_value = binascii_a2b_base32_impl(module, &data, alphabet, &ignorechars); exit: /* Cleanup for data */ if (data.obj) PyBuffer_Release(&data); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } return return_value; } PyDoc_STRVAR(binascii_b2a_base32__doc__, -"b2a_base32($module, data, /, *, alphabet=BASE32_ALPHABET)\n" +"b2a_base32($module, data, /, *, wrapcol=0, alphabet=BASE32_ALPHABET)\n" "--\n" "\n" "Base32-code line of data."); @@ -797,7 +841,7 @@ PyDoc_STRVAR(binascii_b2a_base32__doc__, {"b2a_base32", _PyCFunction_CAST(binascii_b2a_base32), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base32__doc__}, static PyObject * -binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, +binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, Py_buffer *alphabet); static PyObject * @@ -806,7 +850,7 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -815,7 +859,7 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(alphabet), }, + .ob_item = { &_Py_ID(wrapcol), &_Py_ID(alphabet), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -824,16 +868,17 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "alphabet", NULL}; + static const char * const _keywords[] = {"", "wrapcol", "alphabet", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "b2a_base32", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[2]; + PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; + size_t wrapcol = 0; Py_buffer alphabet = {NULL, NULL}; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, @@ -847,11 +892,19 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P if (!noptargs) { goto skip_optional_kwonly; } - if (PyObject_GetBuffer(args[1], &alphabet, PyBUF_SIMPLE) != 0) { + if (args[1]) { + if (!_PyLong_Size_t_Converter(args[1], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[2], &alphabet, PyBUF_SIMPLE) != 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_b2a_base32_impl(module, &data, &alphabet); + return_value = binascii_b2a_base32_impl(module, &data, wrapcol, &alphabet); exit: /* Cleanup for data */ @@ -1172,68 +1225,168 @@ exit: } PyDoc_STRVAR(binascii_a2b_hex__doc__, -"a2b_hex($module, hexstr, /)\n" +"a2b_hex($module, hexstr, /, *, ignorechars=b\'\')\n" "--\n" "\n" "Binary data of hexadecimal representation.\n" "\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input.\n" +"\n" "hexstr must contain an even number of hex digits (upper or lower case).\n" "This function is also available as \"unhexlify()\"."); #define BINASCII_A2B_HEX_METHODDEF \ - {"a2b_hex", (PyCFunction)binascii_a2b_hex, METH_O, binascii_a2b_hex__doc__}, + {"a2b_hex", _PyCFunction_CAST(binascii_a2b_hex), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_hex__doc__}, static PyObject * -binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr); +binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars); static PyObject * -binascii_a2b_hex(PyObject *module, PyObject *arg) +binascii_a2b_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - Py_buffer hexstr = {NULL, NULL}; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - if (!ascii_buffer_converter(arg, &hexstr)) { + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(ignorechars), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "ignorechars", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "a2b_hex", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer hexstr = {NULL, NULL}; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } - return_value = binascii_a2b_hex_impl(module, &hexstr); + if (!ascii_buffer_converter(args[0], &hexstr)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (PyObject_GetBuffer(args[1], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_a2b_hex_impl(module, &hexstr, &ignorechars); exit: /* Cleanup for hexstr */ if (hexstr.obj) PyBuffer_Release(&hexstr); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } return return_value; } PyDoc_STRVAR(binascii_unhexlify__doc__, -"unhexlify($module, hexstr, /)\n" +"unhexlify($module, hexstr, /, *, ignorechars=b\'\')\n" "--\n" "\n" "Binary data of hexadecimal representation.\n" "\n" +" ignorechars\n" +" A byte string containing characters to ignore from the input.\n" +"\n" "hexstr must contain an even number of hex digits (upper or lower case)."); #define BINASCII_UNHEXLIFY_METHODDEF \ - {"unhexlify", (PyCFunction)binascii_unhexlify, METH_O, binascii_unhexlify__doc__}, + {"unhexlify", _PyCFunction_CAST(binascii_unhexlify), METH_FASTCALL|METH_KEYWORDS, binascii_unhexlify__doc__}, static PyObject * -binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr); +binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr, + Py_buffer *ignorechars); static PyObject * -binascii_unhexlify(PyObject *module, PyObject *arg) +binascii_unhexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - Py_buffer hexstr = {NULL, NULL}; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - if (!ascii_buffer_converter(arg, &hexstr)) { + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(ignorechars), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "ignorechars", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "unhexlify", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer hexstr = {NULL, NULL}; + Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } - return_value = binascii_unhexlify_impl(module, &hexstr); + if (!ascii_buffer_converter(args[0], &hexstr)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + if (PyObject_GetBuffer(args[1], &ignorechars, PyBUF_SIMPLE) != 0) { + goto exit; + } +skip_optional_kwonly: + return_value = binascii_unhexlify_impl(module, &hexstr, &ignorechars); exit: /* Cleanup for hexstr */ if (hexstr.obj) PyBuffer_Release(&hexstr); + /* Cleanup for ignorechars */ + if (ignorechars.obj) { + PyBuffer_Release(&ignorechars); + } return return_value; } @@ -1411,4 +1564,4 @@ exit: return return_value; } -/*[clinic end generated code: output=242c0c56b918bd33 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7afd570a9d5a3627 input=a9049054013a1b77]*/ From 473d2a35ceda738cdd4ffde9b7ace013c54ed683 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 1 Apr 2026 11:33:30 +0300 Subject: [PATCH 358/775] gh-147944: Increase range of bytes_per_sep (GH-147946) Accepted range for the bytes_per_sep argument of bytes.hex(), bytearray.hex(), memoryview.hex(), and binascii.b2a_hex() is now increased, so passing sys.maxsize and -sys.maxsize is now valid. --- Include/internal/pycore_strhex.h | 28 ++++++------- Lib/test/test_base64.py | 6 +-- Lib/test/test_bytes.py | 4 +- Lib/test/test_memoryview.py | 4 +- ...-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst | 4 ++ Modules/binascii.c | 10 ++--- Modules/clinic/binascii.c.h | 39 +++++++++++++------ Objects/bytearrayobject.c | 7 ++-- Objects/bytesobject.c | 6 +-- Objects/clinic/bytearrayobject.c.h | 21 +++++++--- Objects/clinic/bytesobject.c.h | 20 +++++++--- Objects/clinic/memoryobject.c.h | 21 +++++++--- Objects/memoryobject.c | 6 +-- Python/pystrhex.c | 23 +++++------ 14 files changed, 121 insertions(+), 78 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst diff --git a/Include/internal/pycore_strhex.h b/Include/internal/pycore_strhex.h index 225f423912f..656acae960a 100644 --- a/Include/internal/pycore_strhex.h +++ b/Include/internal/pycore_strhex.h @@ -10,28 +10,24 @@ extern "C" { // Returns a str() containing the hex representation of argbuf. // Export for '_hashlib' shared extension. -PyAPI_FUNC(PyObject*) _Py_strhex(const - char* argbuf, - const Py_ssize_t arglen); +PyAPI_FUNC(PyObject *) _Py_strhex(const char *argbuf, Py_ssize_t arglen); // Returns a bytes() containing the ASCII hex representation of argbuf. -extern PyObject* _Py_strhex_bytes( - const char* argbuf, - const Py_ssize_t arglen); +extern PyObject *_Py_strhex_bytes(const char *argbuf, Py_ssize_t arglen); // These variants include support for a separator between every N bytes: -extern PyObject* _Py_strhex_with_sep( - const char* argbuf, - const Py_ssize_t arglen, - PyObject* sep, - const int bytes_per_group); +extern PyObject *_Py_strhex_with_sep( + const char *argbuf, + Py_ssize_t arglen, + PyObject *sep, + Py_ssize_t bytes_per_group); // Export for 'binascii' shared extension -PyAPI_FUNC(PyObject*) _Py_strhex_bytes_with_sep( - const char* argbuf, - const Py_ssize_t arglen, - PyObject* sep, - const int bytes_per_group); +PyAPI_FUNC(PyObject *) _Py_strhex_bytes_with_sep( + const char *argbuf, + Py_ssize_t arglen, + PyObject *sep, + Py_ssize_t bytes_per_group); #ifdef __cplusplus } diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index bb3b3c1e235..d5f8f44e280 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -216,11 +216,9 @@ def _common_test_wrapcol(self, func, data): eq(func(data, wrapcol=80), expected) eq(func(b'', wrapcol=0), func(b'')) eq(func(b'', wrapcol=1), func(b'')) - if func is not base64.b16encode: - eq(func(data, wrapcol=sys.maxsize), expected) + eq(func(data, wrapcol=sys.maxsize), expected) if check_impl_detail(): - if func is not base64.b16encode: - eq(func(data, wrapcol=sys.maxsize*2), expected) + eq(func(data, wrapcol=sys.maxsize*2), expected) with self.assertRaises(OverflowError): func(data, wrapcol=2**1000) with self.assertRaises(ValueError): diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 120b611ba9c..b1cdbe04765 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -551,10 +551,10 @@ def test_hex_separator_basics(self): self.assertEqual(three_bytes.hex('*', -2), 'b901*ef') self.assertEqual(three_bytes.hex(sep=':', bytes_per_sep=2), 'b9:01ef') self.assertEqual(three_bytes.hex(sep='*', bytes_per_sep=-2), 'b901*ef') - for bytes_per_sep in 3, -3, 2**31-1, -(2**31-1): + for bytes_per_sep in 3, -3, sys.maxsize, -sys.maxsize: with self.subTest(bytes_per_sep=bytes_per_sep): self.assertEqual(three_bytes.hex(':', bytes_per_sep), 'b901ef') - for bytes_per_sep in 2**31, -2**31, 2**1000, -2**1000: + for bytes_per_sep in sys.maxsize+1, -sys.maxsize-1, 2**1000, -2**1000: with self.subTest(bytes_per_sep=bytes_per_sep): try: self.assertEqual(three_bytes.hex(':', bytes_per_sep), 'b901ef') diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py index 6e9f916f77b..22b9f6af758 100644 --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -718,10 +718,10 @@ def test_memoryview_hex_separator(self): self.assertEqual(m2.hex(':', -2), '6564:6362:61') self.assertEqual(m2.hex(sep=':', bytes_per_sep=2), '65:6463:6261') self.assertEqual(m2.hex(sep=':', bytes_per_sep=-2), '6564:6362:61') - for bytes_per_sep in 5, -5, 2**31-1, -(2**31-1): + for bytes_per_sep in 5, -5, sys.maxsize, -sys.maxsize: with self.subTest(bytes_per_sep=bytes_per_sep): self.assertEqual(m2.hex(':', bytes_per_sep), '6564636261') - for bytes_per_sep in 2**31, -2**31, 2**1000, -2**1000: + for bytes_per_sep in sys.maxsize+1, -sys.maxsize-1, 2**1000, -2**1000: with self.subTest(bytes_per_sep=bytes_per_sep): try: self.assertEqual(m2.hex(':', bytes_per_sep), '6564636261') diff --git a/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst b/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst new file mode 100644 index 00000000000..7ba75bac79c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst @@ -0,0 +1,4 @@ +Accepted range for the *bytes_per_sep* argument of :meth:`bytes.hex`, +:meth:`bytearray.hex`, :meth:`memoryview.hex`, and :func:`binascii.b2a_hex` +is now increased, so passing ``sys.maxsize`` and ``-sys.maxsize`` is now +valid. diff --git a/Modules/binascii.c b/Modules/binascii.c index 3cc67d74561..098c85036c9 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -2067,7 +2067,7 @@ binascii.b2a_hex data: Py_buffer sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2087,8 +2087,8 @@ b'b9_01ef' static PyObject * binascii_b2a_hex_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=a26937946a81d2c7 input=ec0ade6ba2e43543]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=7d703f866f74a813 input=6a1606f01a87118c]*/ { return _Py_strhex_bytes_with_sep((const char *)data->buf, data->len, sep, bytes_per_sep); @@ -2105,8 +2105,8 @@ available as "b2a_hex()". static PyObject * binascii_hexlify_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=d12aa1b001b15199 input=bc317bd4e241f76b]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=b99b3b39d234a3d4 input=bc317bd4e241f76b]*/ { return _Py_strhex_bytes_with_sep((const char *)data->buf, data->len, sep, bytes_per_sep); diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index bbddd7121bf..d27a6599724 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -6,6 +6,7 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_long.h" // _PyLong_Size_t_Converter() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() @@ -1060,7 +1061,7 @@ PyDoc_STRVAR(binascii_b2a_hex__doc__, static PyObject * binascii_b2a_hex_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1097,7 +1098,7 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1116,9 +1117,17 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[2]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = binascii_b2a_hex_impl(module, &data, sep, bytes_per_sep); @@ -1152,7 +1161,7 @@ PyDoc_STRVAR(binascii_hexlify__doc__, static PyObject * binascii_hexlify_impl(PyObject *module, Py_buffer *data, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1189,7 +1198,7 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1208,9 +1217,17 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[2]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = binascii_hexlify_impl(module, &data, sep, bytes_per_sep); @@ -1564,4 +1581,4 @@ exit: return return_value; } -/*[clinic end generated code: output=7afd570a9d5a3627 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=197a0f70aa392d39 input=a9049054013a1b77]*/ diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 552f7144c0d..c583193b5a2 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2640,7 +2640,7 @@ bytearray.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2659,8 +2659,9 @@ Create a string of hexadecimal numbers from a bytearray object. [clinic start generated code]*/ static PyObject * -bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep) -/*[clinic end generated code: output=29c4e5ef72c565a0 input=7784107de7048873]*/ +bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=c9563921aff1262b input=d2b23ef057cfcad5]*/ { char* argbuf = PyByteArray_AS_STRING(self); Py_ssize_t arglen = PyByteArray_GET_SIZE(self); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index b84ce2b53ef..902144e8ec9 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2743,7 +2743,7 @@ bytes.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2762,8 +2762,8 @@ Create a string of hexadecimal numbers from a bytes object. [clinic start generated code]*/ static PyObject * -bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep) -/*[clinic end generated code: output=1f134da504064139 input=1a21282b1f1ae595]*/ +bytes_hex_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=588821f02cb9d8f5 input=bd8eceb755d8230f]*/ { const char *argbuf = PyBytes_AS_STRING(self); Py_ssize_t arglen = PyBytes_GET_SIZE(self); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index d173f45d7be..64603adcc11 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -1723,7 +1723,8 @@ PyDoc_STRVAR(bytearray_hex__doc__, {"hex", _PyCFunction_CAST(bytearray_hex), METH_FASTCALL|METH_KEYWORDS, bytearray_hex__doc__}, static PyObject * -bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep); +bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t bytes_per_sep); static PyObject * bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1759,7 +1760,7 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1775,9 +1776,17 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: Py_BEGIN_CRITICAL_SECTION(self); @@ -1866,4 +1875,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl((PyByteArrayObject *)self); } -/*[clinic end generated code: output=d4976faf6731b8da input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2cacb323147202b9 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 99fcd48898c..4ff696be91b 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -1285,7 +1285,7 @@ PyDoc_STRVAR(bytes_hex__doc__, {"hex", _PyCFunction_CAST(bytes_hex), METH_FASTCALL|METH_KEYWORDS, bytes_hex__doc__}, static PyObject * -bytes_hex_impl(PyBytesObject *self, PyObject *sep, int bytes_per_sep); +bytes_hex_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t bytes_per_sep); static PyObject * bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1321,7 +1321,7 @@ bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1337,9 +1337,17 @@ bytes_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = bytes_hex_impl((PyBytesObject *)self, sep, bytes_per_sep); @@ -1442,4 +1450,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=5675f7008a84ce6d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b252801ff04a89b3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/memoryobject.c.h b/Objects/clinic/memoryobject.c.h index 28cfd1a2208..d97c626532c 100644 --- a/Objects/clinic/memoryobject.c.h +++ b/Objects/clinic/memoryobject.c.h @@ -6,6 +6,7 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(memoryview__doc__, @@ -366,7 +367,7 @@ PyDoc_STRVAR(memoryview_hex__doc__, static PyObject * memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep, - int bytes_per_sep); + Py_ssize_t bytes_per_sep); static PyObject * memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -402,7 +403,7 @@ memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject PyObject *argsbuf[2]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *sep = NULL; - int bytes_per_sep = 1; + Py_ssize_t bytes_per_sep = 1; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -418,9 +419,17 @@ memoryview_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - bytes_per_sep = PyLong_AsInt(args[1]); - if (bytes_per_sep == -1 && PyErr_Occurred()) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bytes_per_sep = ival; } skip_optional_pos: return_value = memoryview_hex_impl((PyMemoryViewObject *)self, sep, bytes_per_sep); @@ -496,4 +505,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=154f4c04263ccb24 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=348b6ddb98a1f412 input=a9049054013a1b77]*/ diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index bca77851ac2..4cbbb7eb7cd 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2358,7 +2358,7 @@ memoryview.hex sep: object = NULL An optional single character or byte to separate hex bytes. - bytes_per_sep: int = 1 + bytes_per_sep: Py_ssize_t = 1 How many bytes between separators. Positive values count from the right, negative values count from the left. @@ -2378,8 +2378,8 @@ Return the data in the buffer as a str of hexadecimal numbers. static PyObject * memoryview_hex_impl(PyMemoryViewObject *self, PyObject *sep, - int bytes_per_sep) -/*[clinic end generated code: output=430ca760f94f3ca7 input=539f6a3a5fb56946]*/ + Py_ssize_t bytes_per_sep) +/*[clinic end generated code: output=c9bb00c7a8e86056 input=dc48a56ed3b058ae]*/ { Py_buffer *src = VIEW_ADDR(self); diff --git a/Python/pystrhex.c b/Python/pystrhex.c index 698e7f26fba..14d5719313a 100644 --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -111,9 +111,10 @@ _Py_hexlify_simd(const unsigned char *src, Py_UCS1 *dst, Py_ssize_t len) #endif /* HAVE_EFFICIENT_BUILTIN_SHUFFLEVECTOR */ -static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, int bytes_per_sep_group, - const int return_bytes) +static PyObject * +_Py_strhex_impl(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_sep_group, + int return_bytes) { assert(arglen >= 0); @@ -149,7 +150,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, else { bytes_per_sep_group = 0; } - unsigned int abs_bytes_per_sep = _Py_ABS_CAST(unsigned int, bytes_per_sep_group); + size_t abs_bytes_per_sep = _Py_ABS_CAST(size_t, bytes_per_sep_group); Py_ssize_t resultlen = 0; if (bytes_per_sep_group && arglen > 0) { /* How many sep characters we'll be inserting. */ @@ -203,7 +204,7 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, /* The number of complete chunk+sep periods */ Py_ssize_t chunks = (arglen - 1) / abs_bytes_per_sep; Py_ssize_t chunk; - unsigned int k; + size_t k; if (bytes_per_sep_group < 0) { i = j = 0; @@ -251,30 +252,30 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, return retval; } -PyObject * _Py_strhex(const char* argbuf, const Py_ssize_t arglen) +PyObject * _Py_strhex(const char* argbuf, Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, NULL, 0, 0); } /* Same as above but returns a bytes() instead of str() to avoid the * need to decode the str() when bytes are needed. */ -PyObject* _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen) +PyObject* _Py_strhex_bytes(const char* argbuf, Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, NULL, 0, 1); } /* These variants include support for a separator between every N bytes: */ -PyObject* _Py_strhex_with_sep(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, const int bytes_per_group) +PyObject* _Py_strhex_with_sep(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_group) { return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 0); } /* Same as above but returns a bytes() instead of str() to avoid the * need to decode the str() when bytes are needed. */ -PyObject* _Py_strhex_bytes_with_sep(const char* argbuf, const Py_ssize_t arglen, - PyObject* sep, const int bytes_per_group) +PyObject* _Py_strhex_bytes_with_sep(const char* argbuf, Py_ssize_t arglen, + PyObject* sep, Py_ssize_t bytes_per_group) { return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 1); } From b38cfb7bcaa88b8036856b1e3d333fc1119786bb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 1 Apr 2026 12:35:58 +0200 Subject: [PATCH 359/775] gh-146479: Skip test_frame_pointer_unwind for gcc -O3 --enable-shared (#147947) Skip the test if Python is built with --enable-shared and "gcc -O2" or "gcc -O3". --- Lib/test/test_frame_pointer_unwind.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Lib/test/test_frame_pointer_unwind.py b/Lib/test/test_frame_pointer_unwind.py index 5804cc7e1d7..c70ec281686 100644 --- a/Lib/test/test_frame_pointer_unwind.py +++ b/Lib/test/test_frame_pointer_unwind.py @@ -25,13 +25,19 @@ def _frame_pointers_expected(machine): ) if value ) + if "no-omit-frame-pointer" in cflags: + # For example, configure adds -fno-omit-frame-pointer if Python + # has perf trampoline (PY_HAVE_PERF_TRAMPOLINE) and Python is built + # in debug mode. return True if "omit-frame-pointer" in cflags: return False + if sys.platform == "darwin": # macOS x86_64/ARM64 always have frame pointer by default. return True + if sys.platform == "linux": if machine in {"aarch64", "arm64"}: # 32-bit Linux is not supported @@ -39,7 +45,21 @@ def _frame_pointers_expected(machine): return None return True if machine == "x86_64": + final_opt = "" + for opt in cflags.split(): + if opt.startswith('-O'): + final_opt = opt + if final_opt in ("-O0", "-Og", "-O1"): + # Unwinding works if the optimization level is low + return True + + Py_ENABLE_SHARED = int(sysconfig.get_config_var('Py_ENABLE_SHARED') or '0') + if Py_ENABLE_SHARED: + # Unwinding does crash using gcc -O2 or gcc -O3 + # when Python is built with --enable-shared + return "crash" return False + if sys.platform == "win32": # MSVC ignores /Oy and /Oy- on x64/ARM64. if machine == "arm64": @@ -153,10 +173,14 @@ class FramePointerUnwindTests(unittest.TestCase): def setUp(self): super().setUp() + machine = platform.machine().lower() expected = _frame_pointers_expected(machine) if expected is None: self.skipTest(f"unsupported architecture for frame pointer check: {machine}") + if expected == "crash": + self.skipTest(f"test does crash on {machine}") + try: _testinternalcapi.manual_frame_pointer_unwind() except RuntimeError as exc: From a504c0a590b9379688e4718225efb361b94cc4a1 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 1 Apr 2026 08:46:19 -0400 Subject: [PATCH 360/775] gh-146488: hash-pin all action references Signed-off-by: William Woodruff --- .github/workflows/add-issue-header.yml | 2 +- .github/workflows/build.yml | 30 +++++++++---------- .github/workflows/documentation-links.yml | 2 +- .github/workflows/jit.yml | 18 +++++------ .github/workflows/lint.yml | 4 +-- .github/workflows/mypy.yml | 4 +-- .../workflows/new-bugs-announce-notifier.yml | 4 +-- .github/workflows/require-pr-label.yml | 8 ++--- .../workflows/reusable-check-c-api-docs.yml | 4 +-- .github/workflows/reusable-cifuzz.yml | 8 ++--- .github/workflows/reusable-context.yml | 4 +-- .github/workflows/reusable-docs.yml | 12 ++++---- .github/workflows/reusable-emscripten.yml | 8 ++--- .github/workflows/reusable-macos.yml | 2 +- .github/workflows/reusable-san.yml | 4 +-- .github/workflows/reusable-ubuntu.yml | 4 +-- .github/workflows/reusable-wasi.yml | 6 ++-- .github/workflows/reusable-windows-msi.yml | 2 +- .github/workflows/reusable-windows.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/tail-call.yml | 8 ++--- .github/workflows/verify-ensurepip-wheels.yml | 4 +-- .github/workflows/verify-expat.yml | 2 +- .github/zizmor.yml | 4 --- 24 files changed, 72 insertions(+), 76 deletions(-) diff --git a/.github/workflows/add-issue-header.yml b/.github/workflows/add-issue-header.yml index c404bc51930..8a8571eedd1 100644 --- a/.github/workflows/add-issue-header.yml +++ b/.github/workflows/add-issue-header.yml @@ -20,7 +20,7 @@ jobs: issues: write timeout-minutes: 5 steps: - - uses: actions/github-script@v8 + - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: # language=JavaScript script: | diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd5ccf4b3a5..025032a3ae6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: run: | apt update && apt install git -yq git config --global --add safe.directory "$GITHUB_WORKSPACE" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 1 persist-credentials: false @@ -101,10 +101,10 @@ jobs: needs: build-context if: needs.build-context.outputs.run-tests == 'true' steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.x' - name: Runner image version @@ -291,7 +291,7 @@ jobs: SSLLIB_DIR: ${{ github.workspace }}/multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }} LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }}/lib steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version @@ -302,7 +302,7 @@ jobs: run: sudo ./.github/workflows/posix-deps-apt.sh - name: 'Restore SSL library build' id: cache-ssl-lib - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ./multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }} key: ${{ matrix.os }}-multissl-${{ matrix.ssllib.name }}-${{ matrix.ssllib.version }} @@ -350,7 +350,7 @@ jobs: runs-on: ${{ matrix.runs-on }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Build and test @@ -363,7 +363,7 @@ jobs: timeout-minutes: 60 runs-on: macos-14 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -401,7 +401,7 @@ jobs: OPENSSL_VER: 3.5.5 PYTHONSTRICTEXTENSIONBUILD: 1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Register gcc problem matcher @@ -415,7 +415,7 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV" - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }} @@ -462,7 +462,7 @@ jobs: ./python -m venv "$VENV_LOC" && "$VENV_PYTHON" -m pip install -r "${GITHUB_WORKSPACE}/Tools/requirements-hypothesis.txt" - name: 'Restore Hypothesis database' id: cache-hypothesis-database - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ${{ env.CPYTHON_BUILDDIR }}/.hypothesis/ key: hypothesis-database-${{ github.head_ref || github.run_id }} @@ -489,7 +489,7 @@ jobs: -x test_subprocess \ -x test_signal \ -x test_sysconfig - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: always() with: name: hypothesis-example-db @@ -510,7 +510,7 @@ jobs: PYTHONSTRICTEXTENSIONBUILD: 1 ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version @@ -520,7 +520,7 @@ jobs: - name: Install dependencies run: sudo ./.github/workflows/posix-deps-apt.sh - name: Set up GCC-10 for ASAN - uses: egor-tensin/setup-gcc@v2 + uses: egor-tensin/setup-gcc@a2861a8b8538f49cf2850980acccf6b05a1b2ae4 # v2.0 with: version: 10 - name: Configure OpenSSL env vars @@ -530,7 +530,7 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV" - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ matrix.os }}-multissl-openssl-${{ env.OPENSSL_VER }} @@ -577,7 +577,7 @@ jobs: needs: build-context if: needs.build-context.outputs.run-ubuntu == 'true' steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version diff --git a/.github/workflows/documentation-links.yml b/.github/workflows/documentation-links.yml index a09a30587b3..19314dd0c88 100644 --- a/.github/workflows/documentation-links.yml +++ b/.github/workflows/documentation-links.yml @@ -22,7 +22,7 @@ jobs: timeout-minutes: 5 steps: - - uses: readthedocs/actions/preview@v1 + - uses: readthedocs/actions/preview@b8bba1484329bda1a3abe986df7ebc80a8950333 # v1.5 with: project-slug: "cpython-previews" single-version: "true" diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 1a3fcb3637e..483ace25554 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Build tier two interpreter @@ -69,10 +69,10 @@ jobs: architecture: ARM64 runner: windows-11-arm steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' # PCbuild downloads LLVM automatically: @@ -103,10 +103,10 @@ jobs: - target: aarch64-apple-darwin/clang runner: macos-26 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - name: Install LLVM @@ -146,10 +146,10 @@ jobs: - target: aarch64-unknown-linux-gnu/gcc runner: ubuntu-24.04-arm steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - name: Build @@ -182,10 +182,10 @@ jobs: use_clang: true run_tests: false steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - name: Build diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0ded53b00da..e9a4eb2b080 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: j178/prek-action@v1 + - uses: j178/prek-action@0bb87d7f00b0c99306c8bcb8b8beba1eb581c037 # v1.1.1 diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index db363bef7a4..e5a5b3939e5 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -65,10 +65,10 @@ jobs: "Tools/peg_generator", ] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" cache: pip diff --git a/.github/workflows/new-bugs-announce-notifier.yml b/.github/workflows/new-bugs-announce-notifier.yml index 9ee38a4fd1c..1f28b9befb4 100644 --- a/.github/workflows/new-bugs-announce-notifier.yml +++ b/.github/workflows/new-bugs-announce-notifier.yml @@ -13,12 +13,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/setup-node@v6 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 20 - run: npm install mailgun.js form-data - name: Send notification - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: MAILGUN_API_KEY: ${{ secrets.MAILGUN_PYTHON_ORG_MAILGUN_KEY }} with: diff --git a/.github/workflows/require-pr-label.yml b/.github/workflows/require-pr-label.yml index 7e534c58c79..94cb219aeee 100644 --- a/.github/workflows/require-pr-label.yml +++ b/.github/workflows/require-pr-label.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Check there's no DO-NOT-MERGE - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 0 @@ -33,7 +33,7 @@ jobs: steps: # Check that the PR is not awaiting changes from the author due to previous review. - name: Check there's no required changes - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 0 @@ -42,7 +42,7 @@ jobs: awaiting change review - id: is-feature name: Check whether this PR is a feature (contains a "type-feature" label) - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 1 @@ -53,7 +53,7 @@ jobs: - id: awaiting-merge if: steps.is-feature.outputs.status == 'success' name: Check for complete review - uses: mheap/github-action-required-labels@v5 + uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2 with: mode: exactly count: 1 diff --git a/.github/workflows/reusable-check-c-api-docs.yml b/.github/workflows/reusable-check-c-api-docs.yml index b95bd6a0184..49e5ef7f768 100644 --- a/.github/workflows/reusable-check-c-api-docs.yml +++ b/.github/workflows/reusable-check-c-api-docs.yml @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.x' - name: Check for undocumented C APIs diff --git a/.github/workflows/reusable-cifuzz.yml b/.github/workflows/reusable-cifuzz.yml index 6cd9c26037f..339fca7919c 100644 --- a/.github/workflows/reusable-cifuzz.yml +++ b/.github/workflows/reusable-cifuzz.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Build fuzzers (${{ inputs.sanitizer }}) id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@ed23f8af80ff82b25ca67cd9b101e690b8897b3f # master with: oss-fuzz-project-name: ${{ inputs.oss-fuzz-project-name }} sanitizer: ${{ inputs.sanitizer }} - name: Run fuzzers (${{ inputs.sanitizer }}) - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@ed23f8af80ff82b25ca67cd9b101e690b8897b3f # master with: fuzz-seconds: 600 oss-fuzz-project-name: ${{ inputs.oss-fuzz-project-name }} @@ -34,13 +34,13 @@ jobs: sanitizer: ${{ inputs.sanitizer }} - name: Upload crash if: failure() && steps.build.outcome == 'success' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: ${{ inputs.sanitizer }}-artifacts path: ./out/artifacts - name: Upload SARIF if: always() && steps.build.outcome == 'success' - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: sarif_file: cifuzz-sarif/results.sarif checkout_path: cifuzz-sarif diff --git a/.github/workflows/reusable-context.yml b/.github/workflows/reusable-context.yml index fc80e6671b5..0f0ca3475b3 100644 --- a/.github/workflows/reusable-context.yml +++ b/.github/workflows/reusable-context.yml @@ -74,14 +74,14 @@ jobs: run-windows-tests: ${{ steps.changes.outputs.run-windows-tests }} steps: - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3" - run: >- echo '${{ github.event_name }}' - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false ref: >- diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml index c1e58fd44d3..bee44e8df27 100644 --- a/.github/workflows/reusable-docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -27,7 +27,7 @@ jobs: refspec_pr: '+${{ github.event.pull_request.head.sha }}:remotes/origin/${{ github.event.pull_request.head.ref }}' steps: - name: 'Check out latest PR branch commit' - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false ref: >- @@ -52,7 +52,7 @@ jobs: git fetch origin "${refspec_base}" --shallow-since="${DATE}" \ --no-tags --prune --no-recurse-submodules - name: 'Set up Python' - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3' cache: 'pip' @@ -82,10 +82,10 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@v5 + - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.cache/pip key: ubuntu-doc-${{ hashFiles('Doc/requirements.txt') }} @@ -108,11 +108,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: 'Set up Python' - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3' cache: 'pip' diff --git a/.github/workflows/reusable-emscripten.yml b/.github/workflows/reusable-emscripten.yml index b79cb5bca29..ce3e65f11a3 100644 --- a/.github/workflows/reusable-emscripten.yml +++ b/.github/workflows/reusable-emscripten.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Read Emscripten config" @@ -38,18 +38,18 @@ jobs: with open(os.environ["GITHUB_ENV"], "a") as f: f.write(f"EMSDK_CACHE={emsdk_cache}\n") - name: "Install Node.js" - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ steps.emscripten-config.outputs.node-version }} - name: "Cache Emscripten SDK" id: emsdk-cache - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ${{ env.EMSDK_CACHE }} key: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }}-${{ steps.emscripten-config.outputs.deps-hash }} restore-keys: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }} - name: "Install Python" - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.x' - name: "Runner image version" diff --git a/.github/workflows/reusable-macos.yml b/.github/workflows/reusable-macos.yml index a96aab1be1d..9d8e6b03464 100644 --- a/.github/workflows/reusable-macos.yml +++ b/.github/workflows/reusable-macos.yml @@ -28,7 +28,7 @@ jobs: PYTHONSTRICTEXTENSIONBUILD: 1 TERM: linux steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version diff --git a/.github/workflows/reusable-san.yml b/.github/workflows/reusable-san.yml index 79a4ded09fc..4e2891ab9b7 100644 --- a/.github/workflows/reusable-san.yml +++ b/.github/workflows/reusable-san.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Runner image version @@ -96,7 +96,7 @@ jobs: run: find "${GITHUB_WORKSPACE}" -name 'san_log.*' | xargs head -n 1000 - name: Archive logs if: always() - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: >- ${{ inputs.sanitizer }}-logs-${{ diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml index 6464590dee4..87274a7b8a3 100644 --- a/.github/workflows/reusable-ubuntu.yml +++ b/.github/workflows/reusable-ubuntu.yml @@ -36,7 +36,7 @@ jobs: PYTHONSTRICTEXTENSIONBUILD: 1 TERM: linux steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Register gcc problem matcher @@ -56,7 +56,7 @@ jobs: echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV" - name: 'Restore OpenSSL build' id: cache-openssl - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ./multissl/openssl/${{ env.OPENSSL_VER }} key: ${{ inputs.os }}-multissl-openssl-${{ env.OPENSSL_VER }} diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml index 8d76679a400..9bff508bd66 100644 --- a/.github/workflows/reusable-wasi.yml +++ b/.github/workflows/reusable-wasi.yml @@ -16,12 +16,12 @@ jobs: CROSS_BUILD_PYTHON: cross-build/build CROSS_BUILD_WASI: cross-build/wasm32-wasip1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false # No problem resolver registered as one doesn't currently exist for Clang. - name: "Install wasmtime" - uses: bytecodealliance/actions/wasmtime/setup@v1 + uses: bytecodealliance/actions/wasmtime/setup@9152e710e9f7182e4c29ad218e4f335a7b203613 # v1.1.3 with: version: ${{ env.WASMTIME_VERSION }} - name: "Read WASI SDK version" @@ -42,7 +42,7 @@ jobs: version: ${{ steps.wasi-sdk-version.outputs.version }} add-to-path: false - name: "Install Python" - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.x' - name: "Runner image version" diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index 42c0dfd9636..a74724323ec 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -23,7 +23,7 @@ jobs: ARCH: ${{ inputs.arch }} IncludeFreethreaded: true steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Build CPython installer diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 8772a04d779..1c399689cde 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -30,7 +30,7 @@ jobs: env: ARCH: ${{ inputs.arch }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Register MSVC problem matcher diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 915b1acd33f..37220783f9c 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,7 +14,7 @@ jobs: steps: - name: "Check PRs" - uses: actions/stale@v10 + uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This PR is stale because it has been open for 30 days with no activity.' diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index 08bd986a64a..a86a3135246 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -36,10 +36,10 @@ jobs: - target: aarch64-apple-darwin/clang runner: macos-26 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - name: Install dependencies @@ -75,10 +75,10 @@ jobs: runner: ubuntu-24.04-arm configure_flags: --with-pydebug steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3.11' - name: Build diff --git a/.github/workflows/verify-ensurepip-wheels.yml b/.github/workflows/verify-ensurepip-wheels.yml index 13597907871..cb40f6abc0b 100644 --- a/.github/workflows/verify-ensurepip-wheels.yml +++ b/.github/workflows/verify-ensurepip-wheels.yml @@ -25,10 +25,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/setup-python@v6 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3' - name: Compare checksum of bundled wheels to the ones published on PyPI diff --git a/.github/workflows/verify-expat.yml b/.github/workflows/verify-expat.yml index 6b12b95cb11..472a11db2da 100644 --- a/.github/workflows/verify-expat.yml +++ b/.github/workflows/verify-expat.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Download and verify bundled libexpat files diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 8b7b4de0fc8..7c776d5ea1f 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -4,7 +4,3 @@ rules: dangerous-triggers: ignore: - documentation-links.yml - unpinned-uses: - config: - policies: - "*": ref-pin From 07d5d724849b08442a5e6a54b987e43e038c18b1 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Wed, 1 Apr 2026 14:46:57 +0200 Subject: [PATCH 361/775] Increase dependabot interval to quarterly (#147959) --- .github/dependabot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e68a07382d5..4b77646e22d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,7 +3,7 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "monthly" + interval: "quarterly" labels: - "skip issue" - "skip news" @@ -24,7 +24,7 @@ updates: - package-ecosystem: "pip" directory: "/Tools/" schedule: - interval: "monthly" + interval: "quarterly" labels: - "skip issue" - "skip news" From 08c5d3d4234e87497f47c7ecd70616b4e24ed765 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Wed, 1 Apr 2026 15:10:27 +0200 Subject: [PATCH 362/775] gh-145000: Run `check-html-ids.py` in CI (#145632) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- .github/workflows/reusable-check-html-ids.yml | 58 +++++++++++++++++++ .github/workflows/reusable-docs.yml | 16 +++++ Doc/tools/check-html-ids.py | 1 + Doc/tools/removed-ids.txt | 1 + 4 files changed, 76 insertions(+) create mode 100644 .github/workflows/reusable-check-html-ids.yml create mode 100644 Doc/tools/removed-ids.txt diff --git a/.github/workflows/reusable-check-html-ids.yml b/.github/workflows/reusable-check-html-ids.yml new file mode 100644 index 00000000000..47a2e25de36 --- /dev/null +++ b/.github/workflows/reusable-check-html-ids.yml @@ -0,0 +1,58 @@ +name: Reusable check HTML IDs + +on: + workflow_call: + +permissions: + contents: read + +env: + FORCE_COLOR: 1 + +jobs: + check-html-ids: + name: 'Check for removed HTML IDs' + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: 'Check out base commit' + uses: actions/checkout@v6 + with: + persist-credentials: false + ref: ${{ github.event.pull_request.base.sha }} + - name: 'Set up Python' + uses: actions/setup-python@v6 + with: + python-version: '3' + cache: 'pip' + cache-dependency-path: 'Doc/requirements.txt' + - name: 'Install build dependencies' + run: make -C Doc/ venv + - name: 'Build HTML documentation' + run: make -C Doc/ SPHINXOPTS="--quiet" html + - name: 'Check out PR head tools' + uses: actions/checkout@v6 + with: + persist-credentials: false + sparse-checkout: | + Doc/tools/check-html-ids.py + Doc/tools/removed-ids.txt + sparse-checkout-cone-mode: false + path: pr-head + - name: 'Use PR head tools' + run: | + cp pr-head/Doc/tools/check-html-ids.py Doc/tools/check-html-ids.py + [ -f pr-head/Doc/tools/removed-ids.txt ] && cp pr-head/Doc/tools/removed-ids.txt Doc/tools/removed-ids.txt + - name: 'Collect HTML IDs' + run: python Doc/tools/check-html-ids.py collect Doc/build/html -o /tmp/html-ids-base.json.gz + - name: 'Download PR head HTML IDs' + uses: actions/download-artifact@v8 + with: + name: html-ids-head.json.gz + path: /tmp + - name: 'Check for removed HTML IDs' + run: | + # shellcheck disable=SC2046 + python Doc/tools/check-html-ids.py -v check \ + /tmp/html-ids-base.json.gz /tmp/html-ids-head.json.gz \ + $([ -f Doc/tools/removed-ids.txt ] && echo "--exclude-file Doc/tools/removed-ids.txt") diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml index bee44e8df27..5227c04c06f 100644 --- a/.github/workflows/reusable-docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -75,6 +75,22 @@ jobs: --fail-if-regression \ --fail-if-improved \ --fail-if-new-news-nit + - name: 'Collect HTML IDs' + if: github.event_name == 'pull_request' + run: python Doc/tools/check-html-ids.py collect Doc/build/html -o Doc/build/html-ids-head.json.gz + - name: 'Upload HTML IDs' + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v7 + with: + name: html-ids-head + path: Doc/build/html-ids-head.json.gz + archive: false + + check-html-ids: + name: 'Check for removed HTML IDs' + needs: build-doc + if: github.event_name == 'pull_request' + uses: ./.github/workflows/reusable-check-html-ids.yml # Run "doctest" on HEAD as new syntax doesn't exist in the latest stable release doctest: diff --git a/Doc/tools/check-html-ids.py b/Doc/tools/check-html-ids.py index 8e8e0a581df..7d86c6cc326 100644 --- a/Doc/tools/check-html-ids.py +++ b/Doc/tools/check-html-ids.py @@ -175,6 +175,7 @@ def verbose_print(*args, **kwargs): ) if args.exclude_file: print(f'Alternatively, add them to {args.exclude_file}.') + sys.exit(1) if __name__ == '__main__': diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt new file mode 100644 index 00000000000..f3cd8bf0ef5 --- /dev/null +++ b/Doc/tools/removed-ids.txt @@ -0,0 +1 @@ +# HTML IDs excluded from the check-html-ids.py check. From 245232400135ade421f656edcf665a7185c0c5c2 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 1 Apr 2026 16:14:59 +0200 Subject: [PATCH 363/775] gh-146636: PEP 803: add Py_TARGET_ABI3T and .abi3t.so extension (GH-146637) - Add Py_TARGET_ABI3T macro. - Add ".abi3t.so" to importlib EXTENSION_SUFFIXES. - Remove ".abi3.so" from importlib EXTENSION_SUFFIXES on Free Threading. - Adjust tests This is part of the implementation for PEP-803. Detailed documentation to come later. Co-authored-by: Nathan Goldbaum --- Doc/c-api/stable.rst | 10 +++++++ Include/Python.h | 4 --- Include/patchlevel.h | 28 +++++++++++++++++++ Lib/test/test_cext/__init__.py | 17 ++++++----- Lib/test/test_cext/setup.py | 12 ++++---- .../test_importlib/extension/test_finder.py | 16 ++++++++++- Python/dynload_shlib.c | 3 ++ 7 files changed, 69 insertions(+), 21 deletions(-) diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst index f5e6b7ad157..f8b41f6d87f 100644 --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -88,6 +88,16 @@ Contents of the Limited API are :ref:`listed below `. You can also define ``Py_LIMITED_API`` to ``3``. This works the same as ``0x03020000`` (Python 3.2, the version that introduced Limited API). +.. c:macro:: Py_TARGET_ABI3T + + Define this macro before including ``Python.h`` to opt in to only use + the Limited API for :term:`free-threaded builds `, + and to select the Limited API version. + + .. seealso:: :pep:`803` + + .. versionadded:: next + .. _stable-abi: diff --git a/Include/Python.h b/Include/Python.h index 17cbc083241..e6e5cab67e2 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -47,10 +47,6 @@ #endif #if defined(Py_GIL_DISABLED) -# if defined(Py_LIMITED_API) && !defined(_Py_OPAQUE_PYOBJECT) -# error "Py_LIMITED_API is not currently supported in the free-threaded build" -# endif - # if defined(_MSC_VER) # include // __readgsqword() # endif diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 7cffd74125f..154bdb0721d 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -61,4 +61,32 @@ #define PYTHON_ABI_VERSION 3 #define PYTHON_ABI_STRING "3" + +/* Stable ABI for free-threaded builds (introduced in PEP 803) + is enabled by one of: + - Py_TARGET_ABI3T, or + - Py_LIMITED_API and Py_GIL_DISABLED. + "Output" macros to be used internally: + - Py_LIMITED_API (defines the subset of API we expose) + - _Py_OPAQUE_PYOBJECT (additionally hides what's ABI-incompatible between + free-threaded & GIL) + (Don't use Py_TARGET_ABI3T directly: it's currently only used to set these + 2 macros. It's also available for users' convenience.) + */ +#if defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) \ + && !defined(Py_TARGET_ABI3T) +# define Py_TARGET_ABI3T Py_LIMITED_API +#endif +#if defined(Py_TARGET_ABI3T) +# define _Py_OPAQUE_PYOBJECT +# if !defined(Py_LIMITED_API) +# define Py_LIMITED_API Py_TARGET_ABI3T +# elif Py_LIMITED_API > Py_TARGET_ABI3T + // if both are defined, use the *lower* version, + // i.e. maximum compatibility +# undef Py_LIMITED_API +# define Py_LIMITED_API Py_TARGET_ABI3T +# endif +#endif + #endif //_Py_PATCHLEVEL_H diff --git a/Lib/test/test_cext/__init__.py b/Lib/test/test_cext/__init__.py index a52c2241f5d..1958c44e2b6 100644 --- a/Lib/test/test_cext/__init__.py +++ b/Lib/test/test_cext/__init__.py @@ -38,15 +38,15 @@ def test_build(self): self.check_build('_test_cext') def check_build(self, extension_name, std=None, limited=False, - opaque_pyobject=False): + abi3t=False): venv_dir = 'env' with support.setup_venv_with_pip_setuptools(venv_dir) as python_exe: self._check_build(extension_name, python_exe, std=std, limited=limited, - opaque_pyobject=opaque_pyobject) + abi3t=abi3t) def _check_build(self, extension_name, python_exe, std, limited, - opaque_pyobject): + abi3t): pkg_dir = 'pkg' os.mkdir(pkg_dir) shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP))) @@ -60,8 +60,8 @@ def run_cmd(operation, cmd): env['CPYTHON_TEST_STD'] = std if limited: env['CPYTHON_TEST_LIMITED'] = '1' - if opaque_pyobject: - env['CPYTHON_TEST_OPAQUE_PYOBJECT'] = '1' + if abi3t: + env['CPYTHON_TEST_ABI3T'] = '1' env['CPYTHON_TEST_EXT_NAME'] = extension_name env['TEST_INTERNAL_C_API'] = str(int(self.TEST_INTERNAL_C_API)) if support.verbose: @@ -116,10 +116,9 @@ def test_build_limited_c11(self): def test_build_c11(self): self.check_build('_test_c11_cext', std='c11') - def test_build_opaque_pyobject(self): - # Test with _Py_OPAQUE_PYOBJECT - self.check_build('_test_limited_opaque_cext', limited=True, - opaque_pyobject=True) + def test_build_abi3t(self): + # Test with Py_TARGET_ABI3T + self.check_build('_test_abi3t', abi3t=True) @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c99") def test_build_c99(self): diff --git a/Lib/test/test_cext/setup.py b/Lib/test/test_cext/setup.py index db43f6fb17a..7262a110d83 100644 --- a/Lib/test/test_cext/setup.py +++ b/Lib/test/test_cext/setup.py @@ -59,7 +59,7 @@ def main(): std = os.environ.get("CPYTHON_TEST_STD", "") module_name = os.environ["CPYTHON_TEST_EXT_NAME"] limited = bool(os.environ.get("CPYTHON_TEST_LIMITED", "")) - opaque_pyobject = bool(os.environ.get("CPYTHON_TEST_OPAQUE_PYOBJECT", "")) + abi3t = bool(os.environ.get("CPYTHON_TEST_ABI3T", "")) internal = bool(int(os.environ.get("TEST_INTERNAL_C_API", "0"))) sources = [SOURCE] @@ -91,14 +91,12 @@ def main(): # CC env var overrides sysconfig CC variable in setuptools os.environ['CC'] = cmd - # Define Py_LIMITED_API macro + # Define opt-in macros if limited: - version = sys.hexversion - cflags.append(f'-DPy_LIMITED_API={version:#x}') + cflags.append(f'-DPy_LIMITED_API={sys.hexversion:#x}') - # Define _Py_OPAQUE_PYOBJECT macro - if opaque_pyobject: - cflags.append(f'-D_Py_OPAQUE_PYOBJECT') + if abi3t: + cflags.append(f'-DPy_TARGET_ABI3T={sys.hexversion:#x}') if internal: cflags.append('-DTEST_INTERNAL_C_API=1') diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index cdc8884d668..dc77fa78a20 100644 --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -1,4 +1,4 @@ -from test.support import is_apple_mobile +from test.support import is_apple_mobile, Py_GIL_DISABLED from test.test_importlib import abc, util machinery = util.import_importlib('importlib.machinery') @@ -59,6 +59,20 @@ def test_module(self): def test_failure(self): self.assertIsNone(self.find_spec('asdfjkl;')) + def test_abi3_extension_suffixes(self): + suffixes = self.machinery.EXTENSION_SUFFIXES + if 'win32' in sys.platform: + # Either "_d.pyd" or ".pyd" must be in suffixes + self.assertTrue({"_d.pyd", ".pyd"}.intersection(suffixes)) + elif 'cygwin' in sys.platform: + pass + else: + if Py_GIL_DISABLED: + self.assertNotIn(".abi3.so", suffixes) + else: + self.assertIn(".abi3.so", suffixes) + self.assertIn(".abi3t.so", suffixes) + (Frozen_FinderTests, Source_FinderTests diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 583c9b752df..2e1455fbe23 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -44,7 +44,10 @@ const char *_PyImport_DynLoadFiletab[] = { #ifdef ALT_SOABI "." ALT_SOABI ".so", #endif +#ifndef Py_GIL_DISABLED ".abi" PYTHON_ABI_STRING ".so", +#endif /* Py_GIL_DISABLED */ + ".abi" PYTHON_ABI_STRING "t.so", ".so", #endif /* __CYGWIN__ */ NULL, From 03f3b9ade975e78a31bf776ff27ac6ac22fcb65a Mon Sep 17 00:00:00 2001 From: konsti Date: Wed, 1 Apr 2026 16:17:56 +0200 Subject: [PATCH 364/775] gh-146907: Clarify ABI compatibility between debug and release builds (GH-146925) --- Doc/using/configure.rst | 6 ++++-- Doc/whatsnew/3.8.rst | 15 ++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index b218325b140..cc6aafe80f8 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -906,9 +906,11 @@ See also the :ref:`Python Development Mode ` and the :option:`--with-trace-refs` configure option. .. versionchanged:: 3.8 - Release builds and debug builds are now ABI compatible: defining the + Release builds are now ABI compatible with debug builds: defining the ``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro (see the - :option:`--with-trace-refs` option). + :option:`--with-trace-refs` option). However, debug builds still expose + more symbols than release builds and code built against a debug build is not + necessarily compatible with a release build. Debug options diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 91cd23f6f2b..5078fc30ac1 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -207,14 +207,15 @@ subdirectories). Debug build uses the same ABI as release build ----------------------------------------------- -Python now uses the same ABI whether it's built in release or debug mode. On -Unix, when Python is built in debug mode, it is now possible to load C -extensions built in release mode and C extensions built using the stable ABI. +The ABI of Python :ref:`debug builds ` is now compatible with +Python release builds. On Unix, when Python is built in debug mode, it is now +possible to load C extensions built in release mode and C extensions built +using the stable ABI. The inverse is not true, as debug builds expose +additional symbols not available in release builds. -Release builds and :ref:`debug builds ` are now ABI compatible: defining the -``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, which -introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, which -adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` +Defining the ``Py_DEBUG`` macro no longer implies the ``Py_TRACE_REFS`` macro, +which introduces the only ABI incompatibility. The ``Py_TRACE_REFS`` macro, +which adds the :func:`sys.getobjects` function and the :envvar:`PYTHONDUMPREFS` environment variable, can be set using the new :option:`./configure --with-trace-refs <--with-trace-refs>` build option. (Contributed by Victor Stinner in :issue:`36465`.) From 9e5b8383724211d14165a32c0e7682e56e13843a Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:23:25 +0300 Subject: [PATCH 365/775] gh-146488: hash-pin check-html-ids action references (#147968) --- .github/workflows/reusable-check-html-ids.yml | 8 ++++---- .github/workflows/reusable-docs.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/reusable-check-html-ids.yml b/.github/workflows/reusable-check-html-ids.yml index 47a2e25de36..4a1d321a8ce 100644 --- a/.github/workflows/reusable-check-html-ids.yml +++ b/.github/workflows/reusable-check-html-ids.yml @@ -16,12 +16,12 @@ jobs: timeout-minutes: 30 steps: - name: 'Check out base commit' - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false ref: ${{ github.event.pull_request.base.sha }} - name: 'Set up Python' - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: '3' cache: 'pip' @@ -31,7 +31,7 @@ jobs: - name: 'Build HTML documentation' run: make -C Doc/ SPHINXOPTS="--quiet" html - name: 'Check out PR head tools' - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false sparse-checkout: | @@ -46,7 +46,7 @@ jobs: - name: 'Collect HTML IDs' run: python Doc/tools/check-html-ids.py collect Doc/build/html -o /tmp/html-ids-base.json.gz - name: 'Download PR head HTML IDs' - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: html-ids-head.json.gz path: /tmp diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml index 5227c04c06f..0453b6ab555 100644 --- a/.github/workflows/reusable-docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -80,7 +80,7 @@ jobs: run: python Doc/tools/check-html-ids.py collect Doc/build/html -o Doc/build/html-ids-head.json.gz - name: 'Upload HTML IDs' if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: html-ids-head path: Doc/build/html-ids-head.json.gz From 255026d9eea81719214c8e807d23df55b5f39b54 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 1 Apr 2026 17:15:13 +0100 Subject: [PATCH 366/775] GH-126910: Make `_Py_get_machine_stack_pointer` return the stack pointer (#147945) * Make _Py_get_machine_stack_pointer return the stack pointer (or close to it), not the frame pointer * Make ``_Py_ReachedRecursionLimit`` inline again * Remove ``_Py_MakeRecCheck`` relacing its use with ``_Py_ReachedRecursionLimit`` * Move stack swtiching check into ``_Py_CheckRecursiveCall`` --- Include/internal/pycore_ceval.h | 16 +++++------ Include/internal/pycore_pystate.h | 22 +++++++-------- Include/internal/pycore_pythonrun.h | 3 ++- Include/pyport.h | 5 ++++ Lib/test/test_pyexpat.py | 2 +- Python/ceval.c | 42 +++++++---------------------- Python/jit.c | 2 +- 7 files changed, 37 insertions(+), 55 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 9fd3be74404..c86cd58e295 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -211,16 +211,16 @@ extern void _PyEval_DeactivateOpCache(void); /* --- _Py_EnterRecursiveCall() ----------------------------------------- */ -static inline int _Py_MakeRecCheck(PyThreadState *tstate) { +static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate) { uintptr_t here_addr = _Py_get_machine_stack_pointer(); _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - // Overflow if stack pointer is between soft limit and the base of the hardware stack. - // If it is below the hardware stack base, assume that we have the wrong stack limits, and do nothing. - // We could have the wrong stack limits because of limited platform support, or user-space threads. + // Possible overflow if stack pointer is beyond the soft limit. + // _Py_CheckRecursiveCall will check for corner cases and + // report an error if there is an overflow. #if _Py_STACK_GROWS_DOWN - return here_addr < _tstate->c_stack_soft_limit && here_addr >= _tstate->c_stack_soft_limit - 2 * _PyOS_STACK_MARGIN_BYTES; + return here_addr < _tstate->c_stack_soft_limit; #else - return here_addr > _tstate->c_stack_soft_limit && here_addr <= _tstate->c_stack_soft_limit + 2 * _PyOS_STACK_MARGIN_BYTES; + return here_addr > _tstate->c_stack_soft_limit; #endif } @@ -235,7 +235,7 @@ PyAPI_FUNC(int) _Py_CheckRecursiveCallPy( static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate, const char *where) { - return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where)); + return (_Py_ReachedRecursionLimit(tstate) && _Py_CheckRecursiveCall(tstate, where)); } static inline int _Py_EnterRecursiveCall(const char *where) { @@ -249,8 +249,6 @@ static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) { PyAPI_FUNC(void) _Py_InitializeRecursionLimits(PyThreadState *tstate); -PyAPI_FUNC(int) _Py_ReachedRecursionLimit(PyThreadState *tstate); - // Export for test_peg_generator PyAPI_FUNC(int) _Py_ReachedRecursionLimitWithMargin( PyThreadState *tstate, diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 189a8dde9f0..054360d69e6 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -306,23 +306,23 @@ _Py_AssertHoldsTstateFunc(const char *func) #define _Py_AssertHoldsTstate() #endif -#if !_Py__has_builtin(__builtin_frame_address) && !defined(__GNUC__) && !defined(_MSC_VER) -static uintptr_t return_pointer_as_int(char* p) { - return (uintptr_t)p; -} -#endif static inline uintptr_t _Py_get_machine_stack_pointer(void) { -#if _Py__has_builtin(__builtin_frame_address) || defined(__GNUC__) - return (uintptr_t)__builtin_frame_address(0); -#elif defined(_MSC_VER) - return (uintptr_t)_AddressOfReturnAddress(); + uintptr_t result; +#if !defined(_MSC_VER) && defined(_M_ARM64) + result = __getReg(31); +#elif defined(_MSC_VER) && defined(_M_X64) + result = (uintptr_t)_AddressOfReturnAddress(); +#elif defined(__aarch64__) + __asm__ ("mov %0, sp" : "=r" (result)); +#elif defined(__x86_64__) + __asm__("{movq %%rsp, %0" : "=r" (result)); #else char here; - /* Avoid compiler warning about returning stack address */ - return return_pointer_as_int(&here); + result = (uintptr_t)&here; #endif + return result; } static inline intptr_t diff --git a/Include/internal/pycore_pythonrun.h b/Include/internal/pycore_pythonrun.h index 2a544edc431..66dd7cd843b 100644 --- a/Include/internal/pycore_pythonrun.h +++ b/Include/internal/pycore_pythonrun.h @@ -46,7 +46,8 @@ extern PyObject * _Py_CompileStringObjectWithModule( * stack consumption of PyEval_EvalDefault */ #if (defined(Py_DEBUG) \ || defined(_Py_ADDRESS_SANITIZER) \ - || defined(_Py_THREAD_SANITIZER)) + || defined(_Py_THREAD_SANITIZER)) \ + || defined(_Py_UNDEFINED_BEHAVIOR_SANITIZER) # define _PyOS_LOG2_STACK_MARGIN 12 #else # define _PyOS_LOG2_STACK_MARGIN 11 diff --git a/Include/pyport.h b/Include/pyport.h index f7bb5d513b9..ee90711c202 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -598,6 +598,11 @@ extern "C" { # define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) # endif # endif +# if __has_feature(undefined_behavior_sanitizer) +# if !defined(_Py_UNDEFINED_BEHAVIOR_SANITIZER) +# define _Py_UNDEFINED_BEHAVIOR_SANITIZER +# endif +# endif #elif defined(__GNUC__) # if defined(__SANITIZE_ADDRESS__) # define _Py_ADDRESS_SANITIZER diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index cace780f79f..0361d9f3da9 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -707,7 +707,7 @@ def test_trigger_leak(self): def test_deeply_nested_content_model(self): # This should raise a RecursionError and not crash. # See https://github.com/python/cpython/issues/145986. - N = 500_000 + N = 800_000 data = ( b'c_stack_hard_limit) { -#else - if (here_addr > _tstate->c_stack_hard_limit) { -#endif - Py_FatalError("Unchecked stack overflow."); - } -} - #if defined(__s390x__) # define Py_C_STACK_SIZE 320000 #elif defined(_WIN32) @@ -278,7 +264,7 @@ PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate) /* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall() - if the stack pointer is between the stack base and c_stack_hard_limit. */ + if the stack pointer is beyond c_stack_soft_limit. */ int _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) { @@ -287,16 +273,21 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) assert(_tstate->c_stack_soft_limit != 0); assert(_tstate->c_stack_hard_limit != 0); #if _Py_STACK_GROWS_DOWN - assert(here_addr >= _tstate->c_stack_hard_limit - _PyOS_STACK_MARGIN_BYTES); if (here_addr < _tstate->c_stack_hard_limit) { - /* Overflowing while handling an overflow. Give up. */ + if (here_addr < _tstate->c_stack_hard_limit - _PyOS_STACK_MARGIN_BYTES) { + // Far out of bounds -- Assume stack switching has occurred + return 0; + } int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024; #else - assert(here_addr <= _tstate->c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES); if (here_addr > _tstate->c_stack_hard_limit) { - /* Overflowing while handling an overflow. Give up. */ + if (here_addr > _tstate->c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES) { + // Far out of bounds -- Assume stack switching has occurred + return 0; + } int kbytes_used = (int)(here_addr - _tstate->c_stack_top)/1024; #endif + /* Too much stack used to safely raise an exception. Give up. */ char buffer[80]; snprintf(buffer, 80, "Unrecoverable stack overflow (used %d kB)%s", kbytes_used, where); Py_FatalError(buffer); @@ -1201,19 +1192,6 @@ _PyEval_GetIter(_PyStackRef iterable, _PyStackRef *index_or_null, int yield_from return PyStackRef_FromPyObjectSteal(iter_o); } -Py_NO_INLINE int -_Py_ReachedRecursionLimit(PyThreadState *tstate) { - uintptr_t here_addr = _Py_get_machine_stack_pointer(); - _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - assert(_tstate->c_stack_hard_limit != 0); -#if _Py_STACK_GROWS_DOWN - return here_addr <= _tstate->c_stack_soft_limit; -#else - return here_addr >= _tstate->c_stack_soft_limit; -#endif -} - - #if (defined(__GNUC__) && __GNUC__ >= 10 && !defined(__clang__)) && defined(__x86_64__) /* * gh-129987: The SLP autovectorizer can cause poor code generation for diff --git a/Python/jit.c b/Python/jit.c index 4990c743224..d3a40ee6ff6 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -734,7 +734,7 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], siz return 0; } -/* One-off compilation of the jit entry shim +/* One-off compilation of the jit entry shim. * We compile this once only as it effectively a normal * function, but we need to use the JIT because it needs * to understand the jit-specific calling convention. From 021ee7fd6a09971fbef5cf0e194b8087ae88677d Mon Sep 17 00:00:00 2001 From: Peter Sutton Date: Wed, 1 Apr 2026 17:16:36 +0100 Subject: [PATCH 367/775] Docs: Use !r in __repr__ example (gh-146273) --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 483e5b1d8fd..e8c4605d057 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1754,7 +1754,7 @@ are always available. They are listed here in alphabetical order. self.age = age def __repr__(self): - return f"Person('{self.name}', {self.age})" + return f"Person({self.name!r}, {self.age!r})" .. function:: reversed(object, /) From 4810beddbfc71fd8743bc89c5d07edef8877d754 Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Thu, 2 Apr 2026 00:34:55 +0800 Subject: [PATCH 368/775] gh-147960: Fix memory leak in crossinterp _tuple_shared() on alloc failure (#147961) --- Python/crossinterp_data_lookup.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index cf84633e10e..54422ad2335 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -657,6 +657,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, xidata_fallback_t fallback, shared->items = (_PyXIData_t **) PyMem_Calloc(shared->len, sizeof(_PyXIData_t *)); if (shared->items == NULL) { PyErr_NoMemory(); + PyMem_RawFree(shared); return -1; } From b456cb25a98985bdbce6987a37f01da4e2ed478e Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 2 Apr 2026 00:42:10 +0300 Subject: [PATCH 369/775] gh-143050: Add helper _PyLong_InitTag() (#147956) With this we can assume, that _PyLong_SetSignAndDigitCount() and _PyLong_SetDigitCount() operate on non-immortal integers. Co-authored-by: Victor Stinner --- Include/internal/pycore_long.h | 21 ++++++++++++++++----- Objects/longobject.c | 26 +++++++++++++++++--------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 5ef9cc410e4..fb5622c99f7 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -238,11 +238,12 @@ _PyLong_IsSmallInt(const PyLongObject *op) { assert(PyLong_Check(op)); bool is_small_int = (op->long_value.lv_tag & IMMORTALITY_BIT_MASK) != 0; - assert(PyLong_CheckExact(op) || (!is_small_int)); - assert(_Py_IsImmortal(op) || (!is_small_int)); - assert((_PyLong_IsCompact(op) - && _PY_IS_SMALL_INT(_PyLong_CompactValue(op))) - || (!is_small_int)); + if (is_small_int) { + assert(PyLong_CheckExact(op)); + assert(_Py_IsImmortal(op)); + assert((_PyLong_IsCompact(op) + && _PY_IS_SMALL_INT(_PyLong_CompactValue(op)))); + } return is_small_int; } @@ -285,6 +286,14 @@ _PyLong_SameSign(const PyLongObject *a, const PyLongObject *b) return (a->long_value.lv_tag & SIGN_MASK) == (b->long_value.lv_tag & SIGN_MASK); } +/* Initialize the tag of a freshly-allocated int. */ +static inline void +_PyLong_InitTag(PyLongObject *op) +{ + assert(PyLong_Check(op)); + op->long_value.lv_tag = SIGN_ZERO; /* non-immortal zero */ +} + #define TAG_FROM_SIGN_AND_SIZE(sign, size) \ ((uintptr_t)(1 - (sign)) | ((uintptr_t)(size) << NON_SIZE_BITS)) @@ -294,6 +303,7 @@ _PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size) assert(size >= 0); assert(-1 <= sign && sign <= 1); assert(sign != 0 || size == 0); + assert(!_PyLong_IsSmallInt(op)); op->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(sign, size); } @@ -301,6 +311,7 @@ static inline void _PyLong_SetDigitCount(PyLongObject *op, Py_ssize_t size) { assert(size >= 0); + assert(!_PyLong_IsSmallInt(op)); op->long_value.lv_tag = (((size_t)size) << NON_SIZE_BITS) | (op->long_value.lv_tag & SIGN_MASK); } diff --git a/Objects/longobject.c b/Objects/longobject.c index d416fc1747e..fde01ff302d 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -185,6 +185,7 @@ long_alloc(Py_ssize_t size) return NULL; } _PyObject_Init((PyObject*)result, &PyLong_Type); + _PyLong_InitTag(result); } _PyLong_SetSignAndDigitCount(result, size != 0, size); /* The digit has to be initialized explicitly to avoid @@ -258,6 +259,7 @@ _PyLong_FromMedium(sdigit x) return NULL; } _PyObject_Init((PyObject*)v, &PyLong_Type); + _PyLong_InitTag(v); } digit abs_x = x < 0 ? -x : x; _PyLong_SetSignAndDigitCount(v, x<0?-1:1, 1); @@ -337,6 +339,7 @@ medium_from_stwodigits(stwodigits x) return PyStackRef_NULL; } _PyObject_Init((PyObject*)v, &PyLong_Type); + _PyLong_InitTag(v); } digit abs_x = x < 0 ? (digit)(-x) : (digit)x; _PyLong_SetSignAndDigitCount(v, x<0?-1:1, 1); @@ -6011,29 +6014,34 @@ static PyObject * long_subtype_new(PyTypeObject *type, PyObject *x, PyObject *obase) { PyLongObject *tmp, *newobj; - Py_ssize_t i, n; + Py_ssize_t size, ndigits; + int sign; assert(PyType_IsSubtype(type, &PyLong_Type)); tmp = (PyLongObject *)long_new_impl(&PyLong_Type, x, obase); if (tmp == NULL) return NULL; assert(PyLong_Check(tmp)); - n = _PyLong_DigitCount(tmp); + size = _PyLong_DigitCount(tmp); /* Fast operations for single digit integers (including zero) * assume that there is always at least one digit present. */ - if (n == 0) { - n = 1; - } - newobj = (PyLongObject *)type->tp_alloc(type, n); + ndigits = size ? size : 1; + newobj = (PyLongObject *)type->tp_alloc(type, ndigits); if (newobj == NULL) { Py_DECREF(tmp); return NULL; } assert(PyLong_Check(newobj)); - newobj->long_value.lv_tag = tmp->long_value.lv_tag & ~IMMORTALITY_BIT_MASK; - for (i = 0; i < n; i++) { - newobj->long_value.ob_digit[i] = tmp->long_value.ob_digit[i]; + if (_PyLong_IsCompact(tmp)) { + sign = _PyLong_CompactSign(tmp); } + else { + sign = _PyLong_NonCompactSign(tmp); + } + _PyLong_InitTag(newobj); + _PyLong_SetSignAndDigitCount(newobj, sign, size); + memcpy(newobj->long_value.ob_digit, tmp->long_value.ob_digit, + ndigits * sizeof(digit)); Py_DECREF(tmp); return (PyObject *)newobj; } From c32e264227b1fee3a6436c18b19dad88317e5aa3 Mon Sep 17 00:00:00 2001 From: Locked-chess-official <13140752715@163.com> Date: Thu, 2 Apr 2026 06:54:06 +0800 Subject: [PATCH 370/775] gh-146656: properly raise `NotImplementedError` instead of `NotImplemented` in `test_discover` (#146661) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: AN Long Co-authored-by: Victor Stinner Co-authored-by: Filipe Laíns --- Lib/test/test_importlib/test_discover.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_importlib/test_discover.py b/Lib/test/test_importlib/test_discover.py index 8c5fa65a564..c4ab7b6982e 100644 --- a/Lib/test/test_importlib/test_discover.py +++ b/Lib/test/test_importlib/test_discover.py @@ -11,7 +11,7 @@ def __init__(self, discover=[]): self._discovered_values = discover def find_spec(self, fullname, path=None, target=None): - raise NotImplemented + raise NotImplementedError def discover(self, parent=None): yield from self._discovered_values From 7817651b21f4cc84541df02542292c2e20c762c8 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 2 Apr 2026 11:46:20 +0800 Subject: [PATCH 371/775] gh-146444: Remove legacy iOS folder (#147993) Remove legacy iOS folder. --- iOS/Resources/bin/arm64-apple-ios-ar | 2 -- iOS/Resources/bin/arm64-apple-ios-clang | 2 -- iOS/Resources/bin/arm64-apple-ios-clang++ | 2 -- iOS/Resources/bin/arm64-apple-ios-cpp | 2 -- iOS/Resources/bin/arm64-apple-ios-simulator-ar | 2 -- iOS/Resources/bin/arm64-apple-ios-simulator-clang | 2 -- iOS/Resources/bin/arm64-apple-ios-simulator-clang++ | 2 -- iOS/Resources/bin/arm64-apple-ios-simulator-cpp | 2 -- iOS/Resources/bin/arm64-apple-ios-simulator-strip | 2 -- iOS/Resources/bin/arm64-apple-ios-strip | 2 -- iOS/Resources/bin/x86_64-apple-ios-simulator-ar | 2 -- iOS/Resources/bin/x86_64-apple-ios-simulator-clang | 2 -- iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ | 2 -- iOS/Resources/bin/x86_64-apple-ios-simulator-cpp | 2 -- iOS/Resources/bin/x86_64-apple-ios-simulator-strip | 2 -- 15 files changed, 30 deletions(-) delete mode 100755 iOS/Resources/bin/arm64-apple-ios-ar delete mode 100755 iOS/Resources/bin/arm64-apple-ios-clang delete mode 100755 iOS/Resources/bin/arm64-apple-ios-clang++ delete mode 100755 iOS/Resources/bin/arm64-apple-ios-cpp delete mode 100755 iOS/Resources/bin/arm64-apple-ios-simulator-ar delete mode 100755 iOS/Resources/bin/arm64-apple-ios-simulator-clang delete mode 100755 iOS/Resources/bin/arm64-apple-ios-simulator-clang++ delete mode 100755 iOS/Resources/bin/arm64-apple-ios-simulator-cpp delete mode 100755 iOS/Resources/bin/arm64-apple-ios-simulator-strip delete mode 100755 iOS/Resources/bin/arm64-apple-ios-strip delete mode 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-ar delete mode 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-clang delete mode 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ delete mode 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-cpp delete mode 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-strip diff --git a/iOS/Resources/bin/arm64-apple-ios-ar b/iOS/Resources/bin/arm64-apple-ios-ar deleted file mode 100755 index 3cf3eb21874..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-ar +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphoneos${IOS_SDK_VERSION} ar "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-clang b/iOS/Resources/bin/arm64-apple-ios-clang deleted file mode 100755 index f50d5b5142f..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-clang +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-clang++ b/iOS/Resources/bin/arm64-apple-ios-clang++ deleted file mode 100755 index 0794731d7dc..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-clang++ +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphoneos${IOS_SDK_VERSION} clang++ -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-cpp b/iOS/Resources/bin/arm64-apple-ios-cpp deleted file mode 100755 index 24fa1506bab..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-cpp +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphoneos${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET} -E "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-ar b/iOS/Resources/bin/arm64-apple-ios-simulator-ar deleted file mode 100755 index b836b6db902..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-simulator-ar +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang b/iOS/Resources/bin/arm64-apple-ios-simulator-clang deleted file mode 100755 index 4891a00876e..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-simulator-clang +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ deleted file mode 100755 index 58b2a5f6f18..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-cpp b/iOS/Resources/bin/arm64-apple-ios-simulator-cpp deleted file mode 100755 index c9df94e8b7c..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-simulator-cpp +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target arm64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator -E "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-strip b/iOS/Resources/bin/arm64-apple-ios-simulator-strip deleted file mode 100755 index fd59d309b73..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-simulator-strip +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} strip -arch arm64 "$@" diff --git a/iOS/Resources/bin/arm64-apple-ios-strip b/iOS/Resources/bin/arm64-apple-ios-strip deleted file mode 100755 index 75e823a3d02..00000000000 --- a/iOS/Resources/bin/arm64-apple-ios-strip +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphoneos${IOS_SDK_VERSION} strip -arch arm64 "$@" diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-ar b/iOS/Resources/bin/x86_64-apple-ios-simulator-ar deleted file mode 100755 index b836b6db902..00000000000 --- a/iOS/Resources/bin/x86_64-apple-ios-simulator-ar +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} ar "$@" diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang deleted file mode 100755 index f4739a7b945..00000000000 --- a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ deleted file mode 100755 index c348ae4c103..00000000000 --- a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang++ -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator "$@" diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp b/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp deleted file mode 100755 index 6d7f8084c9f..00000000000 --- a/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} clang -target x86_64-apple-ios${IPHONEOS_DEPLOYMENT_TARGET}-simulator -E "$@" diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-strip b/iOS/Resources/bin/x86_64-apple-ios-simulator-strip deleted file mode 100755 index c5cfb289291..00000000000 --- a/iOS/Resources/bin/x86_64-apple-ios-simulator-strip +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -xcrun --sdk iphonesimulator${IOS_SDK_VERSION} strip -arch x86_64 "$@" From 97babb8ef70c1c25768a0e534cfb10955c6b290d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 Apr 2026 13:45:59 +0200 Subject: [PATCH 372/775] gh-143394: Skip pyrepl test_no_newline() basic REPL if readline is missing (#147973) --- Lib/test/test_pyrepl/test_pyrepl.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 082215da0a3..8854b19efce 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -44,6 +44,10 @@ import pty except ImportError: pty = None +try: + import readline as readline_module +except ImportError: + readline_module = None class ReplTestCase(TestCase): @@ -1947,9 +1951,12 @@ def test_no_newline(self): commands = "print('Something pretty long', end='')\nexit()\n" expected_output_sequence = "Something pretty long>>> exit()" - basic_output, basic_exit_code = self.run_repl(commands, env=env) - self.assertEqual(basic_exit_code, 0) - self.assertIn(expected_output_sequence, basic_output) + # gh-143394: The basic REPL needs the readline module to turn off + # ECHO terminal attribute. + if readline_module is not None: + basic_output, basic_exit_code = self.run_repl(commands, env=env) + self.assertEqual(basic_exit_code, 0) + self.assertIn(expected_output_sequence, basic_output) output, exit_code = self.run_repl(commands) self.assertEqual(exit_code, 0) From a86963b3e2afa854132968f0d4bffe2ed2c87fe0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 2 Apr 2026 13:54:21 +0200 Subject: [PATCH 373/775] gh-146636: Py_mod_abi mandatory for modules created from slots array (GH-146855) --- Doc/c-api/module.rst | 7 +- Doc/extending/first-extension-module.rst | 7 ++ Doc/includes/capi-extension/spammodule-01.c | 3 + Lib/test/test_capi/test_module.py | 18 ++++- Lib/test/test_cext/extension.c | 2 + Lib/test/test_import/__init__.py | 18 +++-- ...-03-31-13-33-41.gh-issue-146636.5do3wt.rst | 3 + Modules/_testcapi/module.c | 65 +++++++++++++++++++ Modules/_testmultiphase.c | 27 ++++++-- Objects/moduleobject.c | 10 +++ Python/modsupport.c | 12 ++-- 11 files changed, 153 insertions(+), 19 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 39293b0fa22..8b967c285ac 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -230,6 +230,9 @@ Feature slots When creating a module, Python checks the value of this slot using :c:func:`PyABIInfo_Check`. + This slot is required, except for modules created from + :c:struct:`PyModuleDef`. + .. versionadded:: 3.15 .. c:macro:: Py_mod_multiple_interpreters @@ -620,9 +623,9 @@ rather than from an extension's :ref:`export hook `. and the :py:class:`~importlib.machinery.ModuleSpec` *spec*. The *slots* argument must point to an array of :c:type:`PyModuleDef_Slot` - structures, terminated by an entry slot with slot ID of 0 + structures, terminated by an entry with slot ID of 0 (typically written as ``{0}`` or ``{0, NULL}`` in C). - The *slots* argument may not be ``NULL``. + The array must include a :c:data:`Py_mod_abi` entry. The *spec* argument may be any ``ModuleSpec``-like object, as described in :c:macro:`Py_mod_create` documentation. diff --git a/Doc/extending/first-extension-module.rst b/Doc/extending/first-extension-module.rst index f1ba0a3ceb7..cd755a98f7f 100644 --- a/Doc/extending/first-extension-module.rst +++ b/Doc/extending/first-extension-module.rst @@ -265,12 +265,19 @@ Define this array just before your export hook: .. code-block:: c + PyABIInfo_VAR(abi_info); + static PyModuleDef_Slot spam_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "spam"}, {Py_mod_doc, "A wonderful module with an example function"}, {0, NULL} }; +The ``PyABIInfo_VAR(abi_info);`` macro and the :c:data:`Py_mod_abi` slot +are a bit of boilerplate that helps prevent extensions compiled for +a different version of Python from crashing the interpreter. + For both :c:data:`Py_mod_name` and :c:data:`Py_mod_doc`, the values are C strings -- that is, NUL-terminated, UTF-8 encoded byte arrays. diff --git a/Doc/includes/capi-extension/spammodule-01.c b/Doc/includes/capi-extension/spammodule-01.c index ac96f17f047..0bc34ef5744 100644 --- a/Doc/includes/capi-extension/spammodule-01.c +++ b/Doc/includes/capi-extension/spammodule-01.c @@ -35,7 +35,10 @@ static PyMethodDef spam_methods[] = { /// Module slot table +PyABIInfo_VAR(abi_info); + static PyModuleDef_Slot spam_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "spam"}, {Py_mod_doc, "A wonderful module with an example function"}, {Py_mod_methods, spam_methods}, diff --git a/Lib/test/test_capi/test_module.py b/Lib/test/test_capi/test_module.py index 053e6709cda..c32ca1098ed 100644 --- a/Lib/test/test_capi/test_module.py +++ b/Lib/test/test_capi/test_module.py @@ -25,9 +25,13 @@ def def_and_token(mod): ) class TestModFromSlotsAndSpec(unittest.TestCase): - @requires_gil_enabled("empty slots re-enable GIL") def test_empty(self): - mod = _testcapi.module_from_slots_empty(FakeSpec()) + with self.assertRaises(SystemError): + _testcapi.module_from_slots_empty(FakeSpec()) + + @requires_gil_enabled("minimal slots re-enable GIL") + def test_minimal(self): + mod = _testcapi.module_from_slots_minimal(FakeSpec()) self.assertIsInstance(mod, types.ModuleType) self.assertEqual(def_and_token(mod), (0, 0)) self.assertEqual(mod.__name__, 'testmod') @@ -159,6 +163,16 @@ def test_null_def_slot(self): self.assertIn(name, str(cm.exception)) self.assertIn("NULL", str(cm.exception)) + def test_bad_abiinfo(self): + """Slots that incompatible ABI is rejected""" + with self.assertRaises(ImportError) as cm: + _testcapi.module_from_bad_abiinfo(FakeSpec()) + + def test_multiple_abiinfo(self): + """Slots that Py_mod_abiinfo can be repeated""" + mod = _testcapi.module_from_multiple_abiinfo(FakeSpec()) + self.assertEqual(mod.__name__, 'testmod') + def test_def_multiple_exec(self): """PyModule_Exec runs all exec slots of PyModuleDef-defined module""" mod = _testcapi.module_from_def_multiple_exec(FakeSpec()) diff --git a/Lib/test/test_cext/extension.c b/Lib/test/test_cext/extension.c index 7555b78f18c..a880cb82811 100644 --- a/Lib/test/test_cext/extension.c +++ b/Lib/test/test_cext/extension.c @@ -119,8 +119,10 @@ _Py_COMP_DIAG_PUSH #endif PyDoc_STRVAR(_testcext_doc, "C test extension."); +PyABIInfo_VAR(abi_info); static PyModuleDef_Slot _testcext_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, STR(MODULE_NAME)}, {Py_mod_doc, (void*)(char*)_testcext_doc}, {Py_mod_exec, (void*)_testcext_exec}, diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 437ab703135..c905c0da0a1 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -3499,13 +3499,21 @@ class Sub(tp): pass self.assertEqual(_testcapi.pytype_getmodulebytoken(Sub, token), module) - @requires_gil_enabled("empty slots re-enable GIL") def test_from_modexport_empty_slots(self): - # Module to test that: - # - no slots are mandatory for PyModExport - # - the slots array is used as the default token + # Module to test that Py_mod_abi is mandatory for PyModExport modname = '_test_from_modexport_empty_slots' filename = _testmultiphase.__file__ + with self.assertRaises(SystemError): + import_extension_from_file( + modname, filename, put_in_sys_modules=False) + + @requires_gil_enabled("this module re-enables GIL") + def test_from_modexport_minimal_slots(self): + # Module to test that: + # - no slots except Py_mod_abi is mandatory for PyModExport + # - the slots array is used as the default token + modname = '_test_from_modexport_minimal_slots' + filename = _testmultiphase.__file__ module = import_extension_from_file( modname, filename, put_in_sys_modules=False) @@ -3516,7 +3524,7 @@ def test_from_modexport_empty_slots(self): smoke_mod = import_extension_from_file( '_test_from_modexport_smoke', filename, put_in_sys_modules=False) self.assertEqual(_testcapi.pymodule_get_token(module), - smoke_mod.get_modexport_empty_slots()) + smoke_mod.get_modexport_minimal_slots()) @cpython_only class TestMagicNumber(unittest.TestCase): diff --git a/Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst b/Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst new file mode 100644 index 00000000000..8f8b832b8ba --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst @@ -0,0 +1,3 @@ +The :c:data:`Py_mod_abi` slot is now mandatory for modules created from a +slots array (using :c:func:`PyModule_FromSlotsAndSpec` or the +:c:func:`PyModExport_* ` export hook). diff --git a/Modules/_testcapi/module.c b/Modules/_testcapi/module.c index 3411b21e942..52e1d6d94a3 100644 --- a/Modules/_testcapi/module.c +++ b/Modules/_testcapi/module.c @@ -8,6 +8,8 @@ * Lib/test/test_capi/test_module.py */ +PyABIInfo_VAR(abi_info); + static PyObject * module_from_slots_empty(PyObject *self, PyObject *spec) { @@ -17,6 +19,16 @@ module_from_slots_empty(PyObject *self, PyObject *spec) return PyModule_FromSlotsAndSpec(slots, spec); } +static PyObject * +module_from_slots_minimal(PyObject *self, PyObject *spec) +{ + PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, + {0}, + }; + return PyModule_FromSlotsAndSpec(slots, spec); +} + static PyObject * module_from_slots_null(PyObject *self, PyObject *spec) { @@ -27,6 +39,7 @@ static PyObject * module_from_slots_name(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "currently ignored..."}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -39,6 +52,7 @@ static PyObject * module_from_slots_doc(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_doc, "the docstring"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -51,6 +65,7 @@ static PyObject * module_from_slots_size(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_state_size, (void*)123}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -78,6 +93,7 @@ static PyObject * module_from_slots_methods(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_methods, a_methoddef_array}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -96,6 +112,7 @@ static PyObject * module_from_slots_gc(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_state_traverse, noop_traverse}, {Py_mod_state_clear, noop_clear}, {Py_mod_state_free, noop_free}, @@ -128,6 +145,7 @@ static PyObject * module_from_slots_token(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_token, (void*)&test_token}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -156,6 +174,7 @@ static PyObject * module_from_slots_exec(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_exec, simple_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -189,6 +208,7 @@ static PyObject * module_from_slots_create(PyObject *self, PyObject *spec) { PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_create, create_attr_from_spec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -220,6 +240,7 @@ module_from_slots_repeat_slot(PyObject *self, PyObject *spec) return NULL; } PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {slot_id, "anything"}, {slot_id, "anything else"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -238,6 +259,7 @@ module_from_slots_null_slot(PyObject *self, PyObject *spec) } PyModuleDef_Slot slots[] = { {slot_id, NULL}, + {Py_mod_abi, &abi_info}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0}, @@ -254,6 +276,7 @@ module_from_def_slot(PyObject *self, PyObject *spec) } PyModuleDef_Slot slots[] = { {slot_id, "anything"}, + {Py_mod_abi, &abi_info}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0}, @@ -285,6 +308,7 @@ static PyModuleDef parrot_def = { .m_slots = NULL /* set below */, }; static PyModuleDef_Slot parrot_slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, (void*)parrot_name}, {Py_mod_doc, (void*)parrot_doc}, {Py_mod_state_size, (void*)123}, @@ -314,6 +338,43 @@ module_from_def_slot_parrot(PyObject *self, PyObject *spec) return module; } +static PyObject * +module_from_bad_abiinfo(PyObject *self, PyObject *spec) +{ + PyABIInfo bad_abi_info = { + 1, 0, + .abi_version=0x02080000, + }; + PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, + {Py_mod_abi, &bad_abi_info}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0}, + }; + return PyModule_FromSlotsAndSpec(slots, spec); +} + +static PyObject * +module_from_multiple_abiinfo(PyObject *self, PyObject *spec) +{ + PyABIInfo extra_abi_info = { + 1, 0, + .flags=PyABIInfo_STABLE | PyABIInfo_FREETHREADING_AGNOSTIC, + .abi_version=0x03040000, + }; + PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, + {Py_mod_abi, &abi_info}, + {Py_mod_abi, &extra_abi_info}, + {Py_mod_abi, &extra_abi_info}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0}, + }; + return PyModule_FromSlotsAndSpec(slots, spec); +} + static int another_exec(PyObject *module) { @@ -344,6 +405,7 @@ static PyObject * module_from_def_multiple_exec(PyObject *self, PyObject *spec) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_exec, simple_exec}, {Py_mod_exec, another_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -399,6 +461,7 @@ pymodule_get_state_size(PyObject *self, PyObject *module) static PyMethodDef test_methods[] = { {"module_from_slots_empty", module_from_slots_empty, METH_O}, + {"module_from_slots_minimal", module_from_slots_minimal, METH_O}, {"module_from_slots_null", module_from_slots_null, METH_O}, {"module_from_slots_name", module_from_slots_name, METH_O}, {"module_from_slots_doc", module_from_slots_doc, METH_O}, @@ -413,6 +476,8 @@ static PyMethodDef test_methods[] = { {"module_from_def_multiple_exec", module_from_def_multiple_exec, METH_O}, {"module_from_def_slot", module_from_def_slot, METH_O}, {"module_from_def_slot_parrot", module_from_def_slot_parrot, METH_O}, + {"module_from_bad_abiinfo", module_from_bad_abiinfo, METH_O}, + {"module_from_multiple_abiinfo", module_from_multiple_abiinfo, METH_O}, {"pymodule_get_token", pymodule_get_token, METH_O}, {"pymodule_get_def", pymodule_get_def, METH_O}, {"pymodule_get_state_size", pymodule_get_state_size, METH_O}, diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index 4921dc90713..54f53c899f5 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -1034,10 +1034,13 @@ PyInit__test_no_multiple_interpreter_slot(void) /* PyModExport_* hooks */ +PyABIInfo_VAR(abi_info); + PyMODEXPORT_FUNC PyModExport__test_from_modexport(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, @@ -1050,6 +1053,7 @@ PyMODEXPORT_FUNC PyModExport__test_from_modexport_gil_used(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_gil_used"}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_USED}, @@ -1100,6 +1104,7 @@ PyMODEXPORT_FUNC PyModExport__test_from_modexport_create_nonmodule(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_create_nonmodule"}, {Py_mod_create, modexport_create_string}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -1113,6 +1118,7 @@ PyMODEXPORT_FUNC PyModExport__test_from_modexport_create_nonmodule_gil_used(void) { static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_create_nonmodule"}, {Py_mod_create, modexport_create_string}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, @@ -1132,6 +1138,18 @@ PyModExport__test_from_modexport_empty_slots(void) return modexport_empty_slots; } + +static PyModuleDef_Slot modexport_minimal_slots[] = { + {Py_mod_abi, &abi_info}, + {0}, +}; + +PyMODEXPORT_FUNC +PyModExport__test_from_modexport_minimal_slots(void) +{ + return modexport_minimal_slots; +} + static int modexport_smoke_exec(PyObject *mod) { @@ -1172,13 +1190,13 @@ modexport_smoke_get_test_token(PyObject *mod, PyObject *arg) } static PyObject * -modexport_get_empty_slots(PyObject *mod, PyObject *arg) +modexport_get_minimal_slots(PyObject *mod, PyObject *arg) { /* Get the address of modexport_empty_slots. - * This method would be in the `_test_from_modexport_empty_slots` module, + * This method would be in the `_test_from_modexport_minimal_slots` module, * if it had a methods slot. */ - return PyLong_FromVoidPtr(&modexport_empty_slots); + return PyLong_FromVoidPtr(&modexport_minimal_slots); } static void @@ -1198,10 +1216,11 @@ PyModExport__test_from_modexport_smoke(void) static PyMethodDef methods[] = { {"get_state_int", modexport_smoke_get_state_int, METH_NOARGS}, {"get_test_token", modexport_smoke_get_test_token, METH_NOARGS}, - {"get_modexport_empty_slots", modexport_get_empty_slots, METH_NOARGS}, + {"get_modexport_minimal_slots", modexport_get_minimal_slots, METH_NOARGS}, {0}, }; static PyModuleDef_Slot slots[] = { + {Py_mod_abi, &abi_info}, {Py_mod_name, "_test_from_modexport_smoke"}, {Py_mod_doc, "the expected docstring"}, {Py_mod_exec, modexport_smoke_exec}, diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index e3868097c0b..8339e6b91a5 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -446,6 +446,7 @@ module_from_def_and_spec( bool seen_m_traverse_slot = false; bool seen_m_clear_slot = false; bool seen_m_free_slot = false; + bool seen_m_abi_slot = false; for (cur_slot = def_like->m_slots; cur_slot && cur_slot->slot; cur_slot++) { // Macro to copy a non-NULL, non-repeatable slot. @@ -555,6 +556,7 @@ module_from_def_and_spec( if (PyABIInfo_Check((PyABIInfo *)cur_slot->value, name) < 0) { goto error; } + seen_m_abi_slot = true; break; DEF_SLOT_CASE(Py_mod_name, char*, m_name) DEF_SLOT_CASE(Py_mod_doc, char*, m_doc) @@ -587,6 +589,14 @@ module_from_def_and_spec( #undef COPY_NONDEF_SLOT #undef COPY_NONNULL_SLOT } + if (!original_def && !seen_m_abi_slot) { + PyErr_Format( + PyExc_SystemError, + "module %s does not define Py_mod_abi," + " which is mandatory for modules defined from slots only.", + name); + goto error; + } #ifdef Py_GIL_DISABLED // For modules created directly from slots (not from a def), we enable diff --git a/Python/modsupport.c b/Python/modsupport.c index 4624f326d17..bab21d1b2be 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -735,15 +735,15 @@ int PyABIInfo_Check(PyABIInfo *info, const char *module_name) return _abiinfo_raise( module_name, "incompatible future stable ABI version (%d.%d)", - ((info->abi_version) >> 24) % 0xff, - ((info->abi_version) >> 16) % 0xff); + ((info->abi_version) >> 24) & 0xff, + ((info->abi_version) >> 16) & 0xff); } if (info->abi_version < Py_PACK_VERSION(3, 2)) { return _abiinfo_raise( module_name, "invalid stable ABI version (%d.%d)", - ((info->abi_version) >> 24) % 0xff, - ((info->abi_version) >> 16) % 0xff); + ((info->abi_version) >> 24) & 0xff, + ((info->abi_version) >> 16) & 0xff); } } if (info->flags & PyABIInfo_INTERNAL) { @@ -758,8 +758,8 @@ int PyABIInfo_Check(PyABIInfo *info, const char *module_name) return _abiinfo_raise( module_name, "incompatible ABI version (%d.%d)", - ((info->abi_version) >> 24) % 0xff, - ((info->abi_version) >> 16) % 0xff); + ((info->abi_version) >> 24) & 0xff, + ((info->abi_version) >> 16) & 0xff); } } } From c1a4112c225e22d2707ff0a711353227e64f6fb5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 2 Apr 2026 13:55:34 +0200 Subject: [PATCH 374/775] gh-147988: Initialize digits in long_alloc() in debug mode (#147989) When Python is built in debug mode: * long_alloc() now initializes digits with a pattern to detect usage of uninitialized digits. * _PyLong_CompactValue() now makes sure that the digit is zero when the sign is zero. * PyLongWriter_Finish() now raises SystemError if it detects uninitialized digits Co-authored-by: Serhiy Storchaka --- Include/cpython/longintrepr.h | 5 ++++ Lib/test/test_capi/test_long.py | 10 ++++++++ Modules/_testcapi/long.c | 20 +++++++++++++++ Objects/longobject.c | 43 +++++++++++++++++++++++++++------ 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/Include/cpython/longintrepr.h b/Include/cpython/longintrepr.h index 804c1e9427e..998ebe68915 100644 --- a/Include/cpython/longintrepr.h +++ b/Include/cpython/longintrepr.h @@ -133,6 +133,11 @@ _PyLong_CompactValue(const PyLongObject *op) assert(PyType_HasFeature(op->ob_base.ob_type, Py_TPFLAGS_LONG_SUBCLASS)); assert(PyUnstable_Long_IsCompact(op)); sign = 1 - (op->long_value.lv_tag & _PyLong_SIGN_MASK); + if (sign == 0) { + // gh-147988: Make sure that the digit is zero. + // It helps detecting the usage of uninitialized digits. + assert(op->long_value.ob_digit[0] == 0); + } return sign * (Py_ssize_t)op->long_value.ob_digit[0]; } diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index fc0454b71cb..d1467caf688 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -803,6 +803,16 @@ def to_digits(num): self.assertEqual(pylongwriter_create(negative, digits), num, (negative, digits)) + @unittest.skipUnless(support.Py_DEBUG, "need a debug build (Py_DEBUG)") + def test_longwriter_finish(self): + # Test PyLongWriter_Create(0, 3, &digits) with PyLongWriter_Finish() + # where the last digit is left uninitialized + pylongwriter_finish_bug = _testcapi.pylongwriter_finish_bug + with self.assertRaises(SystemError) as cm: + pylongwriter_finish_bug() + self.assertEqual(str(cm.exception), + 'PyLongWriter_Finish: digit 2 is uninitialized') + def test_bug_143050(self): with support.adjust_int_max_str_digits(0): # Bug coming from using _pylong.int_from_string(), that diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c index 6313abf5485..008a7d37726 100644 --- a/Modules/_testcapi/long.c +++ b/Modules/_testcapi/long.c @@ -254,6 +254,25 @@ pylongwriter_create(PyObject *module, PyObject *args) } +static PyObject * +pylongwriter_finish_bug(PyObject *module, PyObject *Py_UNUSED(args)) +{ + void *writer_digits; + PyLongWriter *writer = PyLongWriter_Create(0, 3, &writer_digits); + if (writer == NULL) { + return NULL; + } + + assert(PyLong_GetNativeLayout()->digit_size == sizeof(digit)); + digit *digits = writer_digits; + digits[0] = 1; + digits[1] = 1; + // Oops, digits[2] is left uninitialized on purpose + // to test PyLongWriter_Finish() + return PyLongWriter_Finish(writer); +} + + static PyObject * get_pylong_layout(PyObject *module, PyObject *Py_UNUSED(args)) { @@ -271,6 +290,7 @@ static PyMethodDef test_methods[] = { {"pylong_aspid", pylong_aspid, METH_O}, {"pylong_export", pylong_export, METH_O}, {"pylongwriter_create", pylongwriter_create, METH_VARARGS}, + {"pylongwriter_finish_bug", pylongwriter_finish_bug, METH_NOARGS}, {"get_pylong_layout", get_pylong_layout, METH_NOARGS}, {"pylong_ispositive", pylong_ispositive, METH_O}, {"pylong_isnegative", pylong_isnegative, METH_O}, diff --git a/Objects/longobject.c b/Objects/longobject.c index fde01ff302d..549cf0b8f12 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -188,9 +188,11 @@ long_alloc(Py_ssize_t size) _PyLong_InitTag(result); } _PyLong_SetSignAndDigitCount(result, size != 0, size); - /* The digit has to be initialized explicitly to avoid - * use-of-uninitialized-value. */ - result->long_value.ob_digit[0] = 0; +#ifdef Py_DEBUG + // gh-147988: Fill digits with an invalid pattern to catch usage + // of uninitialized digits. + memset(result->long_value.ob_digit, 0xFF, ndigits * sizeof(digit)); +#endif return result; } @@ -1097,6 +1099,7 @@ _PyLong_FromByteArray(const unsigned char* bytes, size_t n, int sign = is_signed ? -1: 1; if (idigit == 0) { sign = 0; + v->long_value.ob_digit[0] = 0; } _PyLong_SetSignAndDigitCount(v, sign, idigit); return (PyObject *)maybe_small_long(long_normalize(v)); @@ -2855,6 +2858,7 @@ long_from_non_binary_base(const char *start, const char *end, Py_ssize_t digits, *res = NULL; return 0; } + z->long_value.ob_digit[0] = 0; _PyLong_SetSignAndDigitCount(z, 0, 0); /* `convwidth` consecutive input digits are treated as a single @@ -3368,6 +3372,7 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) *prem = NULL; return NULL; } + a->long_value.ob_digit[0] = 0; v0 = v->long_value.ob_digit; w0 = w->long_value.ob_digit; wm1 = w0[size_w-1]; @@ -4144,10 +4149,6 @@ k_mul(PyLongObject *a, PyLongObject *b) /* 1. Allocate result space. */ ret = long_alloc(asize + bsize); if (ret == NULL) goto fail; -#ifdef Py_DEBUG - /* Fill with trash, to catch reference to uninitialized digits. */ - memset(ret->long_value.ob_digit, 0xDF, _PyLong_DigitCount(ret) * sizeof(digit)); -#endif /* 2. t1 <- ah*bh, and copy into high digits of result. */ if ((t1 = k_mul(ah, bh)) == NULL) goto fail; @@ -5636,6 +5637,12 @@ long_bitwise(PyLongObject *a, Py_UNREACHABLE(); } + if ((size_z + negz) == 0) { + Py_XDECREF(new_a); + Py_XDECREF(new_b); + return get_small_int(0); + } + /* We allow an extra digit if z is negative, to make sure that the final two's complement of z doesn't overflow. */ z = long_alloc(size_z + negz); @@ -6959,6 +6966,28 @@ PyLongWriter_Finish(PyLongWriter *writer) PyLongObject *obj = (PyLongObject *)writer; assert(Py_REFCNT(obj) == 1); +#ifdef Py_DEBUG + // gh-147988: Detect uninitialized digits: long_alloc() fills digits with + // 0xFF byte pattern. It's posssible because PyLong_BASE is smaller than + // the maximum value of the C digit type (uint32_t or unsigned short): + // most significan bits are unused by the API. + Py_ssize_t ndigits = _PyLong_DigitCount(obj); + if (ndigits == 0) { + // Check ob_digit[0] digit for the number zero + ndigits = 1; + } + for (Py_ssize_t i = 0; i < ndigits; i++) { + digit d = obj->long_value.ob_digit[i]; + if (d & ~(digit)PyLong_MASK) { + Py_DECREF(obj); + PyErr_Format(PyExc_SystemError, + "PyLongWriter_Finish: digit %zd is uninitialized", + i); + return NULL; + } + } +#endif + // Normalize and get singleton if possible obj = maybe_small_long(long_normalize(obj)); From fc7a188fe70a7b98696b4fcee8db9eb8398aeb7b Mon Sep 17 00:00:00 2001 From: Ma Yukun <68433685+TheSkyC@users.noreply.github.com> Date: Thu, 2 Apr 2026 21:34:58 +0800 Subject: [PATCH 375/775] gh-146613: Fix re-entrant use-after-free in `itertools._grouper` (#147962) --- Lib/test/test_itertools.py | 32 +++++++++++++++++++ ...-04-01-11-05-36.gh-issue-146613.GzjUFK.rst | 2 ++ Modules/itertoolsmodule.c | 11 ++++++- 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index dc64288085f..cf579d4da4e 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -754,6 +754,38 @@ def keys(): next(g) next(g) # must pass with address sanitizer + def test_grouper_reentrant_eq_does_not_crash(self): + # regression test for gh-146613 + grouper_iter = None + + class Key: + __hash__ = None + + def __init__(self, do_advance): + self.do_advance = do_advance + + def __eq__(self, other): + nonlocal grouper_iter + if self.do_advance: + self.do_advance = False + if grouper_iter is not None: + try: + next(grouper_iter) + except StopIteration: + pass + return NotImplemented + return True + + def keyfunc(element): + if element == 0: + return Key(do_advance=True) + return Key(do_advance=False) + + g = itertools.groupby(range(4), keyfunc) + key, grouper_iter = next(g) + items = list(grouper_iter) + self.assertEqual(len(items), 1) + def test_filter(self): self.assertEqual(list(filter(isEven, range(6))), [0,2,4]) self.assertEqual(list(filter(None, [0,1,0,2,0])), [1,2]) diff --git a/Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst b/Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst new file mode 100644 index 00000000000..94e198e7b28 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst @@ -0,0 +1,2 @@ +:mod:`itertools`: Fix a crash in :func:`itertools.groupby` when +the grouper iterator is concurrently mutated. diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index cf49724b886..0453a166c84 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -678,7 +678,16 @@ _grouper_next(PyObject *op) } assert(gbo->currkey != NULL); - rcmp = PyObject_RichCompareBool(igo->tgtkey, gbo->currkey, Py_EQ); + /* A user-defined __eq__ can re-enter the grouper and advance the iterator, + mutating gbo->currkey while we are comparing them. + Take local snapshots and hold strong references so INCREF/DECREF + apply to the same objects even under re-entrancy. */ + PyObject *tgtkey = Py_NewRef(igo->tgtkey); + PyObject *currkey = Py_NewRef(gbo->currkey); + rcmp = PyObject_RichCompareBool(tgtkey, currkey, Py_EQ); + Py_DECREF(tgtkey); + Py_DECREF(currkey); + if (rcmp <= 0) /* got any error or current group is end */ return NULL; From 9b08f8c56f8d41b71fbe9f127a910e9644ac64ac Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 2 Apr 2026 16:53:09 +0200 Subject: [PATCH 376/775] GH-126910: Revert "Make `_Py_get_machine_stack_pointer` return the stack pointer (#147945)" (GH-147994) Revert "GH-126910: Make `_Py_get_machine_stack_pointer` return the stack pointer (#147945)" This reverts commit 255026d9eea81719214c8e807d23df55b5f39b54, which broke a tier-1 buildbot. --- Include/internal/pycore_ceval.h | 16 ++++++----- Include/internal/pycore_pystate.h | 22 +++++++-------- Include/internal/pycore_pythonrun.h | 3 +-- Include/pyport.h | 5 ---- Lib/test/test_pyexpat.py | 2 +- Python/ceval.c | 42 ++++++++++++++++++++++------- Python/jit.c | 2 +- 7 files changed, 55 insertions(+), 37 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index c86cd58e295..9fd3be74404 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -211,16 +211,16 @@ extern void _PyEval_DeactivateOpCache(void); /* --- _Py_EnterRecursiveCall() ----------------------------------------- */ -static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate) { +static inline int _Py_MakeRecCheck(PyThreadState *tstate) { uintptr_t here_addr = _Py_get_machine_stack_pointer(); _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - // Possible overflow if stack pointer is beyond the soft limit. - // _Py_CheckRecursiveCall will check for corner cases and - // report an error if there is an overflow. + // Overflow if stack pointer is between soft limit and the base of the hardware stack. + // If it is below the hardware stack base, assume that we have the wrong stack limits, and do nothing. + // We could have the wrong stack limits because of limited platform support, or user-space threads. #if _Py_STACK_GROWS_DOWN - return here_addr < _tstate->c_stack_soft_limit; + return here_addr < _tstate->c_stack_soft_limit && here_addr >= _tstate->c_stack_soft_limit - 2 * _PyOS_STACK_MARGIN_BYTES; #else - return here_addr > _tstate->c_stack_soft_limit; + return here_addr > _tstate->c_stack_soft_limit && here_addr <= _tstate->c_stack_soft_limit + 2 * _PyOS_STACK_MARGIN_BYTES; #endif } @@ -235,7 +235,7 @@ PyAPI_FUNC(int) _Py_CheckRecursiveCallPy( static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate, const char *where) { - return (_Py_ReachedRecursionLimit(tstate) && _Py_CheckRecursiveCall(tstate, where)); + return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where)); } static inline int _Py_EnterRecursiveCall(const char *where) { @@ -249,6 +249,8 @@ static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) { PyAPI_FUNC(void) _Py_InitializeRecursionLimits(PyThreadState *tstate); +PyAPI_FUNC(int) _Py_ReachedRecursionLimit(PyThreadState *tstate); + // Export for test_peg_generator PyAPI_FUNC(int) _Py_ReachedRecursionLimitWithMargin( PyThreadState *tstate, diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 054360d69e6..189a8dde9f0 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -306,23 +306,23 @@ _Py_AssertHoldsTstateFunc(const char *func) #define _Py_AssertHoldsTstate() #endif +#if !_Py__has_builtin(__builtin_frame_address) && !defined(__GNUC__) && !defined(_MSC_VER) +static uintptr_t return_pointer_as_int(char* p) { + return (uintptr_t)p; +} +#endif static inline uintptr_t _Py_get_machine_stack_pointer(void) { - uintptr_t result; -#if !defined(_MSC_VER) && defined(_M_ARM64) - result = __getReg(31); -#elif defined(_MSC_VER) && defined(_M_X64) - result = (uintptr_t)_AddressOfReturnAddress(); -#elif defined(__aarch64__) - __asm__ ("mov %0, sp" : "=r" (result)); -#elif defined(__x86_64__) - __asm__("{movq %%rsp, %0" : "=r" (result)); +#if _Py__has_builtin(__builtin_frame_address) || defined(__GNUC__) + return (uintptr_t)__builtin_frame_address(0); +#elif defined(_MSC_VER) + return (uintptr_t)_AddressOfReturnAddress(); #else char here; - result = (uintptr_t)&here; + /* Avoid compiler warning about returning stack address */ + return return_pointer_as_int(&here); #endif - return result; } static inline intptr_t diff --git a/Include/internal/pycore_pythonrun.h b/Include/internal/pycore_pythonrun.h index 66dd7cd843b..2a544edc431 100644 --- a/Include/internal/pycore_pythonrun.h +++ b/Include/internal/pycore_pythonrun.h @@ -46,8 +46,7 @@ extern PyObject * _Py_CompileStringObjectWithModule( * stack consumption of PyEval_EvalDefault */ #if (defined(Py_DEBUG) \ || defined(_Py_ADDRESS_SANITIZER) \ - || defined(_Py_THREAD_SANITIZER)) \ - || defined(_Py_UNDEFINED_BEHAVIOR_SANITIZER) + || defined(_Py_THREAD_SANITIZER)) # define _PyOS_LOG2_STACK_MARGIN 12 #else # define _PyOS_LOG2_STACK_MARGIN 11 diff --git a/Include/pyport.h b/Include/pyport.h index ee90711c202..f7bb5d513b9 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -598,11 +598,6 @@ extern "C" { # define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) # endif # endif -# if __has_feature(undefined_behavior_sanitizer) -# if !defined(_Py_UNDEFINED_BEHAVIOR_SANITIZER) -# define _Py_UNDEFINED_BEHAVIOR_SANITIZER -# endif -# endif #elif defined(__GNUC__) # if defined(__SANITIZE_ADDRESS__) # define _Py_ADDRESS_SANITIZER diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 0361d9f3da9..cace780f79f 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -707,7 +707,7 @@ def test_trigger_leak(self): def test_deeply_nested_content_model(self): # This should raise a RecursionError and not crash. # See https://github.com/python/cpython/issues/145986. - N = 800_000 + N = 500_000 data = ( b'c_stack_hard_limit) { +#else + if (here_addr > _tstate->c_stack_hard_limit) { +#endif + Py_FatalError("Unchecked stack overflow."); + } +} + #if defined(__s390x__) # define Py_C_STACK_SIZE 320000 #elif defined(_WIN32) @@ -264,7 +278,7 @@ PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate) /* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall() - if the stack pointer is beyond c_stack_soft_limit. */ + if the stack pointer is between the stack base and c_stack_hard_limit. */ int _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) { @@ -273,21 +287,16 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) assert(_tstate->c_stack_soft_limit != 0); assert(_tstate->c_stack_hard_limit != 0); #if _Py_STACK_GROWS_DOWN + assert(here_addr >= _tstate->c_stack_hard_limit - _PyOS_STACK_MARGIN_BYTES); if (here_addr < _tstate->c_stack_hard_limit) { - if (here_addr < _tstate->c_stack_hard_limit - _PyOS_STACK_MARGIN_BYTES) { - // Far out of bounds -- Assume stack switching has occurred - return 0; - } + /* Overflowing while handling an overflow. Give up. */ int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024; #else + assert(here_addr <= _tstate->c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES); if (here_addr > _tstate->c_stack_hard_limit) { - if (here_addr > _tstate->c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES) { - // Far out of bounds -- Assume stack switching has occurred - return 0; - } + /* Overflowing while handling an overflow. Give up. */ int kbytes_used = (int)(here_addr - _tstate->c_stack_top)/1024; #endif - /* Too much stack used to safely raise an exception. Give up. */ char buffer[80]; snprintf(buffer, 80, "Unrecoverable stack overflow (used %d kB)%s", kbytes_used, where); Py_FatalError(buffer); @@ -1192,6 +1201,19 @@ _PyEval_GetIter(_PyStackRef iterable, _PyStackRef *index_or_null, int yield_from return PyStackRef_FromPyObjectSteal(iter_o); } +Py_NO_INLINE int +_Py_ReachedRecursionLimit(PyThreadState *tstate) { + uintptr_t here_addr = _Py_get_machine_stack_pointer(); + _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; + assert(_tstate->c_stack_hard_limit != 0); +#if _Py_STACK_GROWS_DOWN + return here_addr <= _tstate->c_stack_soft_limit; +#else + return here_addr >= _tstate->c_stack_soft_limit; +#endif +} + + #if (defined(__GNUC__) && __GNUC__ >= 10 && !defined(__clang__)) && defined(__x86_64__) /* * gh-129987: The SLP autovectorizer can cause poor code generation for diff --git a/Python/jit.c b/Python/jit.c index d3a40ee6ff6..4990c743224 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -734,7 +734,7 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], siz return 0; } -/* One-off compilation of the jit entry shim. +/* One-off compilation of the jit entry shim * We compile this once only as it effectively a normal * function, but we need to use the JIT because it needs * to understand the jit-specific calling convention. From 86b8617747699416fcf9cd4ce6ea1da58a66f70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kul=C3=ADk?= Date: Thu, 2 Apr 2026 17:50:38 +0200 Subject: [PATCH 377/775] Move root user checks to test.support (#146195) --- Lib/test/support/__init__.py | 8 +++++++- Lib/test/test_mailbox.py | 7 +++---- Lib/test/test_os/test_os.py | 14 ++++++-------- Lib/test/test_pathlib/test_pathlib.py | 12 ++++-------- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 3da662b0c4d..8ff061e0740 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -71,7 +71,8 @@ "BrokenIter", "in_systemd_nspawn_sync_suppressed", "run_no_yield_async_fn", "run_yielding_async_fn", "async_yield", - "reset_code", "on_github_actions" + "reset_code", "on_github_actions", + "requires_root_user", "requires_non_root_user", ] @@ -3317,3 +3318,8 @@ def control_characters_c0() -> list[str]: C0 control characters defined as the byte range 0x00-0x1F, and 0x7F. """ return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"] + + +_ROOT_IN_POSIX = hasattr(os, 'geteuid') and os.geteuid() == 0 +requires_root_user = unittest.skipUnless(_ROOT_IN_POSIX, "test needs root privilege") +requires_non_root_user = unittest.skipIf(_ROOT_IN_POSIX, "test needs non-root account") diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index 7421076ddd4..019c699bff5 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -11,6 +11,7 @@ from test.support import import_helper, warnings_helper from test.support import os_helper from test.support import refleak_helper +from test.support import requires_root_user from test.support import socket_helper import unittest import textwrap @@ -1086,6 +1087,7 @@ def test_permissions_after_flush(self): self.assertEqual(os.stat(self._path).st_mode, mode) + @requires_root_user @unittest.skipUnless(hasattr(os, 'chown'), 'requires os.chown') def test_ownership_after_flush(self): # See issue gh-117467 @@ -1108,10 +1110,7 @@ def test_ownership_after_flush(self): else: self.skipTest("test needs more than one group") - try: - os.chown(self._path, other_uid, other_gid) - except OSError: - self.skipTest('test needs root privilege') + os.chown(self._path, other_uid, other_gid) # Change permissions as in test_permissions_after_flush. mode = st.st_mode | 0o666 os.chmod(self._path, mode) diff --git a/Lib/test/test_os/test_os.py b/Lib/test/test_os/test_os.py index 06f69caad12..7e670e5a139 100644 --- a/Lib/test/test_os/test_os.py +++ b/Lib/test/test_os/test_os.py @@ -33,6 +33,8 @@ from test.support import os_helper from test.support import socket_helper from test.support import infinite_recursion +from test.support import requires_root_user +from test.support import requires_non_root_user from test.support import warnings_helper from platform import win32_is_iot from .utils import create_file @@ -67,10 +69,6 @@ from test.support.os_helper import FakePath -root_in_posix = False -if hasattr(os, 'geteuid'): - root_in_posix = (os.geteuid() == 0) - # Detect whether we're on a Linux system that uses the (now outdated # and unmaintained) linuxthreads threading library. There's an issue # when combining linuxthreads with a failed execv call: see @@ -2257,8 +2255,8 @@ def test_chown_gid(self): gid = os.stat(os_helper.TESTFN).st_gid self.assertEqual(gid, gid_2) - @unittest.skipUnless(root_in_posix and len(all_users) > 1, - "test needs root privilege and more than one user") + @requires_root_user + @unittest.skipUnless(len(all_users) > 1, "test needs more than one user") def test_chown_with_root(self): uid_1, uid_2 = all_users[:2] gid = os.stat(os_helper.TESTFN).st_gid @@ -2269,8 +2267,8 @@ def test_chown_with_root(self): uid = os.stat(os_helper.TESTFN).st_uid self.assertEqual(uid, uid_2) - @unittest.skipUnless(not root_in_posix and len(all_users) > 1, - "test needs non-root account and more than one user") + @requires_non_root_user + @unittest.skipUnless(len(all_users) > 1, "test needs and more than one user") def test_chown_without_permission(self): uid_1, uid_2 = all_users[:2] gid = os.stat(os_helper.TESTFN).st_gid diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py index ef9ea0d11d0..d346a1a6160 100644 --- a/Lib/test/test_pathlib/test_pathlib.py +++ b/Lib/test/test_pathlib/test_pathlib.py @@ -20,6 +20,7 @@ from test.support import is_emscripten, is_wasi, is_wasm32 from test.support import infinite_recursion from test.support import os_helper +from test.support import requires_root_user from test.support.os_helper import TESTFN, FS_NONASCII, FakePath try: import fcntl @@ -35,11 +36,6 @@ posix = None -root_in_posix = False -if hasattr(os, 'geteuid'): - root_in_posix = (os.geteuid() == 0) - - def patch_replace(old_test): def new_replace(self, target): raise OSError(errno.EXDEV, "Cross-device link", self, target) @@ -1554,7 +1550,7 @@ def raiser(*args, **kwargs): self.assertRaises(FileNotFoundError, source.copy, target) @unittest.skipIf(sys.platform == "win32" or sys.platform == "wasi", "directories are always readable on Windows and WASI") - @unittest.skipIf(root_in_posix, "test fails with root privilege") + @requires_root_user def test_copy_dir_no_read_permission(self): base = self.cls(self.base) source = base / 'dirE' @@ -2027,7 +2023,7 @@ def test_owner(self): self.assertEqual(expected_name, p.owner()) @unittest.skipUnless(pwd, "the pwd module is needed for this test") - @unittest.skipUnless(root_in_posix, "test needs root privilege") + @requires_root_user def test_owner_no_follow_symlinks(self): all_users = [u.pw_uid for u in pwd.getpwall()] if len(all_users) < 2: @@ -2062,7 +2058,7 @@ def test_group(self): self.assertEqual(expected_name, p.group()) @unittest.skipUnless(grp, "the grp module is needed for this test") - @unittest.skipUnless(root_in_posix, "test needs root privilege") + @requires_root_user def test_group_no_follow_symlinks(self): all_groups = [g.gr_gid for g in grp.getgrall()] if len(all_groups) < 2: From 74a82a29ba047dfb14b288329981de237b66b348 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Fri, 3 Apr 2026 03:10:04 +0800 Subject: [PATCH 378/775] gh-139038: Update JIT results in preparation for 3.15a8 (GH-148018) Update JIT results in preparation for 3.15a8 --- Doc/whatsnew/3.15.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 6f5d84a3b8c..2a5f9c939e7 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1347,11 +1347,11 @@ Upgraded JIT compiler Results from the `pyperformance `__ benchmark suite report -`5-6% `__ +`6-7% `__ geometric mean performance improvement for the JIT over the standard CPython interpreter built with all optimizations enabled on x86-64 Linux. On AArch64 macOS, the JIT has a -`8-9% `__ +`12-13% `__ speedup over the :ref:`tail calling interpreter ` with all optimizations enabled. The speedups for JIT builds versus no JIT builds range from roughly 15% slowdown to over From 0c100664bc4c4bdaf6e2c0487a07b145b08c1e19 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Fri, 3 Apr 2026 02:20:13 +0500 Subject: [PATCH 379/775] GH-145247: Use _PyTuple_FromPair in Modules (part 1) (#148000) --- Modules/_asynciomodule.c | 13 ++++--------- Modules/_decimal/_decimal.c | 33 ++++++++++++--------------------- Modules/_elementtree.c | 9 +++++---- Modules/_json.c | 17 ++++------------- Modules/_operator.c | 2 +- Modules/_pickle.c | 32 +++++++++----------------------- Modules/_sre/sre.c | 30 ++++++++++-------------------- Modules/_threadmodule.c | 7 +++---- Modules/arraymodule.c | 28 ++++++++-------------------- Modules/itertoolsmodule.c | 14 ++++---------- Modules/main.c | 3 ++- 11 files changed, 62 insertions(+), 126 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index bd294648ca2..fda7d1ef934 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -13,6 +13,7 @@ #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_runtime_init.h" // _Py_ID() +#include "pycore_tuple.h" // _PyTuple_FromPair #include // offsetof() @@ -829,14 +830,10 @@ future_add_done_callback(asyncio_state *state, FutureObj *fut, PyObject *arg, fut->fut_context0 = Py_NewRef(ctx); } else { - PyObject *tup = PyTuple_New(2); + PyObject *tup = _PyTuple_FromPair(arg, (PyObject *)ctx); if (tup == NULL) { return NULL; } - Py_INCREF(arg); - PyTuple_SET_ITEM(tup, 0, arg); - Py_INCREF(ctx); - PyTuple_SET_ITEM(tup, 1, (PyObject *)ctx); if (fut->fut_callbacks != NULL) { int err = PyList_Append(fut->fut_callbacks, tup); @@ -1503,14 +1500,12 @@ _asyncio_Future__callbacks_get_impl(FutureObj *self) Py_ssize_t i = 0; if (self->fut_callback0 != NULL) { - PyObject *tup0 = PyTuple_New(2); + assert(self->fut_context0 != NULL); + PyObject *tup0 = _PyTuple_FromPair(self->fut_callback0, self->fut_context0); if (tup0 == NULL) { Py_DECREF(callbacks); return NULL; } - PyTuple_SET_ITEM(tup0, 0, Py_NewRef(self->fut_callback0)); - assert(self->fut_context0 != NULL); - PyTuple_SET_ITEM(tup0, 1, Py_NewRef(self->fut_context0)); PyList_SET_ITEM(callbacks, i, tup0); i++; } diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index b47014c4e74..0a8308d9ebc 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -32,6 +32,7 @@ #include #include "pycore_object.h" // _PyObject_VisitType() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_typeobject.h" #include @@ -3975,7 +3976,6 @@ _decimal_Decimal_as_integer_ratio_impl(PyObject *self, PyTypeObject *cls) PyObject *numerator = NULL; PyObject *denominator = NULL; PyObject *exponent = NULL; - PyObject *result = NULL; PyObject *tmp; mpd_ssize_t exp; PyObject *context; @@ -4035,6 +4035,7 @@ _decimal_Decimal_as_integer_ratio_impl(PyObject *self, PyTypeObject *cls) if (exp >= 0) { Py_SETREF(numerator, state->_py_long_multiply(numerator, exponent)); + Py_CLEAR(exponent); if (numerator == NULL) { goto error; } @@ -4061,15 +4062,13 @@ _decimal_Decimal_as_integer_ratio_impl(PyObject *self, PyTypeObject *cls) goto error; } } - - result = PyTuple_Pack(2, numerator, denominator); - + return _PyTuple_FromPairSteal(numerator, denominator); error: Py_XDECREF(exponent); Py_XDECREF(denominator); Py_XDECREF(numerator); - return result; + return NULL; } /*[clinic input] @@ -4613,7 +4612,6 @@ nm_mpd_qdivmod(PyObject *v, PyObject *w) PyObject *q, *r; PyObject *context; uint32_t status = 0; - PyObject *ret; decimal_state *state = find_state_left_or_right(v, w); CURRENT_CONTEXT(state, context); @@ -4642,10 +4640,7 @@ nm_mpd_qdivmod(PyObject *v, PyObject *w) return NULL; } - ret = PyTuple_Pack(2, q, r); - Py_DECREF(r); - Py_DECREF(q); - return ret; + return _PyTuple_FromPairSteal(q, r); } static PyObject * @@ -6674,7 +6669,6 @@ _decimal_Context_divmod_impl(PyObject *context, PyObject *x, PyObject *y) PyObject *a, *b; PyObject *q, *r; uint32_t status = 0; - PyObject *ret; CONVERT_BINOP_RAISE(&a, &b, x, y, context); decimal_state *state = get_module_state_from_ctx(context); @@ -6701,10 +6695,7 @@ _decimal_Context_divmod_impl(PyObject *context, PyObject *x, PyObject *y) return NULL; } - ret = PyTuple_Pack(2, q, r); - Py_DECREF(r); - Py_DECREF(q); - return ret; + return _PyTuple_FromPairSteal(q, r); } /* Binary or ternary arithmetic functions */ @@ -7810,15 +7801,15 @@ _decimal_exec(PyObject *m) switch (cm->flag) { case MPD_Float_operation: - base = PyTuple_Pack(2, state->DecimalException, PyExc_TypeError); + base = _PyTuple_FromPair(state->DecimalException, PyExc_TypeError); break; case MPD_Division_by_zero: - base = PyTuple_Pack(2, state->DecimalException, - PyExc_ZeroDivisionError); + base = _PyTuple_FromPair(state->DecimalException, + PyExc_ZeroDivisionError); break; case MPD_Overflow: - base = PyTuple_Pack(2, state->signal_map[INEXACT].ex, - state->signal_map[ROUNDED].ex); + base = _PyTuple_FromPair(state->signal_map[INEXACT].ex, + state->signal_map[ROUNDED].ex); break; case MPD_Underflow: base = PyTuple_Pack(3, state->signal_map[INEXACT].ex, @@ -7857,7 +7848,7 @@ _decimal_exec(PyObject *m) for (cm = state->cond_map+1; cm->name != NULL; cm++) { PyObject *base; if (cm->flag == MPD_Division_undefined) { - base = PyTuple_Pack(2, state->signal_map[0].ex, PyExc_ZeroDivisionError); + base = _PyTuple_FromPair(state->signal_map[0].ex, PyExc_ZeroDivisionError); } else { base = PyTuple_Pack(1, state->signal_map[0].ex); diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index ba909d15c2e..e2185c4bd03 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -18,6 +18,7 @@ #include "Python.h" #include "pycore_dict.h" // _PyDict_CopyAsDict() #include "pycore_pyhash.h" // _Py_HashSecret +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() #include // offsetof() @@ -2594,7 +2595,7 @@ _elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory, return NULL; } - old = PyTuple_Pack(2, + old = _PyTuple_FromPair( st->comment_factory ? st->comment_factory : Py_None, st->pi_factory ? st->pi_factory : Py_None); @@ -2712,7 +2713,7 @@ treebuilder_append_event(TreeBuilderObject *self, PyObject *action, { if (action != NULL) { PyObject *res; - PyObject *event = PyTuple_Pack(2, action, node); + PyObject *event = _PyTuple_FromPair(action, node); if (event == NULL) return -1; res = PyObject_CallOneArg(self->events_append, event); @@ -2933,7 +2934,7 @@ treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text) Py_XSETREF(self->last_for_tail, Py_NewRef(pi)); } } else { - pi = PyTuple_Pack(2, target, text); + pi = _PyTuple_FromPair(target, text); if (!pi) { return NULL; } @@ -2957,7 +2958,7 @@ treebuilder_handle_start_ns(TreeBuilderObject* self, PyObject* prefix, PyObject* PyObject* parcel; if (self->events_append && self->start_ns_event_obj) { - parcel = PyTuple_Pack(2, prefix, uri); + parcel = _PyTuple_FromPair(prefix, uri); if (!parcel) { return NULL; } diff --git a/Modules/_json.c b/Modules/_json.c index f70c3612508..36614138501 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -14,6 +14,7 @@ #include "pycore_global_strings.h" // _Py_ID() #include "pycore_pyerrors.h" // _PyErr_FormatNote #include "pycore_runtime.h" // _PyRuntime +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_CheckConsistency() #include // bool @@ -446,7 +447,6 @@ raise_stop_iteration(Py_ssize_t idx) static PyObject * _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) { /* return (rval, idx) tuple, stealing reference to rval */ - PyObject *tpl; PyObject *pyidx; /* steal a reference to rval, returns (rval, idx) @@ -459,15 +459,7 @@ _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) { Py_DECREF(rval); return NULL; } - tpl = PyTuple_New(2); - if (tpl == NULL) { - Py_DECREF(pyidx); - Py_DECREF(rval); - return NULL; - } - PyTuple_SET_ITEM(tpl, 0, rval); - PyTuple_SET_ITEM(tpl, 1, pyidx); - return tpl; + return _PyTuple_FromPairSteal(rval, pyidx); } static PyObject * @@ -810,11 +802,10 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss goto bail; if (has_pairs_hook) { - PyObject *item = PyTuple_Pack(2, key, val); + PyObject *item = _PyTuple_FromPairSteal(key, val); + key = val = NULL; if (item == NULL) goto bail; - Py_CLEAR(key); - Py_CLEAR(val); if (PyList_Append(rval, item) == -1) { Py_DECREF(item); goto bail; diff --git a/Modules/_operator.c b/Modules/_operator.c index d04732dc314..417403dc4c1 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -1194,7 +1194,7 @@ itemgetter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) itemgetterobject *ig = itemgetterobject_CAST(op); if (ig->nitems == 1) return Py_BuildValue("O(O)", Py_TYPE(ig), ig->item); - return PyTuple_Pack(2, Py_TYPE(ig), ig->item); + return _PyTuple_FromPair((PyObject *)Py_TYPE(ig), ig->item); } PyDoc_STRVAR(reduce_doc, "Return state information for pickling"); diff --git a/Modules/_pickle.c b/Modules/_pickle.c index a28e5feebc1..9874f9475ac 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -21,6 +21,7 @@ #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_symtable.h" // _Py_Mangle() #include "pycore_sysmodule.h" // _PySys_GetSizeOf() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include // strtol() @@ -3767,7 +3768,7 @@ fix_imports(PickleState *st, PyObject **module_name, PyObject **global_name) PyObject *key; PyObject *item; - key = PyTuple_Pack(2, *module_name, *global_name); + key = _PyTuple_FromPair(*module_name, *global_name); if (key == NULL) return -1; item = PyDict_GetItemWithError(st->name_mapping_3to2, key); @@ -3873,7 +3874,7 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj, char pdata[5]; Py_ssize_t n; - extension_key = PyTuple_Pack(2, module_name, global_name); + extension_key = _PyTuple_FromPair(module_name, global_name); if (extension_key == NULL) { goto error; } @@ -5133,26 +5134,19 @@ static PyObject * _pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self) /*[clinic end generated code: output=bebba1168863ab1d input=2f7c540e24b7aae4]*/ { - PyObject *reduce_value, *dict_args; + PyObject *dict_args; PyObject *contents = _pickle_PicklerMemoProxy_copy_impl(self); if (contents == NULL) return NULL; - reduce_value = PyTuple_New(2); - if (reduce_value == NULL) { - Py_DECREF(contents); - return NULL; - } dict_args = PyTuple_New(1); if (dict_args == NULL) { Py_DECREF(contents); - Py_DECREF(reduce_value); return NULL; } PyTuple_SET_ITEM(dict_args, 0, contents); - PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef(&PyDict_Type)); - PyTuple_SET_ITEM(reduce_value, 1, dict_args); - return reduce_value; + + return _PyTuple_FromPairSteal(Py_NewRef(&PyDict_Type), dict_args); } static PyMethodDef picklerproxy_methods[] = { @@ -7310,7 +7304,7 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyTypeObject *cls, /* Check if the global (i.e., a function or a class) was renamed or moved to another module. */ - key = PyTuple_Pack(2, module_name, global_name); + key = _PyTuple_FromPair(module_name, global_name); if (key == NULL) return NULL; item = PyDict_GetItemWithError(st->name_mapping_2to3, key); @@ -7640,27 +7634,19 @@ static PyObject * _pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self) /*[clinic end generated code: output=6da34ac048d94cca input=6920862413407199]*/ { - PyObject *reduce_value; PyObject *constructor_args; PyObject *contents = _pickle_UnpicklerMemoProxy_copy_impl(self); if (contents == NULL) return NULL; - reduce_value = PyTuple_New(2); - if (reduce_value == NULL) { - Py_DECREF(contents); - return NULL; - } constructor_args = PyTuple_New(1); if (constructor_args == NULL) { Py_DECREF(contents); - Py_DECREF(reduce_value); return NULL; } PyTuple_SET_ITEM(constructor_args, 0, contents); - PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef(&PyDict_Type)); - PyTuple_SET_ITEM(reduce_value, 1, constructor_args); - return reduce_value; + + return _PyTuple_FromPairSteal(Py_NewRef(&PyDict_Type), constructor_args); } static PyMethodDef unpicklerproxy_methods[] = { diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 54de09a7d77..044eb6e5f1f 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -43,6 +43,7 @@ static const char copyright[] = #include "pycore_dict.h" // _PyDict_Next() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_unicodeobject.h" // _PyUnicode_Copy #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() @@ -2572,28 +2573,17 @@ _sre_SRE_Match_end_impl(MatchObject *self, PyObject *group) LOCAL(PyObject*) _pair(Py_ssize_t i1, Py_ssize_t i2) { - PyObject* pair; - PyObject* item; - - pair = PyTuple_New(2); - if (!pair) + PyObject* item1 = PyLong_FromSsize_t(i1); + if (!item1) { return NULL; + } + PyObject* item2 = PyLong_FromSsize_t(i2); + if(!item2) { + Py_DECREF(item1); + return NULL; + } - item = PyLong_FromSsize_t(i1); - if (!item) - goto error; - PyTuple_SET_ITEM(pair, 0, item); - - item = PyLong_FromSsize_t(i2); - if (!item) - goto error; - PyTuple_SET_ITEM(pair, 1, item); - - return pair; - - error: - Py_DECREF(pair); - return NULL; + return _PyTuple_FromPairSteal(item1, item2); } /*[clinic input] diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 529257c2aa7..135b5311101 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -11,6 +11,7 @@ #include "pycore_pylifecycle.h" #include "pycore_pystate.h" // _PyThreadState_SetCurrent() #include "pycore_time.h" // _PyTime_FromSeconds() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_weakref.h" // _PyWeakref_GET_REF() #include // offsetof() @@ -1480,13 +1481,11 @@ create_sentinel_wr(localobject *self) return NULL; } - PyObject *args = PyTuple_New(2); + PyObject *args = _PyTuple_FromPairSteal(self_wr, + Py_NewRef(tstate->threading_local_key)); if (args == NULL) { - Py_DECREF(self_wr); return NULL; } - PyTuple_SET_ITEM(args, 0, self_wr); - PyTuple_SET_ITEM(args, 1, Py_NewRef(tstate->threading_local_key)); PyObject *cb = PyCFunction_New(&wr_callback_def, args); Py_DECREF(args); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 555a35b3fc9..a86a7561271 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -14,6 +14,7 @@ #include "pycore_floatobject.h" // _PY_FLOAT_BIG_ENDIAN #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() #include // offsetof() @@ -1542,27 +1543,17 @@ static PyObject * array_array_buffer_info_impl(arrayobject *self) /*[clinic end generated code: output=9b2a4ec3ae7e98e7 input=63d9ad83ba60cda8]*/ { - PyObject *retval = NULL, *v; - - retval = PyTuple_New(2); - if (!retval) - return NULL; - - v = PyLong_FromVoidPtr(self->ob_item); - if (v == NULL) { - Py_DECREF(retval); + PyObject* item1 = PyLong_FromVoidPtr(self->ob_item); + if (item1 == NULL) { return NULL; } - PyTuple_SET_ITEM(retval, 0, v); - - v = PyLong_FromSsize_t(Py_SIZE(self)); - if (v == NULL) { - Py_DECREF(retval); + PyObject* item2 = PyLong_FromSsize_t(Py_SIZE(self)); + if (item2 == NULL) { + Py_DECREF(item1); return NULL; } - PyTuple_SET_ITEM(retval, 1, v); - return retval; + return _PyTuple_FromPairSteal(item1, item2); } /*[clinic input] @@ -2248,13 +2239,10 @@ make_array(PyTypeObject *arraytype, char typecode, PyObject *items) if (typecode_obj == NULL) return NULL; - new_args = PyTuple_New(2); + new_args = _PyTuple_FromPairSteal(typecode_obj, Py_NewRef(items)); if (new_args == NULL) { - Py_DECREF(typecode_obj); return NULL; } - PyTuple_SET_ITEM(new_args, 0, typecode_obj); - PyTuple_SET_ITEM(new_args, 1, Py_NewRef(items)); array_obj = array_new(arraytype, new_args, NULL); Py_DECREF(new_args); diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 0453a166c84..a6bfa78a461 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -310,7 +310,7 @@ pairwise_new_impl(PyTypeObject *type, PyObject *iterable) } po->it = it; po->old = NULL; - po->result = PyTuple_Pack(2, Py_None, Py_None); + po->result = _PyTuple_FromPairSteal(Py_None, Py_None); if (po->result == NULL) { Py_DECREF(po); return NULL; @@ -389,11 +389,7 @@ pairwise_next(PyObject *op) _PyTuple_Recycle(result); } else { - result = PyTuple_New(2); - if (result != NULL) { - PyTuple_SET_ITEM(result, 0, Py_NewRef(old)); - PyTuple_SET_ITEM(result, 1, Py_NewRef(new)); - } + result = _PyTuple_FromPair(old, new); } Py_XSETREF(po->old, new); @@ -533,7 +529,7 @@ groupby_step(groupbyobject *gbo) static PyObject * groupby_next(PyObject *op) { - PyObject *r, *grouper; + PyObject *grouper; groupbyobject *gbo = groupbyobject_CAST(op); gbo->currgrouper = NULL; @@ -573,9 +569,7 @@ groupby_next(PyObject *op) if (grouper == NULL) return NULL; - r = PyTuple_Pack(2, gbo->currkey, grouper); - Py_DECREF(grouper); - return r; + return _PyTuple_FromPairSteal(Py_NewRef(gbo->currkey), grouper); } static PyType_Slot groupby_slots[] = { diff --git a/Modules/main.c b/Modules/main.c index 7731fa0c7c6..a4dfddd98e2 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -11,6 +11,7 @@ #include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_pythonrun.h" // _PyRun_AnyFileObject() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_Dedent() /* Includes for exit_sigint() */ @@ -342,7 +343,7 @@ pymain_run_module(const wchar_t *modname, int set_argv0) Py_DECREF(runmodule); return pymain_exit_err_print(); } - runargs = PyTuple_Pack(2, module, set_argv0 ? Py_True : Py_False); + runargs = _PyTuple_FromPair(module, set_argv0 ? Py_True : Py_False); if (runargs == NULL) { fprintf(stderr, "Could not create arguments for runpy._run_module_as_main\n"); From c1b20a6d96eadf1c49c511f1e480aff82b6477a4 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Fri, 3 Apr 2026 02:24:03 +0500 Subject: [PATCH 380/775] GH-145247: Use _PyTuple_FromPair in Modules (part 2) (#148003) Co-authored-by: Victor Stinner --- Modules/_ctypes/_ctypes.c | 6 ++-- Modules/_datetimemodule.c | 9 ++--- Modules/_interpretersmodule.c | 6 ++-- Modules/_ssl.c | 3 +- Modules/cjkcodecs/multibytecodec.c | 20 ++++------- Modules/overlapped.c | 30 ++++++++--------- Modules/posixmodule.c | 6 ++-- Modules/selectmodule.c | 5 ++- Modules/signalmodule.c | 24 ++++---------- Modules/socketmodule.c | 53 ++++++++++++++---------------- 10 files changed, 66 insertions(+), 96 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 9a6f377fdb0..57d3d78969f 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -111,6 +111,7 @@ bytes(cdata) #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() #include "pycore_pyatomic_ft_wrappers.h" #include "pycore_object.h" +#include "pycore_tuple.h" // _PyTuple_FromPair #ifdef MS_WIN32 # include "pycore_modsupport.h" // _PyArg_NoKeywords() #endif @@ -3511,7 +3512,7 @@ _PyCData_set(ctypes_state *st, only it's object list. So we create a tuple, containing b_objects list PLUS the array itself, and return that! */ - return PyTuple_Pack(2, keep, value); + return _PyTuple_FromPair(keep, value); } PyErr_Format(PyExc_TypeError, "incompatible types, %s instance instead of %s instance", @@ -5332,8 +5333,7 @@ PyCArrayType_from_ctype(ctypes_state *st, PyObject *itemtype, Py_ssize_t length) len = PyLong_FromSsize_t(length); if (len == NULL) return NULL; - key = PyTuple_Pack(2, itemtype, len); - Py_DECREF(len); + key = _PyTuple_FromPairSteal(Py_NewRef(itemtype), len); if (!key) return NULL; diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 0db8bc675c4..163e499d957 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -13,6 +13,7 @@ #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_object.h" // _PyObject_Init() #include "pycore_time.h" // _PyTime_ObjectToTime_t() +#include "pycore_tuple.h" // _PyTuple_FromPair #include "pycore_unicodeobject.h" // _PyUnicode_Copy() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_pyatomic_ft_wrappers.h" @@ -2692,7 +2693,7 @@ delta_divmod(PyObject *left, PyObject *right) Py_DECREF(divmod); return NULL; } - result = PyTuple_Pack(2, PyTuple_GET_ITEM(divmod, 0), delta); + result = _PyTuple_FromPair(PyTuple_GET_ITEM(divmod, 0), delta); Py_DECREF(delta); Py_DECREF(divmod); return result; @@ -4496,7 +4497,7 @@ timezone_getinitargs(PyObject *op, PyObject *Py_UNUSED(dummy)) PyDateTime_TimeZone *self = PyTimeZone_CAST(op); if (self->name == NULL) return PyTuple_Pack(1, self->offset); - return PyTuple_Pack(2, self->offset, self->name); + return _PyTuple_FromPair(self->offset, self->name); } static PyMethodDef timezone_methods[] = { @@ -5247,7 +5248,7 @@ time_getstate(PyDateTime_Time *self, int proto) if (! HASTZINFO(self) || self->tzinfo == Py_None) result = PyTuple_Pack(1, basestate); else - result = PyTuple_Pack(2, basestate, self->tzinfo); + result = _PyTuple_FromPair(basestate, self->tzinfo); Py_DECREF(basestate); } return result; @@ -7169,7 +7170,7 @@ datetime_getstate(PyDateTime_DateTime *self, int proto) if (! HASTZINFO(self) || self->tzinfo == Py_None) result = PyTuple_Pack(1, basestate); else - result = PyTuple_Pack(2, basestate, self->tzinfo); + result = _PyTuple_FromPair(basestate, self->tzinfo); Py_DECREF(basestate); } return result; diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index b65140e003b..4c9be1d525d 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -15,6 +15,7 @@ #include "pycore_pybuffer.h" // _PyBuffer_ReleaseInInterpreterAndRawFree() #include "pycore_pylifecycle.h" // _PyInterpreterConfig_AsDict() #include "pycore_pystate.h" // _PyInterpreterState_IsRunningMain() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "marshal.h" // PyMarshal_ReadObjectFromString() @@ -796,10 +797,7 @@ get_summary(PyInterpreterState *interp) Py_DECREF(idobj); return NULL; } - PyObject *res = PyTuple_Pack(2, idobj, whenceobj); - Py_DECREF(idobj); - Py_DECREF(whenceobj); - return res; + return _PyTuple_FromPairSteal(idobj, whenceobj); } diff --git a/Modules/_ssl.c b/Modules/_ssl.c index b93bbe8ddf5..4e563379098 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -30,6 +30,7 @@ #include "pycore_long.h" // _PyLong_UnsignedLongLong_Converter() #include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() #include "pycore_time.h" // _PyDeadline_Init() +#include "pycore_tuple.h" // _PyTuple_FromPair /* Include symbols from _socket module */ #include "socketmodule.h" @@ -6796,7 +6797,7 @@ do { \ } /* ssl.CertificateError used to be a subclass of ValueError */ - bases = PyTuple_Pack(2, state->PySSLErrorObject, PyExc_ValueError); + bases = _PyTuple_FromPair(state->PySSLErrorObject, PyExc_ValueError); if (bases == NULL) { goto error; } diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index d774a4968b8..f1124147e2b 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -12,6 +12,7 @@ #include "multibytecodec.h" #include "clinic/multibytecodec.c.h" +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include // offsetof() @@ -102,26 +103,17 @@ static PyObject *multibytecodec_encode(const MultibyteCodec *, static PyObject * make_tuple(PyObject *object, Py_ssize_t len) { - PyObject *v, *w; - - if (object == NULL) + if (object == NULL) { return NULL; + } - v = PyTuple_New(2); - if (v == NULL) { + PyObject* len_obj = PyLong_FromSsize_t(len); + if (len_obj == NULL) { Py_DECREF(object); return NULL; } - PyTuple_SET_ITEM(v, 0, object); - w = PyLong_FromSsize_t(len); - if (w == NULL) { - Py_DECREF(v); - return NULL; - } - PyTuple_SET_ITEM(v, 1, w); - - return v; + return _PyTuple_FromPairSteal(object, len_obj); } static PyObject * diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 8d2bd87ddb3..822e1ce4bdc 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -12,6 +12,7 @@ #endif #include "Python.h" +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #define WINDOWS_LEAN_AND_MEAN #include @@ -896,6 +897,7 @@ _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait) BOOL ret; DWORD err; PyObject *addr; + PyObject *transferred_obj; if (self->type == TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation not yet attempted"); @@ -964,18 +966,12 @@ _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait) } // The result is a two item tuple: (message, address) - self->read_from.result = PyTuple_New(2); + self->read_from.result = _PyTuple_FromPairSteal( + Py_NewRef(self->read_from.allocated_buffer), addr); if (self->read_from.result == NULL) { - Py_CLEAR(addr); return NULL; } - // first item: message - PyTuple_SET_ITEM(self->read_from.result, 0, - Py_NewRef(self->read_from.allocated_buffer)); - // second item: address - PyTuple_SET_ITEM(self->read_from.result, 1, addr); - return Py_NewRef(self->read_from.result); case TYPE_READ_FROM_INTO: // unparse the address @@ -986,18 +982,18 @@ _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait) return NULL; } - // The result is a two item tuple: (number of bytes read, address) - self->read_from_into.result = PyTuple_New(2); - if (self->read_from_into.result == NULL) { - Py_CLEAR(addr); + transferred_obj = PyLong_FromUnsignedLong((unsigned long)transferred); + if (transferred_obj == NULL) { + Py_DECREF(addr); return NULL; } - // first item: number of bytes read - PyTuple_SET_ITEM(self->read_from_into.result, 0, - PyLong_FromUnsignedLong((unsigned long)transferred)); - // second item: address - PyTuple_SET_ITEM(self->read_from_into.result, 1, addr); + // The result is a two item tuple: (number of bytes read, address) + self->read_from_into.result = _PyTuple_FromPairSteal( + transferred_obj, addr); + if (self->read_from_into.result == NULL) { + return NULL; + } return Py_NewRef(self->read_from_into.result); default: diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 07c2b73575f..e5ce487723b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -27,6 +27,7 @@ #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_signal.h" // Py_NSIG #include "pycore_time.h" // _PyLong_FromTime_t() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_typeobject.h" // _PyType_AddMethod() #ifndef MS_WINDOWS @@ -11288,10 +11289,7 @@ build_itimerspec(const struct itimerspec* curr_value) Py_DECREF(value); return NULL; } - PyObject *tuple = PyTuple_Pack(2, value, interval); - Py_DECREF(interval); - Py_DECREF(value); - return tuple; + return _PyTuple_FromPairSteal(value, interval); } static PyObject * diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 32bd9ab0873..eb3148ef246 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -15,6 +15,7 @@ #include "Python.h" #include "pycore_fileutils.h" // _Py_set_inheritable() #include "pycore_time.h" // _PyTime_FromSecondsObject() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include #include // offsetof() @@ -1075,9 +1076,7 @@ select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj) Py_XDECREF(num2); goto error; } - value = PyTuple_Pack(2, num1, num2); - Py_DECREF(num1); - Py_DECREF(num2); + value = _PyTuple_FromPairSteal(num1, num2); if (value == NULL) goto error; PyList_SET_ITEM(result_list, i, value); diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 42ec786f953..fb548b8ca00 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -14,6 +14,7 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_signal.h" // _Py_RestoreSignals() #include "pycore_time.h" // _PyTime_FromSecondsObject() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #ifndef MS_WINDOWS # include "posixmodule.h" // _PyLong_FromUid() @@ -193,27 +194,16 @@ double_from_timeval(struct timeval *tv) static PyObject * itimer_retval(struct itimerval *iv) { - PyObject *r, *v; - - r = PyTuple_New(2); - if (r == NULL) - return NULL; - - if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_value)))) { - Py_DECREF(r); + PyObject *value = PyFloat_FromDouble(double_from_timeval(&iv->it_value)); + if (value == NULL) { return NULL; } - - PyTuple_SET_ITEM(r, 0, v); - - if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)))) { - Py_DECREF(r); + PyObject *interval = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)); + if (interval == NULL) { + Py_DECREF(value); return NULL; } - - PyTuple_SET_ITEM(r, 1, v); - - return r; + return _PyTuple_FromPairSteal(value, interval); } #endif diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index a97b09a4f5d..f1a55db229e 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -111,6 +111,7 @@ Local naming conventions: #include "pycore_moduleobject.h" // _PyModule_GetState #include "pycore_object.h" // _PyObject_VisitType() #include "pycore_time.h" // _PyTime_AsMilliseconds() +#include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_pystate.h" // _Py_AssertHoldsTstate() #ifdef _Py_MEMORY_SANITIZER @@ -3076,7 +3077,6 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) socklen_t addrlen; PyObject *sock = NULL; PyObject *addr = NULL; - PyObject *res = NULL; struct sock_accept ctx; if (!getsockaddrlen(s, &addrlen)) @@ -3102,7 +3102,7 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) if (!SetHandleInformation((HANDLE)newfd, HANDLE_FLAG_INHERIT, 0)) { PyErr_SetFromWindowsErr(0); SOCKETCLOSE(newfd); - goto finally; + goto error; } #endif #else @@ -3113,7 +3113,7 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) { if (_Py_set_inheritable(newfd, 0, NULL) < 0) { SOCKETCLOSE(newfd); - goto finally; + goto error; } } #endif @@ -3121,20 +3121,20 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) sock = PyLong_FromSocket_t(newfd); if (sock == NULL) { SOCKETCLOSE(newfd); - goto finally; + goto error; } addr = makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen, s->sock_proto); if (addr == NULL) - goto finally; + goto error; - res = PyTuple_Pack(2, sock, addr); + return _PyTuple_FromPairSteal(sock, addr); -finally: +error: Py_XDECREF(sock); Py_XDECREF(addr); - return res; + return NULL; } PyDoc_STRVAR(accept_doc, @@ -4166,7 +4166,6 @@ sock_recvfrom(PyObject *self, PyObject *args) PySocketSockObject *s = _PySocketSockObject_CAST(self); PyObject *addr = NULL; - PyObject *ret = NULL; int flags = 0; Py_ssize_t recvlen, outlen; @@ -4188,20 +4187,19 @@ sock_recvfrom(PyObject *self, PyObject *args) recvlen, flags, &addr); if (outlen < 0) { PyBytesWriter_Discard(writer); - goto finally; + goto error; } PyObject *buf = PyBytesWriter_FinishWithSize(writer, outlen); if (buf == NULL) { - goto finally; + goto error; } - ret = PyTuple_Pack(2, buf, addr); - Py_DECREF(buf); + return _PyTuple_FromPairSteal(buf, addr); -finally: +error: Py_XDECREF(addr); - return ret; + return NULL; } PyDoc_STRVAR(recvfrom_doc, @@ -6543,7 +6541,6 @@ socket_socketpair(PyObject *self, PyObject *args) PySocketSockObject *s0 = NULL, *s1 = NULL; SOCKET_T sv[2]; int family, type = SOCK_STREAM, proto = 0; - PyObject *res = NULL; socket_state *state = get_module_state(self); #ifdef SOCK_CLOEXEC int *atomic_flag_works = &sock_cloexec_works; @@ -6588,28 +6585,26 @@ socket_socketpair(PyObject *self, PyObject *args) return set_error(); if (_Py_set_inheritable(sv[0], 0, atomic_flag_works) < 0) - goto finally; + goto error; if (_Py_set_inheritable(sv[1], 0, atomic_flag_works) < 0) - goto finally; + goto error; s0 = new_sockobject(state, sv[0], family, type, proto); if (s0 == NULL) - goto finally; + goto error; s1 = new_sockobject(state, sv[1], family, type, proto); if (s1 == NULL) - goto finally; - res = PyTuple_Pack(2, s0, s1); + goto error; + return _PyTuple_FromPairSteal((PyObject *)s0, (PyObject *)s1); -finally: - if (res == NULL) { - if (s0 == NULL) - SOCKETCLOSE(sv[0]); - if (s1 == NULL) - SOCKETCLOSE(sv[1]); - } +error: + if (s0 == NULL) + SOCKETCLOSE(sv[0]); + if (s1 == NULL) + SOCKETCLOSE(sv[1]); Py_XDECREF(s0); Py_XDECREF(s1); - return res; + return NULL; } PyDoc_STRVAR(socketpair_doc, From 617f4cc1c2605b86b4833450253c3599b61d6638 Mon Sep 17 00:00:00 2001 From: Tadej Magajna Date: Thu, 2 Apr 2026 23:26:21 +0200 Subject: [PATCH 381/775] gh-142533: Document CRLF injection vulnerabilities in http.server doc (#143395) Co-authored-by: Victor Stinner --- Doc/library/http.server.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index bd8c3f09cb4..cb8b5f0df88 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -287,6 +287,8 @@ instantiation, of which this module provides three different variants: specifying its value. Note that, after the send_header calls are done, :meth:`end_headers` MUST BE called in order to complete the operation. + This method does not reject input containing CRLF sequences. + .. versionchanged:: 3.2 Headers are stored in an internal buffer. @@ -297,6 +299,8 @@ instantiation, of which this module provides three different variants: buffered and sent directly the output stream.If the *message* is not specified, the HTTP message corresponding the response *code* is sent. + This method does not reject *message* containing CRLF sequences. + .. versionadded:: 3.2 .. method:: end_headers() @@ -555,6 +559,11 @@ Security considerations requests, this makes it possible for files outside of the specified directory to be served. +Methods :meth:`BaseHTTPRequestHandler.send_header` and +:meth:`BaseHTTPRequestHandler.send_response_only` assume sanitized input +and does not perform input validation such as checking for the presence of CRLF +sequences. Untrusted input may result in HTTP Header injection attacks. + Earlier versions of Python did not scrub control characters from the log messages emitted to stderr from ``python -m http.server`` or the default :class:`BaseHTTPRequestHandler` ``.log_message`` From 9d087d6d41e1eaa0d1b9612ba65c5a4fb6aca098 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Thu, 2 Apr 2026 23:34:06 -0700 Subject: [PATCH 382/775] GH-147985: Use lock-free lookup in `PySet_Contains` (#147986) Co-authored-by: Kumar Aditya --- .../2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst | 3 +++ Objects/setobject.c | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst new file mode 100644 index 00000000000..a94dfca5e2a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst @@ -0,0 +1,3 @@ +Make :c:func:`PySet_Contains` attempt a lock-free lookup, similar to +:meth:`!set.__contains__`. This avoids acquiring the set object mutex in the +normal case. diff --git a/Objects/setobject.c b/Objects/setobject.c index ae6c1d1248d..1e630563604 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -3023,14 +3023,14 @@ PySet_Contains(PyObject *anyset, PyObject *key) PyErr_BadInternalCall(); return -1; } - if (PyFrozenSet_CheckExact(anyset)) { - return set_contains_key((PySetObject *)anyset, key); + + PySetObject *so = (PySetObject *)anyset; + Py_hash_t hash = _PyObject_HashFast(key); + if (hash == -1) { + set_unhashable_type(key); + return -1; } - int rv; - Py_BEGIN_CRITICAL_SECTION(anyset); - rv = set_contains_key((PySetObject *)anyset, key); - Py_END_CRITICAL_SECTION(); - return rv; + return set_contains_entry(so, key, hash); } int From f3b74d62698d5f0ee7dd905b8a7b9189e6ef9fce Mon Sep 17 00:00:00 2001 From: Miikka Koskinen Date: Fri, 3 Apr 2026 09:47:21 +0300 Subject: [PATCH 383/775] gh-80642: timeit - make target time of autorange configurable (#140283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alessandro Cucci Co-authored-by: blurb-it[bot] Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Co-authored-by: Stan Ulbrych Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/library/timeit.rst | 18 ++++++++--- Doc/whatsnew/3.15.rst | 5 +++ Lib/test/test_timeit.py | 9 ++++-- Lib/timeit.py | 31 ++++++++++++------- .../2019-04-25-21-11-37.bpo-36461.TO5YyP.rst | 3 ++ 5 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst index bc12061a2ae..aed7e7556f6 100644 --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -143,21 +143,24 @@ The module defines three convenience functions and a public class: timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit() - .. method:: Timer.autorange(callback=None) + .. method:: Timer.autorange(callback=None, target_time=None) Automatically determine how many times to call :meth:`.timeit`. This is a convenience function that calls :meth:`.timeit` repeatedly - so that the total time >= 0.2 second, returning the eventual + so that the total time >= *Timer.target_time* seconds, returning the eventual (number of loops, time taken for that number of loops). It calls :meth:`.timeit` with increasing numbers from the sequence 1, 2, 5, - 10, 20, 50, ... until the time taken is at least 0.2 seconds. + 10, 20, 50, ... until the time taken is at least *target_time* seconds. If *callback* is given and is not ``None``, it will be called after each trial with two arguments: ``callback(number, time_taken)``. .. versionadded:: 3.6 + .. versionchanged:: next + The optional *target_time* parameter was added. + .. method:: Timer.repeat(repeat=5, number=1000000) @@ -239,6 +242,13 @@ Where the following options are understood: .. versionadded:: 3.5 +.. option:: -t, --target-time=T + + if :option:`--number` is 0, the code will run until it takes at + least this many seconds (default: 0.2) + + .. versionadded:: next + .. option:: -v, --verbose print raw timing results; repeat for more digits precision @@ -254,7 +264,7 @@ similarly. If :option:`-n` is not given, a suitable number of loops is calculated by trying increasing numbers from the sequence 1, 2, 5, 10, 20, 50, ... until the total -time is at least 0.2 seconds. +time is at least :option:`--target-time` seconds (default: 0.2). :func:`default_timer` measurements can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 2a5f9c939e7..287109035f1 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1090,6 +1090,11 @@ timeit :ref:`environment variables `. (Contributed by Yi Hong in :gh:`139374`.) +* Make the target time of :meth:`timeit.Timer.autorange` configurable + and add ``--target-time`` option to the command-line interface. + (Contributed by Alessandro Cucci and Miikka Koskinen in :gh:`140283`.) + + tkinter ------- diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py index f8bc306b455..8837e88ba63 100644 --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -364,10 +364,10 @@ def test_main_exception_fixed_reps(self): s = self.run_main(switches=['-n1', '1/0']) self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError') - def autorange(self, seconds_per_increment=1/1024, callback=None): + def autorange(self, seconds_per_increment=1/1024, callback=None, target_time=0.2): timer = FakeTimer(seconds_per_increment=seconds_per_increment) t = timeit.Timer(stmt=self.fake_stmt, setup=self.fake_setup, timer=timer) - return t.autorange(callback) + return t.autorange(callback, target_time=target_time) def test_autorange(self): num_loops, time_taken = self.autorange() @@ -379,6 +379,11 @@ def test_autorange_second(self): self.assertEqual(num_loops, 1) self.assertEqual(time_taken, 1.0) + def test_autorange_with_target_time(self): + num_loops, time_taken = self.autorange(target_time=1.0) + self.assertEqual(num_loops, 2000) + self.assertEqual(time_taken, 2000/1024) + def test_autorange_with_callback(self): def callback(a, b): print("{} {:.3f}".format(a, b)) diff --git a/Lib/timeit.py b/Lib/timeit.py index 80791acdeca..f900da6ffe7 100644 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -7,7 +7,7 @@ Library usage: see the Timer class. Command line usage: - python timeit.py [-n N] [-r N] [-s S] [-p] [-h] [--] [statement] + python timeit.py [-n N] [-r N] [-s S] [-p] [-h] [-t T] [--] [statement] Options: -n/--number N: how many times to execute 'statement' (default: see below) @@ -17,6 +17,9 @@ -p/--process: use time.process_time() (default is time.perf_counter()) -v/--verbose: print raw timing results; repeat for more digits precision -u/--unit: set the output time unit (nsec, usec, msec, or sec) + -t/--target-time T: if --number is 0 the code will run until it + takes *at least* this many seconds + (default: 0.2) -h/--help: print this usage message and exit --: separate options from statement, use when statement starts with - statement: statement to be timed (default 'pass') @@ -28,7 +31,7 @@ If -n is not given, a suitable number of loops is calculated by trying increasing numbers from the sequence 1, 2, 5, 10, 20, 50, ... until the -total time is at least 0.2 seconds. +total time is at least --target-time seconds. Note: there is a certain baseline overhead associated with executing a pass statement. It differs between versions. The code here doesn't try @@ -57,6 +60,7 @@ default_number = 1000000 default_repeat = 5 default_timer = time.perf_counter +default_target_time = 0.2 _globals = globals @@ -212,12 +216,13 @@ def repeat(self, repeat=default_repeat, number=default_number): r.append(t) return r - def autorange(self, callback=None): - """Return the number of loops and time taken so that total time >= 0.2. + def autorange(self, callback=None, target_time=default_target_time): + """Return the number of loops and time taken so that + total time >= target_time (default is 0.2 seconds). Calls the timeit method with increasing numbers from the sequence - 1, 2, 5, 10, 20, 50, ... until the time taken is at least 0.2 - second. Returns (number, time_taken). + 1, 2, 5, 10, 20, 50, ... until the target time is reached. + Returns (number, time_taken). If *callback* is given and is not None, it will be called after each trial with two arguments: ``callback(number, time_taken)``. @@ -229,7 +234,7 @@ def autorange(self, callback=None): time_taken = self.timeit(number) if callback: callback(number, time_taken) - if time_taken >= 0.2: + if time_taken >= target_time: return (number, time_taken) i *= 10 @@ -270,9 +275,10 @@ def main(args=None, *, _wrap_timer=None): colorize = _colorize.can_colorize() try: - opts, args = getopt.getopt(args, "n:u:s:r:pvh", + opts, args = getopt.getopt(args, "n:u:s:r:pt:vh", ["number=", "setup=", "repeat=", - "process", "verbose", "unit=", "help"]) + "process", "target-time=", + "verbose", "unit=", "help"]) except getopt.error as err: print(err) print("use -h/--help for command line help") @@ -281,6 +287,7 @@ def main(args=None, *, _wrap_timer=None): timer = default_timer stmt = "\n".join(args) or "pass" number = 0 # auto-determine + target_time = default_target_time setup = [] repeat = default_repeat verbose = 0 @@ -305,6 +312,8 @@ def main(args=None, *, _wrap_timer=None): repeat = 1 if o in ("-p", "--process"): timer = time.process_time + if o in ("-t", "--target-time"): + target_time = float(a) if o in ("-v", "--verbose"): if verbose: precision += 1 @@ -324,7 +333,7 @@ def main(args=None, *, _wrap_timer=None): t = Timer(stmt, setup, timer) if number == 0: - # determine number so that 0.2 <= total time < 2.0 + # determine number so that total time >= target_time callback = None if verbose: def callback(number, time_taken): @@ -333,7 +342,7 @@ def callback(number, time_taken): print(msg.format(num=number, s='s' if plural else '', secs=time_taken, prec=precision)) try: - number, _ = t.autorange(callback) + number, _ = t.autorange(callback, target_time) except: t.print_exc(colorize=colorize) return 1 diff --git a/Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst b/Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst new file mode 100644 index 00000000000..e78f6601807 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst @@ -0,0 +1,3 @@ +Make the target time of :meth:`timeit.Timer.autorange` configurable +and add ``--target-time`` option to the command-line interface of +:mod:`timeit`. From 3908593039bde9d4b591ab09919003ee57418d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kul=C3=ADk?= Date: Fri, 3 Apr 2026 10:47:59 +0200 Subject: [PATCH 384/775] test_copy_dir_no_read_permission requires non root user (GH-148028) This fixes a bug introduced in commit 86b8617747699416fcf9cd4ce6ea1da58a66f70e (GH-146195). --- Lib/test/test_pathlib/test_pathlib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py index d346a1a6160..19f4506c109 100644 --- a/Lib/test/test_pathlib/test_pathlib.py +++ b/Lib/test/test_pathlib/test_pathlib.py @@ -21,6 +21,7 @@ from test.support import infinite_recursion from test.support import os_helper from test.support import requires_root_user +from test.support import requires_non_root_user from test.support.os_helper import TESTFN, FS_NONASCII, FakePath try: import fcntl @@ -1550,7 +1551,7 @@ def raiser(*args, **kwargs): self.assertRaises(FileNotFoundError, source.copy, target) @unittest.skipIf(sys.platform == "win32" or sys.platform == "wasi", "directories are always readable on Windows and WASI") - @requires_root_user + @requires_non_root_user def test_copy_dir_no_read_permission(self): base = self.cls(self.base) source = base / 'dirE' From edab6860a7d6c49b5d5762e1c094aa0261245a9c Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Fri, 3 Apr 2026 15:20:50 +0100 Subject: [PATCH 385/775] gh-148022: Add threat model to remote debugging docs (#148024) The remote debugging protocol has been generating spurious vulnerability reports from automated scanners that pattern-match on "remote access" and "memory operations" without understanding the privilege model. This section documents the security boundaries so reporters can self-triage before submitting. The threat model clarifies three points: attaching requires the same OS-level privileges as GDB (ptrace, task_for_pid, or SeDebugPrivilege), crashes caused by reading corrupted target process memory are not security issues, and a compromised target process is out of scope. A subsection explains when operators should use PYTHON_DISABLE_REMOTE_DEBUG for defence-in-depth. --- Doc/howto/remote_debugging.rst | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Doc/howto/remote_debugging.rst b/Doc/howto/remote_debugging.rst index dfe0176b75a..1d5cf24d062 100644 --- a/Doc/howto/remote_debugging.rst +++ b/Doc/howto/remote_debugging.rst @@ -624,3 +624,58 @@ To inject and execute a Python script in a remote process: 6. Set ``_PY_EVAL_PLEASE_STOP_BIT`` in the ``eval_breaker`` field. 7. Resume the process (if suspended). The script will execute at the next safe evaluation point. + +.. _remote-debugging-threat-model: + +Security and threat model +========================= + +The remote debugging protocol relies on the same operating system primitives +used by native debuggers such as GDB and LLDB. Attaching to a process +requires the **same privileges** that those debuggers require, for example +``ptrace`` / Yama LSM on Linux, ``task_for_pid`` on macOS, and +``SeDebugPrivilege`` on Windows. Python does not introduce any new privilege +escalation path; if an attacker already possesses the permissions needed to +attach to a process, they could equally use GDB to read memory or inject +code. + +The following principles define what is, and is not, considered a security +vulnerability in this feature: + +Attaching requires OS-level privileges + On every supported platform the operating system gates cross-process + memory access behind privilege checks (``CAP_SYS_PTRACE``, root, or + administrator rights). A report that demonstrates an issue only after + these privileges have already been obtained is **not** a vulnerability in + CPython, since the OS security boundary was already crossed. + +Crashes or memory errors when reading a compromised process are not vulnerabilities + A tool that reads internal interpreter state from a target process must + trust that memory to be well-formed. If the target process has been + corrupted or is controlled by an attacker, the debugger or profiler may + crash, produce garbage output, or behave unpredictably. This is the same + risk accepted by every ``ptrace``-based debugger. Bugs in this category + (buffer overflows, segmentation faults, or undefined behaviour triggered + by reading corrupted state) are **not** treated as security issues, though + fixes that improve robustness are welcome. + +Vulnerabilities in the target process are not in scope + If the Python process being debugged has already been compromised, the + attacker already controls execution in that process. Demonstrating further + impact from that starting point does not constitute a vulnerability in the + remote debugging protocol. + +When to use ``PYTHON_DISABLE_REMOTE_DEBUG`` +------------------------------------------- + +The environment variable :envvar:`PYTHON_DISABLE_REMOTE_DEBUG` (and the +equivalent :option:`-X disable_remote_debug` flag) allows operators to disable +the in-process side of the protocol as a **defence-in-depth** measure. This +may be useful in hardened or sandboxed deployment environments where no +debugging or profiling of the process is expected and reducing attack surface +is a priority, even though the OS-level privilege checks already prevent +unprivileged access. + +Setting this variable does **not** affect other OS-level debugging interfaces +(``ptrace``, ``/proc``, ``task_for_pid``, etc.), which remain available +according to their own permission models. From 80ab6d958a0e4aa322aaf96994c43cd637496be6 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Fri, 3 Apr 2026 16:19:30 +0100 Subject: [PATCH 386/775] gh-125895: Fix static asset location for `sphinx-notfound-page` (#147984) --- Doc/conf.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Doc/conf.py b/Doc/conf.py index 07e0d113a24..f021c9eabe4 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -572,6 +572,17 @@ stable_abi_file = 'data/stable_abi.dat' threadsafety_file = 'data/threadsafety.dat' +# Options for notfound.extension +# ------------------------------- + +if not os.getenv("READTHEDOCS"): + if language_code: + notfound_urls_prefix = ( + f'/{language_code.replace("_", "-").lower()}/{version}/' + ) + else: + notfound_urls_prefix = f'/{version}/' + # Options for sphinxext-opengraph # ------------------------------- From 48317feec81e1e512ce5ae8292048752782a4fc2 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 3 Apr 2026 17:23:04 +0200 Subject: [PATCH 387/775] gh-146640: Optimize int operations by mutating uniquely-referenced operands in place (JIT only) (GH-146641) --- Include/internal/pycore_uop_ids.h | 2536 +++++++++-------- Include/internal/pycore_uop_metadata.h | 114 + Lib/test/test_capi/test_opt.py | 148 + ...-03-30-20-00-00.gh-issue-146306.C45609.rst | 3 + Python/bytecodes.c | 57 + Python/ceval_macros.h | 43 + Python/executor_cases.c.h | 546 ++++ Python/optimizer_bytecodes.c | 26 +- Python/optimizer_cases.c.h | 120 +- 9 files changed, 2331 insertions(+), 1262 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index dbc7aaab7a7..922fef91fa2 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -16,27 +16,33 @@ extern "C" { #define _BINARY_OP_ADD_FLOAT_INPLACE 304 #define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT 305 #define _BINARY_OP_ADD_INT 306 -#define _BINARY_OP_ADD_UNICODE 307 -#define _BINARY_OP_EXTEND 308 -#define _BINARY_OP_INPLACE_ADD_UNICODE 309 -#define _BINARY_OP_MULTIPLY_FLOAT 310 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE 311 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT 312 -#define _BINARY_OP_MULTIPLY_INT 313 -#define _BINARY_OP_SUBSCR_CHECK_FUNC 314 -#define _BINARY_OP_SUBSCR_DICT 315 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH 316 -#define _BINARY_OP_SUBSCR_INIT_CALL 317 -#define _BINARY_OP_SUBSCR_LIST_INT 318 -#define _BINARY_OP_SUBSCR_LIST_SLICE 319 -#define _BINARY_OP_SUBSCR_STR_INT 320 -#define _BINARY_OP_SUBSCR_TUPLE_INT 321 -#define _BINARY_OP_SUBSCR_USTR_INT 322 -#define _BINARY_OP_SUBTRACT_FLOAT 323 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 324 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 325 -#define _BINARY_OP_SUBTRACT_INT 326 -#define _BINARY_SLICE 327 +#define _BINARY_OP_ADD_INT_INPLACE 307 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT 308 +#define _BINARY_OP_ADD_UNICODE 309 +#define _BINARY_OP_EXTEND 310 +#define _BINARY_OP_INPLACE_ADD_UNICODE 311 +#define _BINARY_OP_MULTIPLY_FLOAT 312 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE 313 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT 314 +#define _BINARY_OP_MULTIPLY_INT 315 +#define _BINARY_OP_MULTIPLY_INT_INPLACE 316 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT 317 +#define _BINARY_OP_SUBSCR_CHECK_FUNC 318 +#define _BINARY_OP_SUBSCR_DICT 319 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH 320 +#define _BINARY_OP_SUBSCR_INIT_CALL 321 +#define _BINARY_OP_SUBSCR_LIST_INT 322 +#define _BINARY_OP_SUBSCR_LIST_SLICE 323 +#define _BINARY_OP_SUBSCR_STR_INT 324 +#define _BINARY_OP_SUBSCR_TUPLE_INT 325 +#define _BINARY_OP_SUBSCR_USTR_INT 326 +#define _BINARY_OP_SUBTRACT_FLOAT 327 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE 328 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT 329 +#define _BINARY_OP_SUBTRACT_INT 330 +#define _BINARY_OP_SUBTRACT_INT_INPLACE 331 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT 332 +#define _BINARY_SLICE 333 #define _BUILD_INTERPOLATION BUILD_INTERPOLATION #define _BUILD_LIST BUILD_LIST #define _BUILD_MAP BUILD_MAP @@ -45,181 +51,181 @@ extern "C" { #define _BUILD_STRING BUILD_STRING #define _BUILD_TEMPLATE BUILD_TEMPLATE #define _BUILD_TUPLE BUILD_TUPLE -#define _CALL_BUILTIN_CLASS 328 -#define _CALL_BUILTIN_FAST 329 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 330 -#define _CALL_BUILTIN_O 331 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL 332 -#define _CALL_INTRINSIC_1 333 -#define _CALL_INTRINSIC_2 334 -#define _CALL_ISINSTANCE 335 -#define _CALL_KW_NON_PY 336 -#define _CALL_LEN 337 -#define _CALL_LIST_APPEND 338 -#define _CALL_METHOD_DESCRIPTOR_FAST 339 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 340 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 341 -#define _CALL_METHOD_DESCRIPTOR_O 342 -#define _CALL_NON_PY_GENERAL 343 -#define _CALL_STR_1 344 -#define _CALL_TUPLE_1 345 -#define _CALL_TYPE_1 346 -#define _CHECK_AND_ALLOCATE_OBJECT 347 -#define _CHECK_ATTR_CLASS 348 -#define _CHECK_ATTR_METHOD_LAZY_DICT 349 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 350 +#define _CALL_BUILTIN_CLASS 334 +#define _CALL_BUILTIN_FAST 335 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 336 +#define _CALL_BUILTIN_O 337 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL 338 +#define _CALL_INTRINSIC_1 339 +#define _CALL_INTRINSIC_2 340 +#define _CALL_ISINSTANCE 341 +#define _CALL_KW_NON_PY 342 +#define _CALL_LEN 343 +#define _CALL_LIST_APPEND 344 +#define _CALL_METHOD_DESCRIPTOR_FAST 345 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 346 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 347 +#define _CALL_METHOD_DESCRIPTOR_O 348 +#define _CALL_NON_PY_GENERAL 349 +#define _CALL_STR_1 350 +#define _CALL_TUPLE_1 351 +#define _CALL_TYPE_1 352 +#define _CHECK_AND_ALLOCATE_OBJECT 353 +#define _CHECK_ATTR_CLASS 354 +#define _CHECK_ATTR_METHOD_LAZY_DICT 355 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 356 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION_EXACT_ARGS 351 -#define _CHECK_FUNCTION_VERSION 352 -#define _CHECK_FUNCTION_VERSION_INLINE 353 -#define _CHECK_FUNCTION_VERSION_KW 354 -#define _CHECK_IS_NOT_PY_CALLABLE 355 -#define _CHECK_IS_NOT_PY_CALLABLE_EX 356 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 357 -#define _CHECK_IS_PY_CALLABLE_EX 358 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 359 -#define _CHECK_METHOD_VERSION 360 -#define _CHECK_METHOD_VERSION_KW 361 -#define _CHECK_PEP_523 362 -#define _CHECK_PERIODIC 363 -#define _CHECK_PERIODIC_AT_END 364 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 365 -#define _CHECK_RECURSION_REMAINING 366 -#define _CHECK_STACK_SPACE 367 -#define _CHECK_STACK_SPACE_OPERAND 368 -#define _CHECK_VALIDITY 369 -#define _COLD_DYNAMIC_EXIT 370 -#define _COLD_EXIT 371 -#define _COMPARE_OP 372 -#define _COMPARE_OP_FLOAT 373 -#define _COMPARE_OP_INT 374 -#define _COMPARE_OP_STR 375 -#define _CONTAINS_OP 376 -#define _CONTAINS_OP_DICT 377 -#define _CONTAINS_OP_SET 378 +#define _CHECK_FUNCTION_EXACT_ARGS 357 +#define _CHECK_FUNCTION_VERSION 358 +#define _CHECK_FUNCTION_VERSION_INLINE 359 +#define _CHECK_FUNCTION_VERSION_KW 360 +#define _CHECK_IS_NOT_PY_CALLABLE 361 +#define _CHECK_IS_NOT_PY_CALLABLE_EX 362 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 363 +#define _CHECK_IS_PY_CALLABLE_EX 364 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 365 +#define _CHECK_METHOD_VERSION 366 +#define _CHECK_METHOD_VERSION_KW 367 +#define _CHECK_PEP_523 368 +#define _CHECK_PERIODIC 369 +#define _CHECK_PERIODIC_AT_END 370 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 371 +#define _CHECK_RECURSION_REMAINING 372 +#define _CHECK_STACK_SPACE 373 +#define _CHECK_STACK_SPACE_OPERAND 374 +#define _CHECK_VALIDITY 375 +#define _COLD_DYNAMIC_EXIT 376 +#define _COLD_EXIT 377 +#define _COMPARE_OP 378 +#define _COMPARE_OP_FLOAT 379 +#define _COMPARE_OP_INT 380 +#define _COMPARE_OP_STR 381 +#define _CONTAINS_OP 382 +#define _CONTAINS_OP_DICT 383 +#define _CONTAINS_OP_SET 384 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 379 -#define _COPY_1 380 -#define _COPY_2 381 -#define _COPY_3 382 +#define _COPY 385 +#define _COPY_1 386 +#define _COPY_2 387 +#define _COPY_3 388 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 383 +#define _CREATE_INIT_FRAME 389 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 384 -#define _DICT_MERGE 385 -#define _DICT_UPDATE 386 -#define _DO_CALL 387 -#define _DO_CALL_FUNCTION_EX 388 -#define _DO_CALL_KW 389 -#define _DYNAMIC_EXIT 390 +#define _DEOPT 390 +#define _DICT_MERGE 391 +#define _DICT_UPDATE 392 +#define _DO_CALL 393 +#define _DO_CALL_FUNCTION_EX 394 +#define _DO_CALL_KW 395 +#define _DYNAMIC_EXIT 396 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 391 +#define _ERROR_POP_N 397 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 392 -#define _EXPAND_METHOD_KW 393 -#define _FATAL_ERROR 394 +#define _EXPAND_METHOD 398 +#define _EXPAND_METHOD_KW 399 +#define _FATAL_ERROR 400 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 395 -#define _FOR_ITER_GEN_FRAME 396 -#define _FOR_ITER_TIER_TWO 397 +#define _FOR_ITER 401 +#define _FOR_ITER_GEN_FRAME 402 +#define _FOR_ITER_TIER_TWO 403 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN -#define _GUARD_BINARY_OP_EXTEND 398 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 399 -#define _GUARD_BIT_IS_SET_POP 400 -#define _GUARD_BIT_IS_SET_POP_4 401 -#define _GUARD_BIT_IS_SET_POP_5 402 -#define _GUARD_BIT_IS_SET_POP_6 403 -#define _GUARD_BIT_IS_SET_POP_7 404 -#define _GUARD_BIT_IS_UNSET_POP 405 -#define _GUARD_BIT_IS_UNSET_POP_4 406 -#define _GUARD_BIT_IS_UNSET_POP_5 407 -#define _GUARD_BIT_IS_UNSET_POP_6 408 -#define _GUARD_BIT_IS_UNSET_POP_7 409 -#define _GUARD_CALLABLE_BUILTIN_FAST 410 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 411 -#define _GUARD_CALLABLE_BUILTIN_O 412 -#define _GUARD_CALLABLE_ISINSTANCE 413 -#define _GUARD_CALLABLE_LEN 414 -#define _GUARD_CALLABLE_LIST_APPEND 415 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 416 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 417 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 418 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 419 -#define _GUARD_CALLABLE_STR_1 420 -#define _GUARD_CALLABLE_TUPLE_1 421 -#define _GUARD_CALLABLE_TYPE_1 422 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR 423 -#define _GUARD_CODE_VERSION_RETURN_VALUE 424 -#define _GUARD_CODE_VERSION_YIELD_VALUE 425 -#define _GUARD_CODE_VERSION__PUSH_FRAME 426 -#define _GUARD_DORV_NO_DICT 427 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 428 -#define _GUARD_GLOBALS_VERSION 429 -#define _GUARD_IP_RETURN_GENERATOR 430 -#define _GUARD_IP_RETURN_VALUE 431 -#define _GUARD_IP_YIELD_VALUE 432 -#define _GUARD_IP__PUSH_FRAME 433 -#define _GUARD_IS_FALSE_POP 434 -#define _GUARD_IS_NONE_POP 435 -#define _GUARD_IS_NOT_NONE_POP 436 -#define _GUARD_IS_TRUE_POP 437 -#define _GUARD_KEYS_VERSION 438 -#define _GUARD_NOS_ANY_DICT 439 -#define _GUARD_NOS_COMPACT_ASCII 440 -#define _GUARD_NOS_DICT 441 -#define _GUARD_NOS_FLOAT 442 -#define _GUARD_NOS_INT 443 -#define _GUARD_NOS_LIST 444 -#define _GUARD_NOS_NOT_NULL 445 -#define _GUARD_NOS_NULL 446 -#define _GUARD_NOS_OVERFLOWED 447 -#define _GUARD_NOS_TUPLE 448 -#define _GUARD_NOS_UNICODE 449 -#define _GUARD_NOT_EXHAUSTED_LIST 450 -#define _GUARD_NOT_EXHAUSTED_RANGE 451 -#define _GUARD_NOT_EXHAUSTED_TUPLE 452 -#define _GUARD_THIRD_NULL 453 -#define _GUARD_TOS_ANY_DICT 454 -#define _GUARD_TOS_ANY_SET 455 -#define _GUARD_TOS_DICT 456 -#define _GUARD_TOS_FLOAT 457 -#define _GUARD_TOS_FROZENDICT 458 -#define _GUARD_TOS_FROZENSET 459 -#define _GUARD_TOS_INT 460 -#define _GUARD_TOS_LIST 461 -#define _GUARD_TOS_OVERFLOWED 462 -#define _GUARD_TOS_SET 463 -#define _GUARD_TOS_SLICE 464 -#define _GUARD_TOS_TUPLE 465 -#define _GUARD_TOS_UNICODE 466 -#define _GUARD_TYPE_VERSION 467 -#define _GUARD_TYPE_VERSION_LOCKED 468 -#define _HANDLE_PENDING_AND_DEOPT 469 +#define _GUARD_BINARY_OP_EXTEND 404 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 405 +#define _GUARD_BIT_IS_SET_POP 406 +#define _GUARD_BIT_IS_SET_POP_4 407 +#define _GUARD_BIT_IS_SET_POP_5 408 +#define _GUARD_BIT_IS_SET_POP_6 409 +#define _GUARD_BIT_IS_SET_POP_7 410 +#define _GUARD_BIT_IS_UNSET_POP 411 +#define _GUARD_BIT_IS_UNSET_POP_4 412 +#define _GUARD_BIT_IS_UNSET_POP_5 413 +#define _GUARD_BIT_IS_UNSET_POP_6 414 +#define _GUARD_BIT_IS_UNSET_POP_7 415 +#define _GUARD_CALLABLE_BUILTIN_FAST 416 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 417 +#define _GUARD_CALLABLE_BUILTIN_O 418 +#define _GUARD_CALLABLE_ISINSTANCE 419 +#define _GUARD_CALLABLE_LEN 420 +#define _GUARD_CALLABLE_LIST_APPEND 421 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 422 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 423 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 424 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 425 +#define _GUARD_CALLABLE_STR_1 426 +#define _GUARD_CALLABLE_TUPLE_1 427 +#define _GUARD_CALLABLE_TYPE_1 428 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR 429 +#define _GUARD_CODE_VERSION_RETURN_VALUE 430 +#define _GUARD_CODE_VERSION_YIELD_VALUE 431 +#define _GUARD_CODE_VERSION__PUSH_FRAME 432 +#define _GUARD_DORV_NO_DICT 433 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 434 +#define _GUARD_GLOBALS_VERSION 435 +#define _GUARD_IP_RETURN_GENERATOR 436 +#define _GUARD_IP_RETURN_VALUE 437 +#define _GUARD_IP_YIELD_VALUE 438 +#define _GUARD_IP__PUSH_FRAME 439 +#define _GUARD_IS_FALSE_POP 440 +#define _GUARD_IS_NONE_POP 441 +#define _GUARD_IS_NOT_NONE_POP 442 +#define _GUARD_IS_TRUE_POP 443 +#define _GUARD_KEYS_VERSION 444 +#define _GUARD_NOS_ANY_DICT 445 +#define _GUARD_NOS_COMPACT_ASCII 446 +#define _GUARD_NOS_DICT 447 +#define _GUARD_NOS_FLOAT 448 +#define _GUARD_NOS_INT 449 +#define _GUARD_NOS_LIST 450 +#define _GUARD_NOS_NOT_NULL 451 +#define _GUARD_NOS_NULL 452 +#define _GUARD_NOS_OVERFLOWED 453 +#define _GUARD_NOS_TUPLE 454 +#define _GUARD_NOS_UNICODE 455 +#define _GUARD_NOT_EXHAUSTED_LIST 456 +#define _GUARD_NOT_EXHAUSTED_RANGE 457 +#define _GUARD_NOT_EXHAUSTED_TUPLE 458 +#define _GUARD_THIRD_NULL 459 +#define _GUARD_TOS_ANY_DICT 460 +#define _GUARD_TOS_ANY_SET 461 +#define _GUARD_TOS_DICT 462 +#define _GUARD_TOS_FLOAT 463 +#define _GUARD_TOS_FROZENDICT 464 +#define _GUARD_TOS_FROZENSET 465 +#define _GUARD_TOS_INT 466 +#define _GUARD_TOS_LIST 467 +#define _GUARD_TOS_OVERFLOWED 468 +#define _GUARD_TOS_SET 469 +#define _GUARD_TOS_SLICE 470 +#define _GUARD_TOS_TUPLE 471 +#define _GUARD_TOS_UNICODE 472 +#define _GUARD_TYPE_VERSION 473 +#define _GUARD_TYPE_VERSION_LOCKED 474 +#define _HANDLE_PENDING_AND_DEOPT 475 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 470 -#define _INIT_CALL_PY_EXACT_ARGS 471 -#define _INIT_CALL_PY_EXACT_ARGS_0 472 -#define _INIT_CALL_PY_EXACT_ARGS_1 473 -#define _INIT_CALL_PY_EXACT_ARGS_2 474 -#define _INIT_CALL_PY_EXACT_ARGS_3 475 -#define _INIT_CALL_PY_EXACT_ARGS_4 476 -#define _INSERT_1_LOAD_CONST_INLINE 477 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 478 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 479 -#define _INSERT_NULL 480 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 476 +#define _INIT_CALL_PY_EXACT_ARGS 477 +#define _INIT_CALL_PY_EXACT_ARGS_0 478 +#define _INIT_CALL_PY_EXACT_ARGS_1 479 +#define _INIT_CALL_PY_EXACT_ARGS_2 480 +#define _INIT_CALL_PY_EXACT_ARGS_3 481 +#define _INIT_CALL_PY_EXACT_ARGS_4 482 +#define _INSERT_1_LOAD_CONST_INLINE 483 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW 484 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW 485 +#define _INSERT_NULL 486 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -229,1128 +235,1146 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 481 -#define _IS_OP 482 -#define _ITER_CHECK_LIST 483 -#define _ITER_CHECK_RANGE 484 -#define _ITER_CHECK_TUPLE 485 -#define _ITER_JUMP_LIST 486 -#define _ITER_JUMP_RANGE 487 -#define _ITER_JUMP_TUPLE 488 -#define _ITER_NEXT_LIST 489 -#define _ITER_NEXT_LIST_TIER_TWO 490 -#define _ITER_NEXT_RANGE 491 -#define _ITER_NEXT_TUPLE 492 +#define _IS_NONE 487 +#define _IS_OP 488 +#define _ITER_CHECK_LIST 489 +#define _ITER_CHECK_RANGE 490 +#define _ITER_CHECK_TUPLE 491 +#define _ITER_JUMP_LIST 492 +#define _ITER_JUMP_RANGE 493 +#define _ITER_JUMP_TUPLE 494 +#define _ITER_NEXT_LIST 495 +#define _ITER_NEXT_LIST_TIER_TWO 496 +#define _ITER_NEXT_RANGE 497 +#define _ITER_NEXT_TUPLE 498 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 493 +#define _JUMP_TO_TOP 499 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND 494 -#define _LOAD_ATTR 495 -#define _LOAD_ATTR_CLASS 496 +#define _LIST_EXTEND 500 +#define _LOAD_ATTR 501 +#define _LOAD_ATTR_CLASS 502 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 497 -#define _LOAD_ATTR_METHOD_LAZY_DICT 498 -#define _LOAD_ATTR_METHOD_NO_DICT 499 -#define _LOAD_ATTR_METHOD_WITH_VALUES 500 -#define _LOAD_ATTR_MODULE 501 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 502 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 503 -#define _LOAD_ATTR_PROPERTY_FRAME 504 -#define _LOAD_ATTR_SLOT 505 -#define _LOAD_ATTR_WITH_HINT 506 +#define _LOAD_ATTR_INSTANCE_VALUE 503 +#define _LOAD_ATTR_METHOD_LAZY_DICT 504 +#define _LOAD_ATTR_METHOD_NO_DICT 505 +#define _LOAD_ATTR_METHOD_WITH_VALUES 506 +#define _LOAD_ATTR_MODULE 507 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 508 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 509 +#define _LOAD_ATTR_PROPERTY_FRAME 510 +#define _LOAD_ATTR_SLOT 511 +#define _LOAD_ATTR_WITH_HINT 512 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 507 +#define _LOAD_BYTECODE 513 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 508 -#define _LOAD_CONST_INLINE_BORROW 509 -#define _LOAD_CONST_UNDER_INLINE 510 -#define _LOAD_CONST_UNDER_INLINE_BORROW 511 +#define _LOAD_CONST_INLINE 514 +#define _LOAD_CONST_INLINE_BORROW 515 +#define _LOAD_CONST_UNDER_INLINE 516 +#define _LOAD_CONST_UNDER_INLINE_BORROW 517 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 512 -#define _LOAD_FAST_0 513 -#define _LOAD_FAST_1 514 -#define _LOAD_FAST_2 515 -#define _LOAD_FAST_3 516 -#define _LOAD_FAST_4 517 -#define _LOAD_FAST_5 518 -#define _LOAD_FAST_6 519 -#define _LOAD_FAST_7 520 +#define _LOAD_FAST 518 +#define _LOAD_FAST_0 519 +#define _LOAD_FAST_1 520 +#define _LOAD_FAST_2 521 +#define _LOAD_FAST_3 522 +#define _LOAD_FAST_4 523 +#define _LOAD_FAST_5 524 +#define _LOAD_FAST_6 525 +#define _LOAD_FAST_7 526 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 521 -#define _LOAD_FAST_BORROW_0 522 -#define _LOAD_FAST_BORROW_1 523 -#define _LOAD_FAST_BORROW_2 524 -#define _LOAD_FAST_BORROW_3 525 -#define _LOAD_FAST_BORROW_4 526 -#define _LOAD_FAST_BORROW_5 527 -#define _LOAD_FAST_BORROW_6 528 -#define _LOAD_FAST_BORROW_7 529 +#define _LOAD_FAST_BORROW 527 +#define _LOAD_FAST_BORROW_0 528 +#define _LOAD_FAST_BORROW_1 529 +#define _LOAD_FAST_BORROW_2 530 +#define _LOAD_FAST_BORROW_3 531 +#define _LOAD_FAST_BORROW_4 532 +#define _LOAD_FAST_BORROW_5 533 +#define _LOAD_FAST_BORROW_6 534 +#define _LOAD_FAST_BORROW_7 535 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 530 -#define _LOAD_GLOBAL_BUILTINS 531 -#define _LOAD_GLOBAL_MODULE 532 +#define _LOAD_GLOBAL 536 +#define _LOAD_GLOBAL_BUILTINS 537 +#define _LOAD_GLOBAL_MODULE 538 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 533 -#define _LOAD_SMALL_INT_0 534 -#define _LOAD_SMALL_INT_1 535 -#define _LOAD_SMALL_INT_2 536 -#define _LOAD_SMALL_INT_3 537 -#define _LOAD_SPECIAL 538 +#define _LOAD_SMALL_INT 539 +#define _LOAD_SMALL_INT_0 540 +#define _LOAD_SMALL_INT_1 541 +#define _LOAD_SMALL_INT_2 542 +#define _LOAD_SMALL_INT_3 543 +#define _LOAD_SPECIAL 544 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _LOCK_OBJECT 539 -#define _MAKE_CALLARGS_A_TUPLE 540 +#define _LOCK_OBJECT 545 +#define _MAKE_CALLARGS_A_TUPLE 546 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_HEAP_SAFE 541 -#define _MAKE_WARM 542 +#define _MAKE_HEAP_SAFE 547 +#define _MAKE_WARM 548 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 543 +#define _MATCH_CLASS 549 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 544 -#define _MAYBE_EXPAND_METHOD_KW 545 -#define _MONITOR_CALL 546 -#define _MONITOR_CALL_KW 547 -#define _MONITOR_JUMP_BACKWARD 548 -#define _MONITOR_RESUME 549 +#define _MAYBE_EXPAND_METHOD 550 +#define _MAYBE_EXPAND_METHOD_KW 551 +#define _MONITOR_CALL 552 +#define _MONITOR_CALL_KW 553 +#define _MONITOR_JUMP_BACKWARD 554 +#define _MONITOR_RESUME 555 #define _NOP NOP -#define _POP_CALL 550 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 551 -#define _POP_CALL_ONE 552 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 553 -#define _POP_CALL_TWO 554 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 555 +#define _POP_CALL 556 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 557 +#define _POP_CALL_ONE 558 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 559 +#define _POP_CALL_TWO 560 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 561 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 556 -#define _POP_JUMP_IF_TRUE 557 +#define _POP_JUMP_IF_FALSE 562 +#define _POP_JUMP_IF_TRUE 563 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 558 -#define _POP_TOP_INT 559 -#define _POP_TOP_LOAD_CONST_INLINE 560 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 561 -#define _POP_TOP_NOP 562 -#define _POP_TOP_UNICODE 563 -#define _POP_TWO 564 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 565 +#define _POP_TOP_FLOAT 564 +#define _POP_TOP_INT 565 +#define _POP_TOP_LOAD_CONST_INLINE 566 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 567 +#define _POP_TOP_NOP 568 +#define _POP_TOP_UNICODE 569 +#define _POP_TWO 570 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 571 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 566 +#define _PUSH_FRAME 572 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 567 -#define _PY_FRAME_EX 568 -#define _PY_FRAME_GENERAL 569 -#define _PY_FRAME_KW 570 -#define _RECORD_3OS_GEN_FUNC 571 -#define _RECORD_4OS 572 -#define _RECORD_BOUND_METHOD 573 -#define _RECORD_CALLABLE 574 -#define _RECORD_CODE 575 -#define _RECORD_NOS 576 -#define _RECORD_NOS_GEN_FUNC 577 -#define _RECORD_TOS 578 -#define _RECORD_TOS_TYPE 579 -#define _REPLACE_WITH_TRUE 580 -#define _RESUME_CHECK 581 +#define _PUSH_NULL_CONDITIONAL 573 +#define _PY_FRAME_EX 574 +#define _PY_FRAME_GENERAL 575 +#define _PY_FRAME_KW 576 +#define _RECORD_3OS_GEN_FUNC 577 +#define _RECORD_4OS 578 +#define _RECORD_BOUND_METHOD 579 +#define _RECORD_CALLABLE 580 +#define _RECORD_CODE 581 +#define _RECORD_NOS 582 +#define _RECORD_NOS_GEN_FUNC 583 +#define _RECORD_TOS 584 +#define _RECORD_TOS_TYPE 585 +#define _REPLACE_WITH_TRUE 586 +#define _RESUME_CHECK 587 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 582 -#define _SAVE_RETURN_OFFSET 583 -#define _SEND 584 -#define _SEND_GEN_FRAME 585 +#define _RETURN_VALUE 588 +#define _SAVE_RETURN_OFFSET 589 +#define _SEND 590 +#define _SEND_GEN_FRAME 591 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 586 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 587 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 588 -#define _SPILL_OR_RELOAD 589 -#define _START_EXECUTOR 590 -#define _STORE_ATTR 591 -#define _STORE_ATTR_INSTANCE_VALUE 592 -#define _STORE_ATTR_SLOT 593 -#define _STORE_ATTR_WITH_HINT 594 +#define _SET_UPDATE 592 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 593 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 594 +#define _SPILL_OR_RELOAD 595 +#define _START_EXECUTOR 596 +#define _STORE_ATTR 597 +#define _STORE_ATTR_INSTANCE_VALUE 598 +#define _STORE_ATTR_SLOT 599 +#define _STORE_ATTR_WITH_HINT 600 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 595 -#define _STORE_SUBSCR 596 -#define _STORE_SUBSCR_DICT 597 -#define _STORE_SUBSCR_DICT_KNOWN_HASH 598 -#define _STORE_SUBSCR_LIST_INT 599 -#define _SWAP 600 -#define _SWAP_2 601 -#define _SWAP_3 602 -#define _SWAP_FAST 603 -#define _SWAP_FAST_0 604 -#define _SWAP_FAST_1 605 -#define _SWAP_FAST_2 606 -#define _SWAP_FAST_3 607 -#define _SWAP_FAST_4 608 -#define _SWAP_FAST_5 609 -#define _SWAP_FAST_6 610 -#define _SWAP_FAST_7 611 -#define _TIER2_RESUME_CHECK 612 -#define _TO_BOOL 613 +#define _STORE_SLICE 601 +#define _STORE_SUBSCR 602 +#define _STORE_SUBSCR_DICT 603 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 604 +#define _STORE_SUBSCR_LIST_INT 605 +#define _SWAP 606 +#define _SWAP_2 607 +#define _SWAP_3 608 +#define _SWAP_FAST 609 +#define _SWAP_FAST_0 610 +#define _SWAP_FAST_1 611 +#define _SWAP_FAST_2 612 +#define _SWAP_FAST_3 613 +#define _SWAP_FAST_4 614 +#define _SWAP_FAST_5 615 +#define _SWAP_FAST_6 616 +#define _SWAP_FAST_7 617 +#define _TIER2_RESUME_CHECK 618 +#define _TO_BOOL 619 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 614 -#define _TO_BOOL_LIST 615 +#define _TO_BOOL_INT 620 +#define _TO_BOOL_LIST 621 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 616 +#define _TO_BOOL_STR 622 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 617 -#define _UNARY_NEGATIVE 618 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 619 +#define _UNARY_INVERT 623 +#define _UNARY_NEGATIVE 624 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 625 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 620 -#define _UNPACK_SEQUENCE_LIST 621 -#define _UNPACK_SEQUENCE_TUPLE 622 -#define _UNPACK_SEQUENCE_TWO_TUPLE 623 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 624 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 625 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 626 +#define _UNPACK_SEQUENCE 626 +#define _UNPACK_SEQUENCE_LIST 627 +#define _UNPACK_SEQUENCE_TUPLE 628 +#define _UNPACK_SEQUENCE_TWO_TUPLE 629 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 630 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 631 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 632 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 627 -#define MAX_UOP_ID 627 -#define _BINARY_OP_r23 628 -#define _BINARY_OP_ADD_FLOAT_r03 629 -#define _BINARY_OP_ADD_FLOAT_r13 630 -#define _BINARY_OP_ADD_FLOAT_r23 631 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 632 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 633 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 634 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 635 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 636 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 637 -#define _BINARY_OP_ADD_INT_r03 638 -#define _BINARY_OP_ADD_INT_r13 639 -#define _BINARY_OP_ADD_INT_r23 640 -#define _BINARY_OP_ADD_UNICODE_r03 641 -#define _BINARY_OP_ADD_UNICODE_r13 642 -#define _BINARY_OP_ADD_UNICODE_r23 643 -#define _BINARY_OP_EXTEND_r23 644 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 645 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 646 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 647 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 648 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 649 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 650 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 651 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 652 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 653 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 654 -#define _BINARY_OP_MULTIPLY_INT_r03 655 -#define _BINARY_OP_MULTIPLY_INT_r13 656 -#define _BINARY_OP_MULTIPLY_INT_r23 657 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 658 -#define _BINARY_OP_SUBSCR_DICT_r23 659 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 660 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 661 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 662 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 663 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 664 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 665 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 666 -#define _BINARY_OP_SUBSCR_STR_INT_r23 667 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 668 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 669 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 670 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 671 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 672 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 673 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 674 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 675 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 676 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 677 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 678 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 679 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 680 -#define _BINARY_OP_SUBTRACT_INT_r03 681 -#define _BINARY_OP_SUBTRACT_INT_r13 682 -#define _BINARY_OP_SUBTRACT_INT_r23 683 -#define _BINARY_SLICE_r31 684 -#define _BUILD_INTERPOLATION_r01 685 -#define _BUILD_LIST_r01 686 -#define _BUILD_MAP_r01 687 -#define _BUILD_SET_r01 688 -#define _BUILD_SLICE_r01 689 -#define _BUILD_STRING_r01 690 -#define _BUILD_TEMPLATE_r21 691 -#define _BUILD_TUPLE_r01 692 -#define _CALL_BUILTIN_CLASS_r01 693 -#define _CALL_BUILTIN_FAST_r01 694 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 695 -#define _CALL_BUILTIN_O_r03 696 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 697 -#define _CALL_INTRINSIC_1_r12 698 -#define _CALL_INTRINSIC_2_r23 699 -#define _CALL_ISINSTANCE_r31 700 -#define _CALL_KW_NON_PY_r11 701 -#define _CALL_LEN_r33 702 -#define _CALL_LIST_APPEND_r03 703 -#define _CALL_LIST_APPEND_r13 704 -#define _CALL_LIST_APPEND_r23 705 -#define _CALL_LIST_APPEND_r33 706 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 707 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 708 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 709 -#define _CALL_METHOD_DESCRIPTOR_O_r03 710 -#define _CALL_NON_PY_GENERAL_r01 711 -#define _CALL_STR_1_r32 712 -#define _CALL_TUPLE_1_r32 713 -#define _CALL_TYPE_1_r02 714 -#define _CALL_TYPE_1_r12 715 -#define _CALL_TYPE_1_r22 716 -#define _CALL_TYPE_1_r32 717 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 718 -#define _CHECK_ATTR_CLASS_r01 719 -#define _CHECK_ATTR_CLASS_r11 720 -#define _CHECK_ATTR_CLASS_r22 721 -#define _CHECK_ATTR_CLASS_r33 722 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 723 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 724 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 725 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 726 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 727 -#define _CHECK_EG_MATCH_r22 728 -#define _CHECK_EXC_MATCH_r22 729 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 730 -#define _CHECK_FUNCTION_VERSION_r00 731 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 732 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 733 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 734 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 735 -#define _CHECK_FUNCTION_VERSION_KW_r11 736 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 737 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 738 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 739 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 740 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 741 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 742 -#define _CHECK_IS_PY_CALLABLE_EX_r03 743 -#define _CHECK_IS_PY_CALLABLE_EX_r13 744 -#define _CHECK_IS_PY_CALLABLE_EX_r23 745 -#define _CHECK_IS_PY_CALLABLE_EX_r33 746 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 747 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 748 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 749 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 750 -#define _CHECK_METHOD_VERSION_r00 751 -#define _CHECK_METHOD_VERSION_KW_r11 752 -#define _CHECK_PEP_523_r00 753 -#define _CHECK_PEP_523_r11 754 -#define _CHECK_PEP_523_r22 755 -#define _CHECK_PEP_523_r33 756 -#define _CHECK_PERIODIC_r00 757 -#define _CHECK_PERIODIC_AT_END_r00 758 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 759 -#define _CHECK_RECURSION_REMAINING_r00 760 -#define _CHECK_RECURSION_REMAINING_r11 761 -#define _CHECK_RECURSION_REMAINING_r22 762 -#define _CHECK_RECURSION_REMAINING_r33 763 -#define _CHECK_STACK_SPACE_r00 764 -#define _CHECK_STACK_SPACE_OPERAND_r00 765 -#define _CHECK_STACK_SPACE_OPERAND_r11 766 -#define _CHECK_STACK_SPACE_OPERAND_r22 767 -#define _CHECK_STACK_SPACE_OPERAND_r33 768 -#define _CHECK_VALIDITY_r00 769 -#define _CHECK_VALIDITY_r11 770 -#define _CHECK_VALIDITY_r22 771 -#define _CHECK_VALIDITY_r33 772 -#define _COLD_DYNAMIC_EXIT_r00 773 -#define _COLD_EXIT_r00 774 -#define _COMPARE_OP_r21 775 -#define _COMPARE_OP_FLOAT_r03 776 -#define _COMPARE_OP_FLOAT_r13 777 -#define _COMPARE_OP_FLOAT_r23 778 -#define _COMPARE_OP_INT_r23 779 -#define _COMPARE_OP_STR_r23 780 -#define _CONTAINS_OP_r23 781 -#define _CONTAINS_OP_DICT_r23 782 -#define _CONTAINS_OP_SET_r23 783 -#define _CONVERT_VALUE_r11 784 -#define _COPY_r01 785 -#define _COPY_1_r02 786 -#define _COPY_1_r12 787 -#define _COPY_1_r23 788 -#define _COPY_2_r03 789 -#define _COPY_2_r13 790 -#define _COPY_2_r23 791 -#define _COPY_3_r03 792 -#define _COPY_3_r13 793 -#define _COPY_3_r23 794 -#define _COPY_3_r33 795 -#define _COPY_FREE_VARS_r00 796 -#define _COPY_FREE_VARS_r11 797 -#define _COPY_FREE_VARS_r22 798 -#define _COPY_FREE_VARS_r33 799 -#define _CREATE_INIT_FRAME_r01 800 -#define _DELETE_ATTR_r10 801 -#define _DELETE_DEREF_r00 802 -#define _DELETE_FAST_r00 803 -#define _DELETE_GLOBAL_r00 804 -#define _DELETE_NAME_r00 805 -#define _DELETE_SUBSCR_r20 806 -#define _DEOPT_r00 807 -#define _DEOPT_r10 808 -#define _DEOPT_r20 809 -#define _DEOPT_r30 810 -#define _DICT_MERGE_r11 811 -#define _DICT_UPDATE_r11 812 -#define _DO_CALL_r01 813 -#define _DO_CALL_FUNCTION_EX_r31 814 -#define _DO_CALL_KW_r11 815 -#define _DYNAMIC_EXIT_r00 816 -#define _DYNAMIC_EXIT_r10 817 -#define _DYNAMIC_EXIT_r20 818 -#define _DYNAMIC_EXIT_r30 819 -#define _END_FOR_r10 820 -#define _END_SEND_r31 821 -#define _ERROR_POP_N_r00 822 -#define _EXIT_INIT_CHECK_r10 823 -#define _EXIT_TRACE_r00 824 -#define _EXIT_TRACE_r10 825 -#define _EXIT_TRACE_r20 826 -#define _EXIT_TRACE_r30 827 -#define _EXPAND_METHOD_r00 828 -#define _EXPAND_METHOD_KW_r11 829 -#define _FATAL_ERROR_r00 830 -#define _FATAL_ERROR_r11 831 -#define _FATAL_ERROR_r22 832 -#define _FATAL_ERROR_r33 833 -#define _FORMAT_SIMPLE_r11 834 -#define _FORMAT_WITH_SPEC_r21 835 -#define _FOR_ITER_r23 836 -#define _FOR_ITER_GEN_FRAME_r03 837 -#define _FOR_ITER_GEN_FRAME_r13 838 -#define _FOR_ITER_GEN_FRAME_r23 839 -#define _FOR_ITER_TIER_TWO_r23 840 -#define _GET_AITER_r11 841 -#define _GET_ANEXT_r12 842 -#define _GET_AWAITABLE_r11 843 -#define _GET_ITER_r12 844 -#define _GET_LEN_r12 845 -#define _GUARD_BINARY_OP_EXTEND_r22 846 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 847 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 848 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 849 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 850 -#define _GUARD_BIT_IS_SET_POP_r00 851 -#define _GUARD_BIT_IS_SET_POP_r10 852 -#define _GUARD_BIT_IS_SET_POP_r21 853 -#define _GUARD_BIT_IS_SET_POP_r32 854 -#define _GUARD_BIT_IS_SET_POP_4_r00 855 -#define _GUARD_BIT_IS_SET_POP_4_r10 856 -#define _GUARD_BIT_IS_SET_POP_4_r21 857 -#define _GUARD_BIT_IS_SET_POP_4_r32 858 -#define _GUARD_BIT_IS_SET_POP_5_r00 859 -#define _GUARD_BIT_IS_SET_POP_5_r10 860 -#define _GUARD_BIT_IS_SET_POP_5_r21 861 -#define _GUARD_BIT_IS_SET_POP_5_r32 862 -#define _GUARD_BIT_IS_SET_POP_6_r00 863 -#define _GUARD_BIT_IS_SET_POP_6_r10 864 -#define _GUARD_BIT_IS_SET_POP_6_r21 865 -#define _GUARD_BIT_IS_SET_POP_6_r32 866 -#define _GUARD_BIT_IS_SET_POP_7_r00 867 -#define _GUARD_BIT_IS_SET_POP_7_r10 868 -#define _GUARD_BIT_IS_SET_POP_7_r21 869 -#define _GUARD_BIT_IS_SET_POP_7_r32 870 -#define _GUARD_BIT_IS_UNSET_POP_r00 871 -#define _GUARD_BIT_IS_UNSET_POP_r10 872 -#define _GUARD_BIT_IS_UNSET_POP_r21 873 -#define _GUARD_BIT_IS_UNSET_POP_r32 874 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 875 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 876 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 877 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 878 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 879 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 880 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 881 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 882 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 883 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 884 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 885 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 886 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 887 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 888 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 889 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 890 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 891 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 892 -#define _GUARD_CALLABLE_BUILTIN_O_r00 893 -#define _GUARD_CALLABLE_ISINSTANCE_r03 894 -#define _GUARD_CALLABLE_ISINSTANCE_r13 895 -#define _GUARD_CALLABLE_ISINSTANCE_r23 896 -#define _GUARD_CALLABLE_ISINSTANCE_r33 897 -#define _GUARD_CALLABLE_LEN_r03 898 -#define _GUARD_CALLABLE_LEN_r13 899 -#define _GUARD_CALLABLE_LEN_r23 900 -#define _GUARD_CALLABLE_LEN_r33 901 -#define _GUARD_CALLABLE_LIST_APPEND_r03 902 -#define _GUARD_CALLABLE_LIST_APPEND_r13 903 -#define _GUARD_CALLABLE_LIST_APPEND_r23 904 -#define _GUARD_CALLABLE_LIST_APPEND_r33 905 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 906 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 907 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 908 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 909 -#define _GUARD_CALLABLE_STR_1_r03 910 -#define _GUARD_CALLABLE_STR_1_r13 911 -#define _GUARD_CALLABLE_STR_1_r23 912 -#define _GUARD_CALLABLE_STR_1_r33 913 -#define _GUARD_CALLABLE_TUPLE_1_r03 914 -#define _GUARD_CALLABLE_TUPLE_1_r13 915 -#define _GUARD_CALLABLE_TUPLE_1_r23 916 -#define _GUARD_CALLABLE_TUPLE_1_r33 917 -#define _GUARD_CALLABLE_TYPE_1_r03 918 -#define _GUARD_CALLABLE_TYPE_1_r13 919 -#define _GUARD_CALLABLE_TYPE_1_r23 920 -#define _GUARD_CALLABLE_TYPE_1_r33 921 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 922 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 923 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 924 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 925 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 926 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 927 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 928 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 929 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 930 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 931 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 932 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 933 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 934 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 935 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 936 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 937 -#define _GUARD_DORV_NO_DICT_r01 938 -#define _GUARD_DORV_NO_DICT_r11 939 -#define _GUARD_DORV_NO_DICT_r22 940 -#define _GUARD_DORV_NO_DICT_r33 941 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 942 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 943 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 944 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 945 -#define _GUARD_GLOBALS_VERSION_r00 946 -#define _GUARD_GLOBALS_VERSION_r11 947 -#define _GUARD_GLOBALS_VERSION_r22 948 -#define _GUARD_GLOBALS_VERSION_r33 949 -#define _GUARD_IP_RETURN_GENERATOR_r00 950 -#define _GUARD_IP_RETURN_GENERATOR_r11 951 -#define _GUARD_IP_RETURN_GENERATOR_r22 952 -#define _GUARD_IP_RETURN_GENERATOR_r33 953 -#define _GUARD_IP_RETURN_VALUE_r00 954 -#define _GUARD_IP_RETURN_VALUE_r11 955 -#define _GUARD_IP_RETURN_VALUE_r22 956 -#define _GUARD_IP_RETURN_VALUE_r33 957 -#define _GUARD_IP_YIELD_VALUE_r00 958 -#define _GUARD_IP_YIELD_VALUE_r11 959 -#define _GUARD_IP_YIELD_VALUE_r22 960 -#define _GUARD_IP_YIELD_VALUE_r33 961 -#define _GUARD_IP__PUSH_FRAME_r00 962 -#define _GUARD_IP__PUSH_FRAME_r11 963 -#define _GUARD_IP__PUSH_FRAME_r22 964 -#define _GUARD_IP__PUSH_FRAME_r33 965 -#define _GUARD_IS_FALSE_POP_r00 966 -#define _GUARD_IS_FALSE_POP_r10 967 -#define _GUARD_IS_FALSE_POP_r21 968 -#define _GUARD_IS_FALSE_POP_r32 969 -#define _GUARD_IS_NONE_POP_r00 970 -#define _GUARD_IS_NONE_POP_r10 971 -#define _GUARD_IS_NONE_POP_r21 972 -#define _GUARD_IS_NONE_POP_r32 973 -#define _GUARD_IS_NOT_NONE_POP_r10 974 -#define _GUARD_IS_TRUE_POP_r00 975 -#define _GUARD_IS_TRUE_POP_r10 976 -#define _GUARD_IS_TRUE_POP_r21 977 -#define _GUARD_IS_TRUE_POP_r32 978 -#define _GUARD_KEYS_VERSION_r01 979 -#define _GUARD_KEYS_VERSION_r11 980 -#define _GUARD_KEYS_VERSION_r22 981 -#define _GUARD_KEYS_VERSION_r33 982 -#define _GUARD_NOS_ANY_DICT_r02 983 -#define _GUARD_NOS_ANY_DICT_r12 984 -#define _GUARD_NOS_ANY_DICT_r22 985 -#define _GUARD_NOS_ANY_DICT_r33 986 -#define _GUARD_NOS_COMPACT_ASCII_r02 987 -#define _GUARD_NOS_COMPACT_ASCII_r12 988 -#define _GUARD_NOS_COMPACT_ASCII_r22 989 -#define _GUARD_NOS_COMPACT_ASCII_r33 990 -#define _GUARD_NOS_DICT_r02 991 -#define _GUARD_NOS_DICT_r12 992 -#define _GUARD_NOS_DICT_r22 993 -#define _GUARD_NOS_DICT_r33 994 -#define _GUARD_NOS_FLOAT_r02 995 -#define _GUARD_NOS_FLOAT_r12 996 -#define _GUARD_NOS_FLOAT_r22 997 -#define _GUARD_NOS_FLOAT_r33 998 -#define _GUARD_NOS_INT_r02 999 -#define _GUARD_NOS_INT_r12 1000 -#define _GUARD_NOS_INT_r22 1001 -#define _GUARD_NOS_INT_r33 1002 -#define _GUARD_NOS_LIST_r02 1003 -#define _GUARD_NOS_LIST_r12 1004 -#define _GUARD_NOS_LIST_r22 1005 -#define _GUARD_NOS_LIST_r33 1006 -#define _GUARD_NOS_NOT_NULL_r02 1007 -#define _GUARD_NOS_NOT_NULL_r12 1008 -#define _GUARD_NOS_NOT_NULL_r22 1009 -#define _GUARD_NOS_NOT_NULL_r33 1010 -#define _GUARD_NOS_NULL_r02 1011 -#define _GUARD_NOS_NULL_r12 1012 -#define _GUARD_NOS_NULL_r22 1013 -#define _GUARD_NOS_NULL_r33 1014 -#define _GUARD_NOS_OVERFLOWED_r02 1015 -#define _GUARD_NOS_OVERFLOWED_r12 1016 -#define _GUARD_NOS_OVERFLOWED_r22 1017 -#define _GUARD_NOS_OVERFLOWED_r33 1018 -#define _GUARD_NOS_TUPLE_r02 1019 -#define _GUARD_NOS_TUPLE_r12 1020 -#define _GUARD_NOS_TUPLE_r22 1021 -#define _GUARD_NOS_TUPLE_r33 1022 -#define _GUARD_NOS_UNICODE_r02 1023 -#define _GUARD_NOS_UNICODE_r12 1024 -#define _GUARD_NOS_UNICODE_r22 1025 -#define _GUARD_NOS_UNICODE_r33 1026 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1027 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1028 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1029 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1030 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1031 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1032 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1033 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1034 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1035 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1036 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1037 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1038 -#define _GUARD_THIRD_NULL_r03 1039 -#define _GUARD_THIRD_NULL_r13 1040 -#define _GUARD_THIRD_NULL_r23 1041 -#define _GUARD_THIRD_NULL_r33 1042 -#define _GUARD_TOS_ANY_DICT_r01 1043 -#define _GUARD_TOS_ANY_DICT_r11 1044 -#define _GUARD_TOS_ANY_DICT_r22 1045 -#define _GUARD_TOS_ANY_DICT_r33 1046 -#define _GUARD_TOS_ANY_SET_r01 1047 -#define _GUARD_TOS_ANY_SET_r11 1048 -#define _GUARD_TOS_ANY_SET_r22 1049 -#define _GUARD_TOS_ANY_SET_r33 1050 -#define _GUARD_TOS_DICT_r01 1051 -#define _GUARD_TOS_DICT_r11 1052 -#define _GUARD_TOS_DICT_r22 1053 -#define _GUARD_TOS_DICT_r33 1054 -#define _GUARD_TOS_FLOAT_r01 1055 -#define _GUARD_TOS_FLOAT_r11 1056 -#define _GUARD_TOS_FLOAT_r22 1057 -#define _GUARD_TOS_FLOAT_r33 1058 -#define _GUARD_TOS_FROZENDICT_r01 1059 -#define _GUARD_TOS_FROZENDICT_r11 1060 -#define _GUARD_TOS_FROZENDICT_r22 1061 -#define _GUARD_TOS_FROZENDICT_r33 1062 -#define _GUARD_TOS_FROZENSET_r01 1063 -#define _GUARD_TOS_FROZENSET_r11 1064 -#define _GUARD_TOS_FROZENSET_r22 1065 -#define _GUARD_TOS_FROZENSET_r33 1066 -#define _GUARD_TOS_INT_r01 1067 -#define _GUARD_TOS_INT_r11 1068 -#define _GUARD_TOS_INT_r22 1069 -#define _GUARD_TOS_INT_r33 1070 -#define _GUARD_TOS_LIST_r01 1071 -#define _GUARD_TOS_LIST_r11 1072 -#define _GUARD_TOS_LIST_r22 1073 -#define _GUARD_TOS_LIST_r33 1074 -#define _GUARD_TOS_OVERFLOWED_r01 1075 -#define _GUARD_TOS_OVERFLOWED_r11 1076 -#define _GUARD_TOS_OVERFLOWED_r22 1077 -#define _GUARD_TOS_OVERFLOWED_r33 1078 -#define _GUARD_TOS_SET_r01 1079 -#define _GUARD_TOS_SET_r11 1080 -#define _GUARD_TOS_SET_r22 1081 -#define _GUARD_TOS_SET_r33 1082 -#define _GUARD_TOS_SLICE_r01 1083 -#define _GUARD_TOS_SLICE_r11 1084 -#define _GUARD_TOS_SLICE_r22 1085 -#define _GUARD_TOS_SLICE_r33 1086 -#define _GUARD_TOS_TUPLE_r01 1087 -#define _GUARD_TOS_TUPLE_r11 1088 -#define _GUARD_TOS_TUPLE_r22 1089 -#define _GUARD_TOS_TUPLE_r33 1090 -#define _GUARD_TOS_UNICODE_r01 1091 -#define _GUARD_TOS_UNICODE_r11 1092 -#define _GUARD_TOS_UNICODE_r22 1093 -#define _GUARD_TOS_UNICODE_r33 1094 -#define _GUARD_TYPE_VERSION_r01 1095 -#define _GUARD_TYPE_VERSION_r11 1096 -#define _GUARD_TYPE_VERSION_r22 1097 -#define _GUARD_TYPE_VERSION_r33 1098 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1099 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1100 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1101 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1102 -#define _HANDLE_PENDING_AND_DEOPT_r00 1103 -#define _HANDLE_PENDING_AND_DEOPT_r10 1104 -#define _HANDLE_PENDING_AND_DEOPT_r20 1105 -#define _HANDLE_PENDING_AND_DEOPT_r30 1106 -#define _IMPORT_FROM_r12 1107 -#define _IMPORT_NAME_r21 1108 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1109 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1110 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1111 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1112 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1113 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1114 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1115 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1116 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1117 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1118 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1119 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1120 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1121 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1122 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1123 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1124 -#define _INSERT_NULL_r10 1125 -#define _INSTRUMENTED_FOR_ITER_r23 1126 -#define _INSTRUMENTED_INSTRUCTION_r00 1127 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1128 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1129 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1130 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1131 -#define _INSTRUMENTED_LINE_r00 1132 -#define _INSTRUMENTED_NOT_TAKEN_r00 1133 -#define _INSTRUMENTED_NOT_TAKEN_r11 1134 -#define _INSTRUMENTED_NOT_TAKEN_r22 1135 -#define _INSTRUMENTED_NOT_TAKEN_r33 1136 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1137 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1138 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1139 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1140 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1141 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1142 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1143 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1144 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1145 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1146 -#define _IS_NONE_r11 1147 -#define _IS_OP_r03 1148 -#define _IS_OP_r13 1149 -#define _IS_OP_r23 1150 -#define _ITER_CHECK_LIST_r02 1151 -#define _ITER_CHECK_LIST_r12 1152 -#define _ITER_CHECK_LIST_r22 1153 -#define _ITER_CHECK_LIST_r33 1154 -#define _ITER_CHECK_RANGE_r02 1155 -#define _ITER_CHECK_RANGE_r12 1156 -#define _ITER_CHECK_RANGE_r22 1157 -#define _ITER_CHECK_RANGE_r33 1158 -#define _ITER_CHECK_TUPLE_r02 1159 -#define _ITER_CHECK_TUPLE_r12 1160 -#define _ITER_CHECK_TUPLE_r22 1161 -#define _ITER_CHECK_TUPLE_r33 1162 -#define _ITER_JUMP_LIST_r02 1163 -#define _ITER_JUMP_LIST_r12 1164 -#define _ITER_JUMP_LIST_r22 1165 -#define _ITER_JUMP_LIST_r33 1166 -#define _ITER_JUMP_RANGE_r02 1167 -#define _ITER_JUMP_RANGE_r12 1168 -#define _ITER_JUMP_RANGE_r22 1169 -#define _ITER_JUMP_RANGE_r33 1170 -#define _ITER_JUMP_TUPLE_r02 1171 -#define _ITER_JUMP_TUPLE_r12 1172 -#define _ITER_JUMP_TUPLE_r22 1173 -#define _ITER_JUMP_TUPLE_r33 1174 -#define _ITER_NEXT_LIST_r23 1175 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1176 -#define _ITER_NEXT_RANGE_r03 1177 -#define _ITER_NEXT_RANGE_r13 1178 -#define _ITER_NEXT_RANGE_r23 1179 -#define _ITER_NEXT_TUPLE_r03 1180 -#define _ITER_NEXT_TUPLE_r13 1181 -#define _ITER_NEXT_TUPLE_r23 1182 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1183 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1184 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1185 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1186 -#define _JUMP_TO_TOP_r00 1187 -#define _LIST_APPEND_r10 1188 -#define _LIST_EXTEND_r11 1189 -#define _LOAD_ATTR_r10 1190 -#define _LOAD_ATTR_CLASS_r11 1191 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1192 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1193 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1194 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1195 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1196 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1197 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1198 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1199 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1200 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1201 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1202 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1203 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1204 -#define _LOAD_ATTR_MODULE_r12 1205 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1206 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1207 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1208 -#define _LOAD_ATTR_SLOT_r02 1209 -#define _LOAD_ATTR_SLOT_r12 1210 -#define _LOAD_ATTR_SLOT_r23 1211 -#define _LOAD_ATTR_WITH_HINT_r12 1212 -#define _LOAD_BUILD_CLASS_r01 1213 -#define _LOAD_BYTECODE_r00 1214 -#define _LOAD_COMMON_CONSTANT_r01 1215 -#define _LOAD_COMMON_CONSTANT_r12 1216 -#define _LOAD_COMMON_CONSTANT_r23 1217 -#define _LOAD_CONST_r01 1218 -#define _LOAD_CONST_r12 1219 -#define _LOAD_CONST_r23 1220 -#define _LOAD_CONST_INLINE_r01 1221 -#define _LOAD_CONST_INLINE_r12 1222 -#define _LOAD_CONST_INLINE_r23 1223 -#define _LOAD_CONST_INLINE_BORROW_r01 1224 -#define _LOAD_CONST_INLINE_BORROW_r12 1225 -#define _LOAD_CONST_INLINE_BORROW_r23 1226 -#define _LOAD_CONST_UNDER_INLINE_r02 1227 -#define _LOAD_CONST_UNDER_INLINE_r12 1228 -#define _LOAD_CONST_UNDER_INLINE_r23 1229 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1230 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1231 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1232 -#define _LOAD_DEREF_r01 1233 -#define _LOAD_FAST_r01 1234 -#define _LOAD_FAST_r12 1235 -#define _LOAD_FAST_r23 1236 -#define _LOAD_FAST_0_r01 1237 -#define _LOAD_FAST_0_r12 1238 -#define _LOAD_FAST_0_r23 1239 -#define _LOAD_FAST_1_r01 1240 -#define _LOAD_FAST_1_r12 1241 -#define _LOAD_FAST_1_r23 1242 -#define _LOAD_FAST_2_r01 1243 -#define _LOAD_FAST_2_r12 1244 -#define _LOAD_FAST_2_r23 1245 -#define _LOAD_FAST_3_r01 1246 -#define _LOAD_FAST_3_r12 1247 -#define _LOAD_FAST_3_r23 1248 -#define _LOAD_FAST_4_r01 1249 -#define _LOAD_FAST_4_r12 1250 -#define _LOAD_FAST_4_r23 1251 -#define _LOAD_FAST_5_r01 1252 -#define _LOAD_FAST_5_r12 1253 -#define _LOAD_FAST_5_r23 1254 -#define _LOAD_FAST_6_r01 1255 -#define _LOAD_FAST_6_r12 1256 -#define _LOAD_FAST_6_r23 1257 -#define _LOAD_FAST_7_r01 1258 -#define _LOAD_FAST_7_r12 1259 -#define _LOAD_FAST_7_r23 1260 -#define _LOAD_FAST_AND_CLEAR_r01 1261 -#define _LOAD_FAST_AND_CLEAR_r12 1262 -#define _LOAD_FAST_AND_CLEAR_r23 1263 -#define _LOAD_FAST_BORROW_r01 1264 -#define _LOAD_FAST_BORROW_r12 1265 -#define _LOAD_FAST_BORROW_r23 1266 -#define _LOAD_FAST_BORROW_0_r01 1267 -#define _LOAD_FAST_BORROW_0_r12 1268 -#define _LOAD_FAST_BORROW_0_r23 1269 -#define _LOAD_FAST_BORROW_1_r01 1270 -#define _LOAD_FAST_BORROW_1_r12 1271 -#define _LOAD_FAST_BORROW_1_r23 1272 -#define _LOAD_FAST_BORROW_2_r01 1273 -#define _LOAD_FAST_BORROW_2_r12 1274 -#define _LOAD_FAST_BORROW_2_r23 1275 -#define _LOAD_FAST_BORROW_3_r01 1276 -#define _LOAD_FAST_BORROW_3_r12 1277 -#define _LOAD_FAST_BORROW_3_r23 1278 -#define _LOAD_FAST_BORROW_4_r01 1279 -#define _LOAD_FAST_BORROW_4_r12 1280 -#define _LOAD_FAST_BORROW_4_r23 1281 -#define _LOAD_FAST_BORROW_5_r01 1282 -#define _LOAD_FAST_BORROW_5_r12 1283 -#define _LOAD_FAST_BORROW_5_r23 1284 -#define _LOAD_FAST_BORROW_6_r01 1285 -#define _LOAD_FAST_BORROW_6_r12 1286 -#define _LOAD_FAST_BORROW_6_r23 1287 -#define _LOAD_FAST_BORROW_7_r01 1288 -#define _LOAD_FAST_BORROW_7_r12 1289 -#define _LOAD_FAST_BORROW_7_r23 1290 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1291 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1292 -#define _LOAD_FAST_CHECK_r01 1293 -#define _LOAD_FAST_CHECK_r12 1294 -#define _LOAD_FAST_CHECK_r23 1295 -#define _LOAD_FAST_LOAD_FAST_r02 1296 -#define _LOAD_FAST_LOAD_FAST_r13 1297 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1298 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1299 -#define _LOAD_GLOBAL_r00 1300 -#define _LOAD_GLOBAL_BUILTINS_r01 1301 -#define _LOAD_GLOBAL_MODULE_r01 1302 -#define _LOAD_LOCALS_r01 1303 -#define _LOAD_LOCALS_r12 1304 -#define _LOAD_LOCALS_r23 1305 -#define _LOAD_NAME_r01 1306 -#define _LOAD_SMALL_INT_r01 1307 -#define _LOAD_SMALL_INT_r12 1308 -#define _LOAD_SMALL_INT_r23 1309 -#define _LOAD_SMALL_INT_0_r01 1310 -#define _LOAD_SMALL_INT_0_r12 1311 -#define _LOAD_SMALL_INT_0_r23 1312 -#define _LOAD_SMALL_INT_1_r01 1313 -#define _LOAD_SMALL_INT_1_r12 1314 -#define _LOAD_SMALL_INT_1_r23 1315 -#define _LOAD_SMALL_INT_2_r01 1316 -#define _LOAD_SMALL_INT_2_r12 1317 -#define _LOAD_SMALL_INT_2_r23 1318 -#define _LOAD_SMALL_INT_3_r01 1319 -#define _LOAD_SMALL_INT_3_r12 1320 -#define _LOAD_SMALL_INT_3_r23 1321 -#define _LOAD_SPECIAL_r00 1322 -#define _LOAD_SUPER_ATTR_ATTR_r31 1323 -#define _LOAD_SUPER_ATTR_METHOD_r32 1324 -#define _LOCK_OBJECT_r01 1325 -#define _LOCK_OBJECT_r11 1326 -#define _LOCK_OBJECT_r22 1327 -#define _LOCK_OBJECT_r33 1328 -#define _MAKE_CALLARGS_A_TUPLE_r33 1329 -#define _MAKE_CELL_r00 1330 -#define _MAKE_FUNCTION_r11 1331 -#define _MAKE_HEAP_SAFE_r01 1332 -#define _MAKE_HEAP_SAFE_r11 1333 -#define _MAKE_HEAP_SAFE_r22 1334 -#define _MAKE_HEAP_SAFE_r33 1335 -#define _MAKE_WARM_r00 1336 -#define _MAKE_WARM_r11 1337 -#define _MAKE_WARM_r22 1338 -#define _MAKE_WARM_r33 1339 -#define _MAP_ADD_r20 1340 -#define _MATCH_CLASS_r33 1341 -#define _MATCH_KEYS_r23 1342 -#define _MATCH_MAPPING_r02 1343 -#define _MATCH_MAPPING_r12 1344 -#define _MATCH_MAPPING_r23 1345 -#define _MATCH_SEQUENCE_r02 1346 -#define _MATCH_SEQUENCE_r12 1347 -#define _MATCH_SEQUENCE_r23 1348 -#define _MAYBE_EXPAND_METHOD_r00 1349 -#define _MAYBE_EXPAND_METHOD_KW_r11 1350 -#define _MONITOR_CALL_r00 1351 -#define _MONITOR_CALL_KW_r11 1352 -#define _MONITOR_JUMP_BACKWARD_r00 1353 -#define _MONITOR_JUMP_BACKWARD_r11 1354 -#define _MONITOR_JUMP_BACKWARD_r22 1355 -#define _MONITOR_JUMP_BACKWARD_r33 1356 -#define _MONITOR_RESUME_r00 1357 -#define _NOP_r00 1358 -#define _NOP_r11 1359 -#define _NOP_r22 1360 -#define _NOP_r33 1361 -#define _POP_CALL_r20 1362 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1363 -#define _POP_CALL_ONE_r30 1364 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1365 -#define _POP_CALL_TWO_r30 1366 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1367 -#define _POP_EXCEPT_r10 1368 -#define _POP_ITER_r20 1369 -#define _POP_JUMP_IF_FALSE_r00 1370 -#define _POP_JUMP_IF_FALSE_r10 1371 -#define _POP_JUMP_IF_FALSE_r21 1372 -#define _POP_JUMP_IF_FALSE_r32 1373 -#define _POP_JUMP_IF_TRUE_r00 1374 -#define _POP_JUMP_IF_TRUE_r10 1375 -#define _POP_JUMP_IF_TRUE_r21 1376 -#define _POP_JUMP_IF_TRUE_r32 1377 -#define _POP_TOP_r10 1378 -#define _POP_TOP_FLOAT_r00 1379 -#define _POP_TOP_FLOAT_r10 1380 -#define _POP_TOP_FLOAT_r21 1381 -#define _POP_TOP_FLOAT_r32 1382 -#define _POP_TOP_INT_r00 1383 -#define _POP_TOP_INT_r10 1384 -#define _POP_TOP_INT_r21 1385 -#define _POP_TOP_INT_r32 1386 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1387 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1388 -#define _POP_TOP_NOP_r00 1389 -#define _POP_TOP_NOP_r10 1390 -#define _POP_TOP_NOP_r21 1391 -#define _POP_TOP_NOP_r32 1392 -#define _POP_TOP_UNICODE_r00 1393 -#define _POP_TOP_UNICODE_r10 1394 -#define _POP_TOP_UNICODE_r21 1395 -#define _POP_TOP_UNICODE_r32 1396 -#define _POP_TWO_r20 1397 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1398 -#define _PUSH_EXC_INFO_r02 1399 -#define _PUSH_EXC_INFO_r12 1400 -#define _PUSH_EXC_INFO_r23 1401 -#define _PUSH_FRAME_r10 1402 -#define _PUSH_NULL_r01 1403 -#define _PUSH_NULL_r12 1404 -#define _PUSH_NULL_r23 1405 -#define _PUSH_NULL_CONDITIONAL_r00 1406 -#define _PY_FRAME_EX_r31 1407 -#define _PY_FRAME_GENERAL_r01 1408 -#define _PY_FRAME_KW_r11 1409 -#define _REPLACE_WITH_TRUE_r02 1410 -#define _REPLACE_WITH_TRUE_r12 1411 -#define _REPLACE_WITH_TRUE_r23 1412 -#define _RESUME_CHECK_r00 1413 -#define _RESUME_CHECK_r11 1414 -#define _RESUME_CHECK_r22 1415 -#define _RESUME_CHECK_r33 1416 -#define _RETURN_GENERATOR_r01 1417 -#define _RETURN_VALUE_r11 1418 -#define _SAVE_RETURN_OFFSET_r00 1419 -#define _SAVE_RETURN_OFFSET_r11 1420 -#define _SAVE_RETURN_OFFSET_r22 1421 -#define _SAVE_RETURN_OFFSET_r33 1422 -#define _SEND_r33 1423 -#define _SEND_GEN_FRAME_r33 1424 -#define _SETUP_ANNOTATIONS_r00 1425 -#define _SET_ADD_r10 1426 -#define _SET_FUNCTION_ATTRIBUTE_r01 1427 -#define _SET_FUNCTION_ATTRIBUTE_r11 1428 -#define _SET_FUNCTION_ATTRIBUTE_r21 1429 -#define _SET_FUNCTION_ATTRIBUTE_r32 1430 -#define _SET_IP_r00 1431 -#define _SET_IP_r11 1432 -#define _SET_IP_r22 1433 -#define _SET_IP_r33 1434 -#define _SET_UPDATE_r11 1435 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1436 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1437 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1438 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1439 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1440 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1441 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1442 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1443 -#define _SPILL_OR_RELOAD_r01 1444 -#define _SPILL_OR_RELOAD_r02 1445 -#define _SPILL_OR_RELOAD_r03 1446 -#define _SPILL_OR_RELOAD_r10 1447 -#define _SPILL_OR_RELOAD_r12 1448 -#define _SPILL_OR_RELOAD_r13 1449 -#define _SPILL_OR_RELOAD_r20 1450 -#define _SPILL_OR_RELOAD_r21 1451 -#define _SPILL_OR_RELOAD_r23 1452 -#define _SPILL_OR_RELOAD_r30 1453 -#define _SPILL_OR_RELOAD_r31 1454 -#define _SPILL_OR_RELOAD_r32 1455 -#define _START_EXECUTOR_r00 1456 -#define _STORE_ATTR_r20 1457 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1458 -#define _STORE_ATTR_SLOT_r21 1459 -#define _STORE_ATTR_WITH_HINT_r21 1460 -#define _STORE_DEREF_r10 1461 -#define _STORE_FAST_LOAD_FAST_r11 1462 -#define _STORE_FAST_STORE_FAST_r20 1463 -#define _STORE_GLOBAL_r10 1464 -#define _STORE_NAME_r10 1465 -#define _STORE_SLICE_r30 1466 -#define _STORE_SUBSCR_r30 1467 -#define _STORE_SUBSCR_DICT_r31 1468 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1469 -#define _STORE_SUBSCR_LIST_INT_r32 1470 -#define _SWAP_r11 1471 -#define _SWAP_2_r02 1472 -#define _SWAP_2_r12 1473 -#define _SWAP_2_r22 1474 -#define _SWAP_2_r33 1475 -#define _SWAP_3_r03 1476 -#define _SWAP_3_r13 1477 -#define _SWAP_3_r23 1478 -#define _SWAP_3_r33 1479 -#define _SWAP_FAST_r01 1480 -#define _SWAP_FAST_r11 1481 -#define _SWAP_FAST_r22 1482 -#define _SWAP_FAST_r33 1483 -#define _SWAP_FAST_0_r01 1484 -#define _SWAP_FAST_0_r11 1485 -#define _SWAP_FAST_0_r22 1486 -#define _SWAP_FAST_0_r33 1487 -#define _SWAP_FAST_1_r01 1488 -#define _SWAP_FAST_1_r11 1489 -#define _SWAP_FAST_1_r22 1490 -#define _SWAP_FAST_1_r33 1491 -#define _SWAP_FAST_2_r01 1492 -#define _SWAP_FAST_2_r11 1493 -#define _SWAP_FAST_2_r22 1494 -#define _SWAP_FAST_2_r33 1495 -#define _SWAP_FAST_3_r01 1496 -#define _SWAP_FAST_3_r11 1497 -#define _SWAP_FAST_3_r22 1498 -#define _SWAP_FAST_3_r33 1499 -#define _SWAP_FAST_4_r01 1500 -#define _SWAP_FAST_4_r11 1501 -#define _SWAP_FAST_4_r22 1502 -#define _SWAP_FAST_4_r33 1503 -#define _SWAP_FAST_5_r01 1504 -#define _SWAP_FAST_5_r11 1505 -#define _SWAP_FAST_5_r22 1506 -#define _SWAP_FAST_5_r33 1507 -#define _SWAP_FAST_6_r01 1508 -#define _SWAP_FAST_6_r11 1509 -#define _SWAP_FAST_6_r22 1510 -#define _SWAP_FAST_6_r33 1511 -#define _SWAP_FAST_7_r01 1512 -#define _SWAP_FAST_7_r11 1513 -#define _SWAP_FAST_7_r22 1514 -#define _SWAP_FAST_7_r33 1515 -#define _TIER2_RESUME_CHECK_r00 1516 -#define _TIER2_RESUME_CHECK_r11 1517 -#define _TIER2_RESUME_CHECK_r22 1518 -#define _TIER2_RESUME_CHECK_r33 1519 -#define _TO_BOOL_r11 1520 -#define _TO_BOOL_BOOL_r01 1521 -#define _TO_BOOL_BOOL_r11 1522 -#define _TO_BOOL_BOOL_r22 1523 -#define _TO_BOOL_BOOL_r33 1524 -#define _TO_BOOL_INT_r02 1525 -#define _TO_BOOL_INT_r12 1526 -#define _TO_BOOL_INT_r23 1527 -#define _TO_BOOL_LIST_r02 1528 -#define _TO_BOOL_LIST_r12 1529 -#define _TO_BOOL_LIST_r23 1530 -#define _TO_BOOL_NONE_r01 1531 -#define _TO_BOOL_NONE_r11 1532 -#define _TO_BOOL_NONE_r22 1533 -#define _TO_BOOL_NONE_r33 1534 -#define _TO_BOOL_STR_r02 1535 -#define _TO_BOOL_STR_r12 1536 -#define _TO_BOOL_STR_r23 1537 -#define _TRACE_RECORD_r00 1538 -#define _UNARY_INVERT_r12 1539 -#define _UNARY_NEGATIVE_r12 1540 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1541 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1542 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1543 -#define _UNARY_NOT_r01 1544 -#define _UNARY_NOT_r11 1545 -#define _UNARY_NOT_r22 1546 -#define _UNARY_NOT_r33 1547 -#define _UNPACK_EX_r10 1548 -#define _UNPACK_SEQUENCE_r10 1549 -#define _UNPACK_SEQUENCE_LIST_r10 1550 -#define _UNPACK_SEQUENCE_TUPLE_r10 1551 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1552 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1553 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1554 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1555 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1556 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1557 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1558 -#define _WITH_EXCEPT_START_r33 1559 -#define _YIELD_VALUE_r11 1560 -#define MAX_UOP_REGS_ID 1560 +#define _YIELD_VALUE 633 +#define MAX_UOP_ID 633 +#define _BINARY_OP_r23 634 +#define _BINARY_OP_ADD_FLOAT_r03 635 +#define _BINARY_OP_ADD_FLOAT_r13 636 +#define _BINARY_OP_ADD_FLOAT_r23 637 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 638 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 639 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 640 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 641 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 642 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 643 +#define _BINARY_OP_ADD_INT_r03 644 +#define _BINARY_OP_ADD_INT_r13 645 +#define _BINARY_OP_ADD_INT_r23 646 +#define _BINARY_OP_ADD_INT_INPLACE_r03 647 +#define _BINARY_OP_ADD_INT_INPLACE_r13 648 +#define _BINARY_OP_ADD_INT_INPLACE_r23 649 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 650 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 651 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 652 +#define _BINARY_OP_ADD_UNICODE_r03 653 +#define _BINARY_OP_ADD_UNICODE_r13 654 +#define _BINARY_OP_ADD_UNICODE_r23 655 +#define _BINARY_OP_EXTEND_r23 656 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 657 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 658 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 659 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 660 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 661 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 662 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 663 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 664 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 665 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 666 +#define _BINARY_OP_MULTIPLY_INT_r03 667 +#define _BINARY_OP_MULTIPLY_INT_r13 668 +#define _BINARY_OP_MULTIPLY_INT_r23 669 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 670 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 671 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 672 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 673 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 674 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 675 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 676 +#define _BINARY_OP_SUBSCR_DICT_r23 677 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 678 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 679 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 680 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 681 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 682 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 683 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 684 +#define _BINARY_OP_SUBSCR_STR_INT_r23 685 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 686 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 687 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 688 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 689 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 690 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 691 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 692 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 693 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 694 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 695 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 696 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 697 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 698 +#define _BINARY_OP_SUBTRACT_INT_r03 699 +#define _BINARY_OP_SUBTRACT_INT_r13 700 +#define _BINARY_OP_SUBTRACT_INT_r23 701 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 702 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 703 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 704 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 705 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 706 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 707 +#define _BINARY_SLICE_r31 708 +#define _BUILD_INTERPOLATION_r01 709 +#define _BUILD_LIST_r01 710 +#define _BUILD_MAP_r01 711 +#define _BUILD_SET_r01 712 +#define _BUILD_SLICE_r01 713 +#define _BUILD_STRING_r01 714 +#define _BUILD_TEMPLATE_r21 715 +#define _BUILD_TUPLE_r01 716 +#define _CALL_BUILTIN_CLASS_r01 717 +#define _CALL_BUILTIN_FAST_r01 718 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 719 +#define _CALL_BUILTIN_O_r03 720 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 721 +#define _CALL_INTRINSIC_1_r12 722 +#define _CALL_INTRINSIC_2_r23 723 +#define _CALL_ISINSTANCE_r31 724 +#define _CALL_KW_NON_PY_r11 725 +#define _CALL_LEN_r33 726 +#define _CALL_LIST_APPEND_r03 727 +#define _CALL_LIST_APPEND_r13 728 +#define _CALL_LIST_APPEND_r23 729 +#define _CALL_LIST_APPEND_r33 730 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 731 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 732 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 733 +#define _CALL_METHOD_DESCRIPTOR_O_r03 734 +#define _CALL_NON_PY_GENERAL_r01 735 +#define _CALL_STR_1_r32 736 +#define _CALL_TUPLE_1_r32 737 +#define _CALL_TYPE_1_r02 738 +#define _CALL_TYPE_1_r12 739 +#define _CALL_TYPE_1_r22 740 +#define _CALL_TYPE_1_r32 741 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 742 +#define _CHECK_ATTR_CLASS_r01 743 +#define _CHECK_ATTR_CLASS_r11 744 +#define _CHECK_ATTR_CLASS_r22 745 +#define _CHECK_ATTR_CLASS_r33 746 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 747 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 748 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 749 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 750 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 751 +#define _CHECK_EG_MATCH_r22 752 +#define _CHECK_EXC_MATCH_r22 753 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 754 +#define _CHECK_FUNCTION_VERSION_r00 755 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 756 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 757 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 758 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 759 +#define _CHECK_FUNCTION_VERSION_KW_r11 760 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 761 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 762 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 763 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 764 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 765 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 766 +#define _CHECK_IS_PY_CALLABLE_EX_r03 767 +#define _CHECK_IS_PY_CALLABLE_EX_r13 768 +#define _CHECK_IS_PY_CALLABLE_EX_r23 769 +#define _CHECK_IS_PY_CALLABLE_EX_r33 770 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 771 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 772 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 773 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 774 +#define _CHECK_METHOD_VERSION_r00 775 +#define _CHECK_METHOD_VERSION_KW_r11 776 +#define _CHECK_PEP_523_r00 777 +#define _CHECK_PEP_523_r11 778 +#define _CHECK_PEP_523_r22 779 +#define _CHECK_PEP_523_r33 780 +#define _CHECK_PERIODIC_r00 781 +#define _CHECK_PERIODIC_AT_END_r00 782 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 783 +#define _CHECK_RECURSION_REMAINING_r00 784 +#define _CHECK_RECURSION_REMAINING_r11 785 +#define _CHECK_RECURSION_REMAINING_r22 786 +#define _CHECK_RECURSION_REMAINING_r33 787 +#define _CHECK_STACK_SPACE_r00 788 +#define _CHECK_STACK_SPACE_OPERAND_r00 789 +#define _CHECK_STACK_SPACE_OPERAND_r11 790 +#define _CHECK_STACK_SPACE_OPERAND_r22 791 +#define _CHECK_STACK_SPACE_OPERAND_r33 792 +#define _CHECK_VALIDITY_r00 793 +#define _CHECK_VALIDITY_r11 794 +#define _CHECK_VALIDITY_r22 795 +#define _CHECK_VALIDITY_r33 796 +#define _COLD_DYNAMIC_EXIT_r00 797 +#define _COLD_EXIT_r00 798 +#define _COMPARE_OP_r21 799 +#define _COMPARE_OP_FLOAT_r03 800 +#define _COMPARE_OP_FLOAT_r13 801 +#define _COMPARE_OP_FLOAT_r23 802 +#define _COMPARE_OP_INT_r23 803 +#define _COMPARE_OP_STR_r23 804 +#define _CONTAINS_OP_r23 805 +#define _CONTAINS_OP_DICT_r23 806 +#define _CONTAINS_OP_SET_r23 807 +#define _CONVERT_VALUE_r11 808 +#define _COPY_r01 809 +#define _COPY_1_r02 810 +#define _COPY_1_r12 811 +#define _COPY_1_r23 812 +#define _COPY_2_r03 813 +#define _COPY_2_r13 814 +#define _COPY_2_r23 815 +#define _COPY_3_r03 816 +#define _COPY_3_r13 817 +#define _COPY_3_r23 818 +#define _COPY_3_r33 819 +#define _COPY_FREE_VARS_r00 820 +#define _COPY_FREE_VARS_r11 821 +#define _COPY_FREE_VARS_r22 822 +#define _COPY_FREE_VARS_r33 823 +#define _CREATE_INIT_FRAME_r01 824 +#define _DELETE_ATTR_r10 825 +#define _DELETE_DEREF_r00 826 +#define _DELETE_FAST_r00 827 +#define _DELETE_GLOBAL_r00 828 +#define _DELETE_NAME_r00 829 +#define _DELETE_SUBSCR_r20 830 +#define _DEOPT_r00 831 +#define _DEOPT_r10 832 +#define _DEOPT_r20 833 +#define _DEOPT_r30 834 +#define _DICT_MERGE_r11 835 +#define _DICT_UPDATE_r11 836 +#define _DO_CALL_r01 837 +#define _DO_CALL_FUNCTION_EX_r31 838 +#define _DO_CALL_KW_r11 839 +#define _DYNAMIC_EXIT_r00 840 +#define _DYNAMIC_EXIT_r10 841 +#define _DYNAMIC_EXIT_r20 842 +#define _DYNAMIC_EXIT_r30 843 +#define _END_FOR_r10 844 +#define _END_SEND_r31 845 +#define _ERROR_POP_N_r00 846 +#define _EXIT_INIT_CHECK_r10 847 +#define _EXIT_TRACE_r00 848 +#define _EXIT_TRACE_r10 849 +#define _EXIT_TRACE_r20 850 +#define _EXIT_TRACE_r30 851 +#define _EXPAND_METHOD_r00 852 +#define _EXPAND_METHOD_KW_r11 853 +#define _FATAL_ERROR_r00 854 +#define _FATAL_ERROR_r11 855 +#define _FATAL_ERROR_r22 856 +#define _FATAL_ERROR_r33 857 +#define _FORMAT_SIMPLE_r11 858 +#define _FORMAT_WITH_SPEC_r21 859 +#define _FOR_ITER_r23 860 +#define _FOR_ITER_GEN_FRAME_r03 861 +#define _FOR_ITER_GEN_FRAME_r13 862 +#define _FOR_ITER_GEN_FRAME_r23 863 +#define _FOR_ITER_TIER_TWO_r23 864 +#define _GET_AITER_r11 865 +#define _GET_ANEXT_r12 866 +#define _GET_AWAITABLE_r11 867 +#define _GET_ITER_r12 868 +#define _GET_LEN_r12 869 +#define _GUARD_BINARY_OP_EXTEND_r22 870 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 871 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 872 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 873 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 874 +#define _GUARD_BIT_IS_SET_POP_r00 875 +#define _GUARD_BIT_IS_SET_POP_r10 876 +#define _GUARD_BIT_IS_SET_POP_r21 877 +#define _GUARD_BIT_IS_SET_POP_r32 878 +#define _GUARD_BIT_IS_SET_POP_4_r00 879 +#define _GUARD_BIT_IS_SET_POP_4_r10 880 +#define _GUARD_BIT_IS_SET_POP_4_r21 881 +#define _GUARD_BIT_IS_SET_POP_4_r32 882 +#define _GUARD_BIT_IS_SET_POP_5_r00 883 +#define _GUARD_BIT_IS_SET_POP_5_r10 884 +#define _GUARD_BIT_IS_SET_POP_5_r21 885 +#define _GUARD_BIT_IS_SET_POP_5_r32 886 +#define _GUARD_BIT_IS_SET_POP_6_r00 887 +#define _GUARD_BIT_IS_SET_POP_6_r10 888 +#define _GUARD_BIT_IS_SET_POP_6_r21 889 +#define _GUARD_BIT_IS_SET_POP_6_r32 890 +#define _GUARD_BIT_IS_SET_POP_7_r00 891 +#define _GUARD_BIT_IS_SET_POP_7_r10 892 +#define _GUARD_BIT_IS_SET_POP_7_r21 893 +#define _GUARD_BIT_IS_SET_POP_7_r32 894 +#define _GUARD_BIT_IS_UNSET_POP_r00 895 +#define _GUARD_BIT_IS_UNSET_POP_r10 896 +#define _GUARD_BIT_IS_UNSET_POP_r21 897 +#define _GUARD_BIT_IS_UNSET_POP_r32 898 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 899 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 900 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 901 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 902 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 903 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 904 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 905 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 906 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 907 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 908 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 909 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 910 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 911 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 912 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 913 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 914 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 915 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 916 +#define _GUARD_CALLABLE_BUILTIN_O_r00 917 +#define _GUARD_CALLABLE_ISINSTANCE_r03 918 +#define _GUARD_CALLABLE_ISINSTANCE_r13 919 +#define _GUARD_CALLABLE_ISINSTANCE_r23 920 +#define _GUARD_CALLABLE_ISINSTANCE_r33 921 +#define _GUARD_CALLABLE_LEN_r03 922 +#define _GUARD_CALLABLE_LEN_r13 923 +#define _GUARD_CALLABLE_LEN_r23 924 +#define _GUARD_CALLABLE_LEN_r33 925 +#define _GUARD_CALLABLE_LIST_APPEND_r03 926 +#define _GUARD_CALLABLE_LIST_APPEND_r13 927 +#define _GUARD_CALLABLE_LIST_APPEND_r23 928 +#define _GUARD_CALLABLE_LIST_APPEND_r33 929 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 930 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 931 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 932 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 933 +#define _GUARD_CALLABLE_STR_1_r03 934 +#define _GUARD_CALLABLE_STR_1_r13 935 +#define _GUARD_CALLABLE_STR_1_r23 936 +#define _GUARD_CALLABLE_STR_1_r33 937 +#define _GUARD_CALLABLE_TUPLE_1_r03 938 +#define _GUARD_CALLABLE_TUPLE_1_r13 939 +#define _GUARD_CALLABLE_TUPLE_1_r23 940 +#define _GUARD_CALLABLE_TUPLE_1_r33 941 +#define _GUARD_CALLABLE_TYPE_1_r03 942 +#define _GUARD_CALLABLE_TYPE_1_r13 943 +#define _GUARD_CALLABLE_TYPE_1_r23 944 +#define _GUARD_CALLABLE_TYPE_1_r33 945 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 946 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 947 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 948 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 949 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 950 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 951 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 952 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 953 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 954 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 955 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 956 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 957 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 958 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 959 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 960 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 961 +#define _GUARD_DORV_NO_DICT_r01 962 +#define _GUARD_DORV_NO_DICT_r11 963 +#define _GUARD_DORV_NO_DICT_r22 964 +#define _GUARD_DORV_NO_DICT_r33 965 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 966 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 967 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 968 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 969 +#define _GUARD_GLOBALS_VERSION_r00 970 +#define _GUARD_GLOBALS_VERSION_r11 971 +#define _GUARD_GLOBALS_VERSION_r22 972 +#define _GUARD_GLOBALS_VERSION_r33 973 +#define _GUARD_IP_RETURN_GENERATOR_r00 974 +#define _GUARD_IP_RETURN_GENERATOR_r11 975 +#define _GUARD_IP_RETURN_GENERATOR_r22 976 +#define _GUARD_IP_RETURN_GENERATOR_r33 977 +#define _GUARD_IP_RETURN_VALUE_r00 978 +#define _GUARD_IP_RETURN_VALUE_r11 979 +#define _GUARD_IP_RETURN_VALUE_r22 980 +#define _GUARD_IP_RETURN_VALUE_r33 981 +#define _GUARD_IP_YIELD_VALUE_r00 982 +#define _GUARD_IP_YIELD_VALUE_r11 983 +#define _GUARD_IP_YIELD_VALUE_r22 984 +#define _GUARD_IP_YIELD_VALUE_r33 985 +#define _GUARD_IP__PUSH_FRAME_r00 986 +#define _GUARD_IP__PUSH_FRAME_r11 987 +#define _GUARD_IP__PUSH_FRAME_r22 988 +#define _GUARD_IP__PUSH_FRAME_r33 989 +#define _GUARD_IS_FALSE_POP_r00 990 +#define _GUARD_IS_FALSE_POP_r10 991 +#define _GUARD_IS_FALSE_POP_r21 992 +#define _GUARD_IS_FALSE_POP_r32 993 +#define _GUARD_IS_NONE_POP_r00 994 +#define _GUARD_IS_NONE_POP_r10 995 +#define _GUARD_IS_NONE_POP_r21 996 +#define _GUARD_IS_NONE_POP_r32 997 +#define _GUARD_IS_NOT_NONE_POP_r10 998 +#define _GUARD_IS_TRUE_POP_r00 999 +#define _GUARD_IS_TRUE_POP_r10 1000 +#define _GUARD_IS_TRUE_POP_r21 1001 +#define _GUARD_IS_TRUE_POP_r32 1002 +#define _GUARD_KEYS_VERSION_r01 1003 +#define _GUARD_KEYS_VERSION_r11 1004 +#define _GUARD_KEYS_VERSION_r22 1005 +#define _GUARD_KEYS_VERSION_r33 1006 +#define _GUARD_NOS_ANY_DICT_r02 1007 +#define _GUARD_NOS_ANY_DICT_r12 1008 +#define _GUARD_NOS_ANY_DICT_r22 1009 +#define _GUARD_NOS_ANY_DICT_r33 1010 +#define _GUARD_NOS_COMPACT_ASCII_r02 1011 +#define _GUARD_NOS_COMPACT_ASCII_r12 1012 +#define _GUARD_NOS_COMPACT_ASCII_r22 1013 +#define _GUARD_NOS_COMPACT_ASCII_r33 1014 +#define _GUARD_NOS_DICT_r02 1015 +#define _GUARD_NOS_DICT_r12 1016 +#define _GUARD_NOS_DICT_r22 1017 +#define _GUARD_NOS_DICT_r33 1018 +#define _GUARD_NOS_FLOAT_r02 1019 +#define _GUARD_NOS_FLOAT_r12 1020 +#define _GUARD_NOS_FLOAT_r22 1021 +#define _GUARD_NOS_FLOAT_r33 1022 +#define _GUARD_NOS_INT_r02 1023 +#define _GUARD_NOS_INT_r12 1024 +#define _GUARD_NOS_INT_r22 1025 +#define _GUARD_NOS_INT_r33 1026 +#define _GUARD_NOS_LIST_r02 1027 +#define _GUARD_NOS_LIST_r12 1028 +#define _GUARD_NOS_LIST_r22 1029 +#define _GUARD_NOS_LIST_r33 1030 +#define _GUARD_NOS_NOT_NULL_r02 1031 +#define _GUARD_NOS_NOT_NULL_r12 1032 +#define _GUARD_NOS_NOT_NULL_r22 1033 +#define _GUARD_NOS_NOT_NULL_r33 1034 +#define _GUARD_NOS_NULL_r02 1035 +#define _GUARD_NOS_NULL_r12 1036 +#define _GUARD_NOS_NULL_r22 1037 +#define _GUARD_NOS_NULL_r33 1038 +#define _GUARD_NOS_OVERFLOWED_r02 1039 +#define _GUARD_NOS_OVERFLOWED_r12 1040 +#define _GUARD_NOS_OVERFLOWED_r22 1041 +#define _GUARD_NOS_OVERFLOWED_r33 1042 +#define _GUARD_NOS_TUPLE_r02 1043 +#define _GUARD_NOS_TUPLE_r12 1044 +#define _GUARD_NOS_TUPLE_r22 1045 +#define _GUARD_NOS_TUPLE_r33 1046 +#define _GUARD_NOS_UNICODE_r02 1047 +#define _GUARD_NOS_UNICODE_r12 1048 +#define _GUARD_NOS_UNICODE_r22 1049 +#define _GUARD_NOS_UNICODE_r33 1050 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1051 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1052 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1053 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1054 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1055 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1056 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1057 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1058 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1059 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1060 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1061 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1062 +#define _GUARD_THIRD_NULL_r03 1063 +#define _GUARD_THIRD_NULL_r13 1064 +#define _GUARD_THIRD_NULL_r23 1065 +#define _GUARD_THIRD_NULL_r33 1066 +#define _GUARD_TOS_ANY_DICT_r01 1067 +#define _GUARD_TOS_ANY_DICT_r11 1068 +#define _GUARD_TOS_ANY_DICT_r22 1069 +#define _GUARD_TOS_ANY_DICT_r33 1070 +#define _GUARD_TOS_ANY_SET_r01 1071 +#define _GUARD_TOS_ANY_SET_r11 1072 +#define _GUARD_TOS_ANY_SET_r22 1073 +#define _GUARD_TOS_ANY_SET_r33 1074 +#define _GUARD_TOS_DICT_r01 1075 +#define _GUARD_TOS_DICT_r11 1076 +#define _GUARD_TOS_DICT_r22 1077 +#define _GUARD_TOS_DICT_r33 1078 +#define _GUARD_TOS_FLOAT_r01 1079 +#define _GUARD_TOS_FLOAT_r11 1080 +#define _GUARD_TOS_FLOAT_r22 1081 +#define _GUARD_TOS_FLOAT_r33 1082 +#define _GUARD_TOS_FROZENDICT_r01 1083 +#define _GUARD_TOS_FROZENDICT_r11 1084 +#define _GUARD_TOS_FROZENDICT_r22 1085 +#define _GUARD_TOS_FROZENDICT_r33 1086 +#define _GUARD_TOS_FROZENSET_r01 1087 +#define _GUARD_TOS_FROZENSET_r11 1088 +#define _GUARD_TOS_FROZENSET_r22 1089 +#define _GUARD_TOS_FROZENSET_r33 1090 +#define _GUARD_TOS_INT_r01 1091 +#define _GUARD_TOS_INT_r11 1092 +#define _GUARD_TOS_INT_r22 1093 +#define _GUARD_TOS_INT_r33 1094 +#define _GUARD_TOS_LIST_r01 1095 +#define _GUARD_TOS_LIST_r11 1096 +#define _GUARD_TOS_LIST_r22 1097 +#define _GUARD_TOS_LIST_r33 1098 +#define _GUARD_TOS_OVERFLOWED_r01 1099 +#define _GUARD_TOS_OVERFLOWED_r11 1100 +#define _GUARD_TOS_OVERFLOWED_r22 1101 +#define _GUARD_TOS_OVERFLOWED_r33 1102 +#define _GUARD_TOS_SET_r01 1103 +#define _GUARD_TOS_SET_r11 1104 +#define _GUARD_TOS_SET_r22 1105 +#define _GUARD_TOS_SET_r33 1106 +#define _GUARD_TOS_SLICE_r01 1107 +#define _GUARD_TOS_SLICE_r11 1108 +#define _GUARD_TOS_SLICE_r22 1109 +#define _GUARD_TOS_SLICE_r33 1110 +#define _GUARD_TOS_TUPLE_r01 1111 +#define _GUARD_TOS_TUPLE_r11 1112 +#define _GUARD_TOS_TUPLE_r22 1113 +#define _GUARD_TOS_TUPLE_r33 1114 +#define _GUARD_TOS_UNICODE_r01 1115 +#define _GUARD_TOS_UNICODE_r11 1116 +#define _GUARD_TOS_UNICODE_r22 1117 +#define _GUARD_TOS_UNICODE_r33 1118 +#define _GUARD_TYPE_VERSION_r01 1119 +#define _GUARD_TYPE_VERSION_r11 1120 +#define _GUARD_TYPE_VERSION_r22 1121 +#define _GUARD_TYPE_VERSION_r33 1122 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1123 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1124 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1125 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1126 +#define _HANDLE_PENDING_AND_DEOPT_r00 1127 +#define _HANDLE_PENDING_AND_DEOPT_r10 1128 +#define _HANDLE_PENDING_AND_DEOPT_r20 1129 +#define _HANDLE_PENDING_AND_DEOPT_r30 1130 +#define _IMPORT_FROM_r12 1131 +#define _IMPORT_NAME_r21 1132 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1133 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1134 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1135 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1136 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1137 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1138 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1139 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1140 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1141 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1142 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1143 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1144 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1145 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1146 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1147 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1148 +#define _INSERT_NULL_r10 1149 +#define _INSTRUMENTED_FOR_ITER_r23 1150 +#define _INSTRUMENTED_INSTRUCTION_r00 1151 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1152 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1153 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1154 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1155 +#define _INSTRUMENTED_LINE_r00 1156 +#define _INSTRUMENTED_NOT_TAKEN_r00 1157 +#define _INSTRUMENTED_NOT_TAKEN_r11 1158 +#define _INSTRUMENTED_NOT_TAKEN_r22 1159 +#define _INSTRUMENTED_NOT_TAKEN_r33 1160 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1161 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1162 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1163 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1164 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1165 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1166 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1167 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1168 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1169 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1170 +#define _IS_NONE_r11 1171 +#define _IS_OP_r03 1172 +#define _IS_OP_r13 1173 +#define _IS_OP_r23 1174 +#define _ITER_CHECK_LIST_r02 1175 +#define _ITER_CHECK_LIST_r12 1176 +#define _ITER_CHECK_LIST_r22 1177 +#define _ITER_CHECK_LIST_r33 1178 +#define _ITER_CHECK_RANGE_r02 1179 +#define _ITER_CHECK_RANGE_r12 1180 +#define _ITER_CHECK_RANGE_r22 1181 +#define _ITER_CHECK_RANGE_r33 1182 +#define _ITER_CHECK_TUPLE_r02 1183 +#define _ITER_CHECK_TUPLE_r12 1184 +#define _ITER_CHECK_TUPLE_r22 1185 +#define _ITER_CHECK_TUPLE_r33 1186 +#define _ITER_JUMP_LIST_r02 1187 +#define _ITER_JUMP_LIST_r12 1188 +#define _ITER_JUMP_LIST_r22 1189 +#define _ITER_JUMP_LIST_r33 1190 +#define _ITER_JUMP_RANGE_r02 1191 +#define _ITER_JUMP_RANGE_r12 1192 +#define _ITER_JUMP_RANGE_r22 1193 +#define _ITER_JUMP_RANGE_r33 1194 +#define _ITER_JUMP_TUPLE_r02 1195 +#define _ITER_JUMP_TUPLE_r12 1196 +#define _ITER_JUMP_TUPLE_r22 1197 +#define _ITER_JUMP_TUPLE_r33 1198 +#define _ITER_NEXT_LIST_r23 1199 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1200 +#define _ITER_NEXT_RANGE_r03 1201 +#define _ITER_NEXT_RANGE_r13 1202 +#define _ITER_NEXT_RANGE_r23 1203 +#define _ITER_NEXT_TUPLE_r03 1204 +#define _ITER_NEXT_TUPLE_r13 1205 +#define _ITER_NEXT_TUPLE_r23 1206 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1207 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1208 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1209 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1210 +#define _JUMP_TO_TOP_r00 1211 +#define _LIST_APPEND_r10 1212 +#define _LIST_EXTEND_r11 1213 +#define _LOAD_ATTR_r10 1214 +#define _LOAD_ATTR_CLASS_r11 1215 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1216 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1217 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1218 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1219 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1220 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1221 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1222 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1223 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1224 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1225 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1226 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1227 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1228 +#define _LOAD_ATTR_MODULE_r12 1229 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1230 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1231 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1232 +#define _LOAD_ATTR_SLOT_r02 1233 +#define _LOAD_ATTR_SLOT_r12 1234 +#define _LOAD_ATTR_SLOT_r23 1235 +#define _LOAD_ATTR_WITH_HINT_r12 1236 +#define _LOAD_BUILD_CLASS_r01 1237 +#define _LOAD_BYTECODE_r00 1238 +#define _LOAD_COMMON_CONSTANT_r01 1239 +#define _LOAD_COMMON_CONSTANT_r12 1240 +#define _LOAD_COMMON_CONSTANT_r23 1241 +#define _LOAD_CONST_r01 1242 +#define _LOAD_CONST_r12 1243 +#define _LOAD_CONST_r23 1244 +#define _LOAD_CONST_INLINE_r01 1245 +#define _LOAD_CONST_INLINE_r12 1246 +#define _LOAD_CONST_INLINE_r23 1247 +#define _LOAD_CONST_INLINE_BORROW_r01 1248 +#define _LOAD_CONST_INLINE_BORROW_r12 1249 +#define _LOAD_CONST_INLINE_BORROW_r23 1250 +#define _LOAD_CONST_UNDER_INLINE_r02 1251 +#define _LOAD_CONST_UNDER_INLINE_r12 1252 +#define _LOAD_CONST_UNDER_INLINE_r23 1253 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1254 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1255 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1256 +#define _LOAD_DEREF_r01 1257 +#define _LOAD_FAST_r01 1258 +#define _LOAD_FAST_r12 1259 +#define _LOAD_FAST_r23 1260 +#define _LOAD_FAST_0_r01 1261 +#define _LOAD_FAST_0_r12 1262 +#define _LOAD_FAST_0_r23 1263 +#define _LOAD_FAST_1_r01 1264 +#define _LOAD_FAST_1_r12 1265 +#define _LOAD_FAST_1_r23 1266 +#define _LOAD_FAST_2_r01 1267 +#define _LOAD_FAST_2_r12 1268 +#define _LOAD_FAST_2_r23 1269 +#define _LOAD_FAST_3_r01 1270 +#define _LOAD_FAST_3_r12 1271 +#define _LOAD_FAST_3_r23 1272 +#define _LOAD_FAST_4_r01 1273 +#define _LOAD_FAST_4_r12 1274 +#define _LOAD_FAST_4_r23 1275 +#define _LOAD_FAST_5_r01 1276 +#define _LOAD_FAST_5_r12 1277 +#define _LOAD_FAST_5_r23 1278 +#define _LOAD_FAST_6_r01 1279 +#define _LOAD_FAST_6_r12 1280 +#define _LOAD_FAST_6_r23 1281 +#define _LOAD_FAST_7_r01 1282 +#define _LOAD_FAST_7_r12 1283 +#define _LOAD_FAST_7_r23 1284 +#define _LOAD_FAST_AND_CLEAR_r01 1285 +#define _LOAD_FAST_AND_CLEAR_r12 1286 +#define _LOAD_FAST_AND_CLEAR_r23 1287 +#define _LOAD_FAST_BORROW_r01 1288 +#define _LOAD_FAST_BORROW_r12 1289 +#define _LOAD_FAST_BORROW_r23 1290 +#define _LOAD_FAST_BORROW_0_r01 1291 +#define _LOAD_FAST_BORROW_0_r12 1292 +#define _LOAD_FAST_BORROW_0_r23 1293 +#define _LOAD_FAST_BORROW_1_r01 1294 +#define _LOAD_FAST_BORROW_1_r12 1295 +#define _LOAD_FAST_BORROW_1_r23 1296 +#define _LOAD_FAST_BORROW_2_r01 1297 +#define _LOAD_FAST_BORROW_2_r12 1298 +#define _LOAD_FAST_BORROW_2_r23 1299 +#define _LOAD_FAST_BORROW_3_r01 1300 +#define _LOAD_FAST_BORROW_3_r12 1301 +#define _LOAD_FAST_BORROW_3_r23 1302 +#define _LOAD_FAST_BORROW_4_r01 1303 +#define _LOAD_FAST_BORROW_4_r12 1304 +#define _LOAD_FAST_BORROW_4_r23 1305 +#define _LOAD_FAST_BORROW_5_r01 1306 +#define _LOAD_FAST_BORROW_5_r12 1307 +#define _LOAD_FAST_BORROW_5_r23 1308 +#define _LOAD_FAST_BORROW_6_r01 1309 +#define _LOAD_FAST_BORROW_6_r12 1310 +#define _LOAD_FAST_BORROW_6_r23 1311 +#define _LOAD_FAST_BORROW_7_r01 1312 +#define _LOAD_FAST_BORROW_7_r12 1313 +#define _LOAD_FAST_BORROW_7_r23 1314 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1315 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1316 +#define _LOAD_FAST_CHECK_r01 1317 +#define _LOAD_FAST_CHECK_r12 1318 +#define _LOAD_FAST_CHECK_r23 1319 +#define _LOAD_FAST_LOAD_FAST_r02 1320 +#define _LOAD_FAST_LOAD_FAST_r13 1321 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1322 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1323 +#define _LOAD_GLOBAL_r00 1324 +#define _LOAD_GLOBAL_BUILTINS_r01 1325 +#define _LOAD_GLOBAL_MODULE_r01 1326 +#define _LOAD_LOCALS_r01 1327 +#define _LOAD_LOCALS_r12 1328 +#define _LOAD_LOCALS_r23 1329 +#define _LOAD_NAME_r01 1330 +#define _LOAD_SMALL_INT_r01 1331 +#define _LOAD_SMALL_INT_r12 1332 +#define _LOAD_SMALL_INT_r23 1333 +#define _LOAD_SMALL_INT_0_r01 1334 +#define _LOAD_SMALL_INT_0_r12 1335 +#define _LOAD_SMALL_INT_0_r23 1336 +#define _LOAD_SMALL_INT_1_r01 1337 +#define _LOAD_SMALL_INT_1_r12 1338 +#define _LOAD_SMALL_INT_1_r23 1339 +#define _LOAD_SMALL_INT_2_r01 1340 +#define _LOAD_SMALL_INT_2_r12 1341 +#define _LOAD_SMALL_INT_2_r23 1342 +#define _LOAD_SMALL_INT_3_r01 1343 +#define _LOAD_SMALL_INT_3_r12 1344 +#define _LOAD_SMALL_INT_3_r23 1345 +#define _LOAD_SPECIAL_r00 1346 +#define _LOAD_SUPER_ATTR_ATTR_r31 1347 +#define _LOAD_SUPER_ATTR_METHOD_r32 1348 +#define _LOCK_OBJECT_r01 1349 +#define _LOCK_OBJECT_r11 1350 +#define _LOCK_OBJECT_r22 1351 +#define _LOCK_OBJECT_r33 1352 +#define _MAKE_CALLARGS_A_TUPLE_r33 1353 +#define _MAKE_CELL_r00 1354 +#define _MAKE_FUNCTION_r11 1355 +#define _MAKE_HEAP_SAFE_r01 1356 +#define _MAKE_HEAP_SAFE_r11 1357 +#define _MAKE_HEAP_SAFE_r22 1358 +#define _MAKE_HEAP_SAFE_r33 1359 +#define _MAKE_WARM_r00 1360 +#define _MAKE_WARM_r11 1361 +#define _MAKE_WARM_r22 1362 +#define _MAKE_WARM_r33 1363 +#define _MAP_ADD_r20 1364 +#define _MATCH_CLASS_r33 1365 +#define _MATCH_KEYS_r23 1366 +#define _MATCH_MAPPING_r02 1367 +#define _MATCH_MAPPING_r12 1368 +#define _MATCH_MAPPING_r23 1369 +#define _MATCH_SEQUENCE_r02 1370 +#define _MATCH_SEQUENCE_r12 1371 +#define _MATCH_SEQUENCE_r23 1372 +#define _MAYBE_EXPAND_METHOD_r00 1373 +#define _MAYBE_EXPAND_METHOD_KW_r11 1374 +#define _MONITOR_CALL_r00 1375 +#define _MONITOR_CALL_KW_r11 1376 +#define _MONITOR_JUMP_BACKWARD_r00 1377 +#define _MONITOR_JUMP_BACKWARD_r11 1378 +#define _MONITOR_JUMP_BACKWARD_r22 1379 +#define _MONITOR_JUMP_BACKWARD_r33 1380 +#define _MONITOR_RESUME_r00 1381 +#define _NOP_r00 1382 +#define _NOP_r11 1383 +#define _NOP_r22 1384 +#define _NOP_r33 1385 +#define _POP_CALL_r20 1386 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1387 +#define _POP_CALL_ONE_r30 1388 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1389 +#define _POP_CALL_TWO_r30 1390 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1391 +#define _POP_EXCEPT_r10 1392 +#define _POP_ITER_r20 1393 +#define _POP_JUMP_IF_FALSE_r00 1394 +#define _POP_JUMP_IF_FALSE_r10 1395 +#define _POP_JUMP_IF_FALSE_r21 1396 +#define _POP_JUMP_IF_FALSE_r32 1397 +#define _POP_JUMP_IF_TRUE_r00 1398 +#define _POP_JUMP_IF_TRUE_r10 1399 +#define _POP_JUMP_IF_TRUE_r21 1400 +#define _POP_JUMP_IF_TRUE_r32 1401 +#define _POP_TOP_r10 1402 +#define _POP_TOP_FLOAT_r00 1403 +#define _POP_TOP_FLOAT_r10 1404 +#define _POP_TOP_FLOAT_r21 1405 +#define _POP_TOP_FLOAT_r32 1406 +#define _POP_TOP_INT_r00 1407 +#define _POP_TOP_INT_r10 1408 +#define _POP_TOP_INT_r21 1409 +#define _POP_TOP_INT_r32 1410 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1411 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1412 +#define _POP_TOP_NOP_r00 1413 +#define _POP_TOP_NOP_r10 1414 +#define _POP_TOP_NOP_r21 1415 +#define _POP_TOP_NOP_r32 1416 +#define _POP_TOP_UNICODE_r00 1417 +#define _POP_TOP_UNICODE_r10 1418 +#define _POP_TOP_UNICODE_r21 1419 +#define _POP_TOP_UNICODE_r32 1420 +#define _POP_TWO_r20 1421 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1422 +#define _PUSH_EXC_INFO_r02 1423 +#define _PUSH_EXC_INFO_r12 1424 +#define _PUSH_EXC_INFO_r23 1425 +#define _PUSH_FRAME_r10 1426 +#define _PUSH_NULL_r01 1427 +#define _PUSH_NULL_r12 1428 +#define _PUSH_NULL_r23 1429 +#define _PUSH_NULL_CONDITIONAL_r00 1430 +#define _PY_FRAME_EX_r31 1431 +#define _PY_FRAME_GENERAL_r01 1432 +#define _PY_FRAME_KW_r11 1433 +#define _REPLACE_WITH_TRUE_r02 1434 +#define _REPLACE_WITH_TRUE_r12 1435 +#define _REPLACE_WITH_TRUE_r23 1436 +#define _RESUME_CHECK_r00 1437 +#define _RESUME_CHECK_r11 1438 +#define _RESUME_CHECK_r22 1439 +#define _RESUME_CHECK_r33 1440 +#define _RETURN_GENERATOR_r01 1441 +#define _RETURN_VALUE_r11 1442 +#define _SAVE_RETURN_OFFSET_r00 1443 +#define _SAVE_RETURN_OFFSET_r11 1444 +#define _SAVE_RETURN_OFFSET_r22 1445 +#define _SAVE_RETURN_OFFSET_r33 1446 +#define _SEND_r33 1447 +#define _SEND_GEN_FRAME_r33 1448 +#define _SETUP_ANNOTATIONS_r00 1449 +#define _SET_ADD_r10 1450 +#define _SET_FUNCTION_ATTRIBUTE_r01 1451 +#define _SET_FUNCTION_ATTRIBUTE_r11 1452 +#define _SET_FUNCTION_ATTRIBUTE_r21 1453 +#define _SET_FUNCTION_ATTRIBUTE_r32 1454 +#define _SET_IP_r00 1455 +#define _SET_IP_r11 1456 +#define _SET_IP_r22 1457 +#define _SET_IP_r33 1458 +#define _SET_UPDATE_r11 1459 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1460 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1461 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1462 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1463 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1464 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1465 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1466 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1467 +#define _SPILL_OR_RELOAD_r01 1468 +#define _SPILL_OR_RELOAD_r02 1469 +#define _SPILL_OR_RELOAD_r03 1470 +#define _SPILL_OR_RELOAD_r10 1471 +#define _SPILL_OR_RELOAD_r12 1472 +#define _SPILL_OR_RELOAD_r13 1473 +#define _SPILL_OR_RELOAD_r20 1474 +#define _SPILL_OR_RELOAD_r21 1475 +#define _SPILL_OR_RELOAD_r23 1476 +#define _SPILL_OR_RELOAD_r30 1477 +#define _SPILL_OR_RELOAD_r31 1478 +#define _SPILL_OR_RELOAD_r32 1479 +#define _START_EXECUTOR_r00 1480 +#define _STORE_ATTR_r20 1481 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1482 +#define _STORE_ATTR_SLOT_r21 1483 +#define _STORE_ATTR_WITH_HINT_r21 1484 +#define _STORE_DEREF_r10 1485 +#define _STORE_FAST_LOAD_FAST_r11 1486 +#define _STORE_FAST_STORE_FAST_r20 1487 +#define _STORE_GLOBAL_r10 1488 +#define _STORE_NAME_r10 1489 +#define _STORE_SLICE_r30 1490 +#define _STORE_SUBSCR_r30 1491 +#define _STORE_SUBSCR_DICT_r31 1492 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1493 +#define _STORE_SUBSCR_LIST_INT_r32 1494 +#define _SWAP_r11 1495 +#define _SWAP_2_r02 1496 +#define _SWAP_2_r12 1497 +#define _SWAP_2_r22 1498 +#define _SWAP_2_r33 1499 +#define _SWAP_3_r03 1500 +#define _SWAP_3_r13 1501 +#define _SWAP_3_r23 1502 +#define _SWAP_3_r33 1503 +#define _SWAP_FAST_r01 1504 +#define _SWAP_FAST_r11 1505 +#define _SWAP_FAST_r22 1506 +#define _SWAP_FAST_r33 1507 +#define _SWAP_FAST_0_r01 1508 +#define _SWAP_FAST_0_r11 1509 +#define _SWAP_FAST_0_r22 1510 +#define _SWAP_FAST_0_r33 1511 +#define _SWAP_FAST_1_r01 1512 +#define _SWAP_FAST_1_r11 1513 +#define _SWAP_FAST_1_r22 1514 +#define _SWAP_FAST_1_r33 1515 +#define _SWAP_FAST_2_r01 1516 +#define _SWAP_FAST_2_r11 1517 +#define _SWAP_FAST_2_r22 1518 +#define _SWAP_FAST_2_r33 1519 +#define _SWAP_FAST_3_r01 1520 +#define _SWAP_FAST_3_r11 1521 +#define _SWAP_FAST_3_r22 1522 +#define _SWAP_FAST_3_r33 1523 +#define _SWAP_FAST_4_r01 1524 +#define _SWAP_FAST_4_r11 1525 +#define _SWAP_FAST_4_r22 1526 +#define _SWAP_FAST_4_r33 1527 +#define _SWAP_FAST_5_r01 1528 +#define _SWAP_FAST_5_r11 1529 +#define _SWAP_FAST_5_r22 1530 +#define _SWAP_FAST_5_r33 1531 +#define _SWAP_FAST_6_r01 1532 +#define _SWAP_FAST_6_r11 1533 +#define _SWAP_FAST_6_r22 1534 +#define _SWAP_FAST_6_r33 1535 +#define _SWAP_FAST_7_r01 1536 +#define _SWAP_FAST_7_r11 1537 +#define _SWAP_FAST_7_r22 1538 +#define _SWAP_FAST_7_r33 1539 +#define _TIER2_RESUME_CHECK_r00 1540 +#define _TIER2_RESUME_CHECK_r11 1541 +#define _TIER2_RESUME_CHECK_r22 1542 +#define _TIER2_RESUME_CHECK_r33 1543 +#define _TO_BOOL_r11 1544 +#define _TO_BOOL_BOOL_r01 1545 +#define _TO_BOOL_BOOL_r11 1546 +#define _TO_BOOL_BOOL_r22 1547 +#define _TO_BOOL_BOOL_r33 1548 +#define _TO_BOOL_INT_r02 1549 +#define _TO_BOOL_INT_r12 1550 +#define _TO_BOOL_INT_r23 1551 +#define _TO_BOOL_LIST_r02 1552 +#define _TO_BOOL_LIST_r12 1553 +#define _TO_BOOL_LIST_r23 1554 +#define _TO_BOOL_NONE_r01 1555 +#define _TO_BOOL_NONE_r11 1556 +#define _TO_BOOL_NONE_r22 1557 +#define _TO_BOOL_NONE_r33 1558 +#define _TO_BOOL_STR_r02 1559 +#define _TO_BOOL_STR_r12 1560 +#define _TO_BOOL_STR_r23 1561 +#define _TRACE_RECORD_r00 1562 +#define _UNARY_INVERT_r12 1563 +#define _UNARY_NEGATIVE_r12 1564 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1565 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1566 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1567 +#define _UNARY_NOT_r01 1568 +#define _UNARY_NOT_r11 1569 +#define _UNARY_NOT_r22 1570 +#define _UNARY_NOT_r33 1571 +#define _UNPACK_EX_r10 1572 +#define _UNPACK_SEQUENCE_r10 1573 +#define _UNPACK_SEQUENCE_LIST_r10 1574 +#define _UNPACK_SEQUENCE_TUPLE_r10 1575 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1576 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1577 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1578 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1579 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1580 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1581 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1582 +#define _WITH_EXCEPT_START_r33 1583 +#define _YIELD_VALUE_r11 1584 +#define MAX_UOP_REGS_ID 1584 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 4e16c3040c7..52bec0bd0b8 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -108,6 +108,12 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_OP_MULTIPLY_INT] = HAS_EXIT_FLAG | HAS_PURE_FLAG, [_BINARY_OP_ADD_INT] = HAS_EXIT_FLAG | HAS_PURE_FLAG, [_BINARY_OP_SUBTRACT_INT] = HAS_EXIT_FLAG | HAS_PURE_FLAG, + [_BINARY_OP_ADD_INT_INPLACE] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBTRACT_INT_INPLACE] = HAS_EXIT_FLAG, + [_BINARY_OP_MULTIPLY_INT_INPLACE] = HAS_EXIT_FLAG, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT] = HAS_EXIT_FLAG, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT] = HAS_EXIT_FLAG, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT] = HAS_EXIT_FLAG, [_GUARD_NOS_FLOAT] = HAS_EXIT_FLAG, [_GUARD_TOS_FLOAT] = HAS_EXIT_FLAG, [_BINARY_OP_MULTIPLY_FLOAT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_PURE_FLAG, @@ -1084,6 +1090,60 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_BINARY_OP_ADD_INT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_ADD_INT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_ADD_INT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_ADD_INT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_SUBTRACT_INT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_SUBTRACT_INT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_SUBTRACT_INT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_SUBTRACT_INT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_MULTIPLY_INT_INPLACE] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_MULTIPLY_INT_INPLACE_r03 }, + { 3, 1, _BINARY_OP_MULTIPLY_INT_INPLACE_r13 }, + { 3, 2, _BINARY_OP_MULTIPLY_INT_INPLACE_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT] = { + .best = { 0, 1, 2, 2 }, + .entries = { + { 3, 0, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 }, + { 3, 1, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 }, + { 3, 2, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 }, + { -1, -1, -1 }, + }, + }, [_GUARD_NOS_FLOAT] = { .best = { 0, 1, 2, 3 }, .entries = { @@ -3960,6 +4020,24 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_INT_r03] = _BINARY_OP_SUBTRACT_INT, [_BINARY_OP_SUBTRACT_INT_r13] = _BINARY_OP_SUBTRACT_INT, [_BINARY_OP_SUBTRACT_INT_r23] = _BINARY_OP_SUBTRACT_INT, + [_BINARY_OP_ADD_INT_INPLACE_r03] = _BINARY_OP_ADD_INT_INPLACE, + [_BINARY_OP_ADD_INT_INPLACE_r13] = _BINARY_OP_ADD_INT_INPLACE, + [_BINARY_OP_ADD_INT_INPLACE_r23] = _BINARY_OP_ADD_INT_INPLACE, + [_BINARY_OP_SUBTRACT_INT_INPLACE_r03] = _BINARY_OP_SUBTRACT_INT_INPLACE, + [_BINARY_OP_SUBTRACT_INT_INPLACE_r13] = _BINARY_OP_SUBTRACT_INT_INPLACE, + [_BINARY_OP_SUBTRACT_INT_INPLACE_r23] = _BINARY_OP_SUBTRACT_INT_INPLACE, + [_BINARY_OP_MULTIPLY_INT_INPLACE_r03] = _BINARY_OP_MULTIPLY_INT_INPLACE, + [_BINARY_OP_MULTIPLY_INT_INPLACE_r13] = _BINARY_OP_MULTIPLY_INT_INPLACE, + [_BINARY_OP_MULTIPLY_INT_INPLACE_r23] = _BINARY_OP_MULTIPLY_INT_INPLACE, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r03] = _BINARY_OP_ADD_INT_INPLACE_RIGHT, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r13] = _BINARY_OP_ADD_INT_INPLACE_RIGHT, + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r23] = _BINARY_OP_ADD_INT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03] = _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13] = _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23] = _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03] = _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13] = _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23] = _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, [_GUARD_NOS_FLOAT_r02] = _GUARD_NOS_FLOAT, [_GUARD_NOS_FLOAT_r12] = _GUARD_NOS_FLOAT, [_GUARD_NOS_FLOAT_r22] = _GUARD_NOS_FLOAT, @@ -4633,6 +4711,14 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_ADD_INT_r03] = "_BINARY_OP_ADD_INT_r03", [_BINARY_OP_ADD_INT_r13] = "_BINARY_OP_ADD_INT_r13", [_BINARY_OP_ADD_INT_r23] = "_BINARY_OP_ADD_INT_r23", + [_BINARY_OP_ADD_INT_INPLACE] = "_BINARY_OP_ADD_INT_INPLACE", + [_BINARY_OP_ADD_INT_INPLACE_r03] = "_BINARY_OP_ADD_INT_INPLACE_r03", + [_BINARY_OP_ADD_INT_INPLACE_r13] = "_BINARY_OP_ADD_INT_INPLACE_r13", + [_BINARY_OP_ADD_INT_INPLACE_r23] = "_BINARY_OP_ADD_INT_INPLACE_r23", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r03] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT_r03", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r13] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT_r13", + [_BINARY_OP_ADD_INT_INPLACE_RIGHT_r23] = "_BINARY_OP_ADD_INT_INPLACE_RIGHT_r23", [_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE", [_BINARY_OP_ADD_UNICODE_r03] = "_BINARY_OP_ADD_UNICODE_r03", [_BINARY_OP_ADD_UNICODE_r13] = "_BINARY_OP_ADD_UNICODE_r13", @@ -4657,6 +4743,14 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_MULTIPLY_INT_r03] = "_BINARY_OP_MULTIPLY_INT_r03", [_BINARY_OP_MULTIPLY_INT_r13] = "_BINARY_OP_MULTIPLY_INT_r13", [_BINARY_OP_MULTIPLY_INT_r23] = "_BINARY_OP_MULTIPLY_INT_r23", + [_BINARY_OP_MULTIPLY_INT_INPLACE] = "_BINARY_OP_MULTIPLY_INT_INPLACE", + [_BINARY_OP_MULTIPLY_INT_INPLACE_r03] = "_BINARY_OP_MULTIPLY_INT_INPLACE_r03", + [_BINARY_OP_MULTIPLY_INT_INPLACE_r13] = "_BINARY_OP_MULTIPLY_INT_INPLACE_r13", + [_BINARY_OP_MULTIPLY_INT_INPLACE_r23] = "_BINARY_OP_MULTIPLY_INT_INPLACE_r23", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13", + [_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23] = "_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23", [_BINARY_OP_SUBSCR_CHECK_FUNC] = "_BINARY_OP_SUBSCR_CHECK_FUNC", [_BINARY_OP_SUBSCR_CHECK_FUNC_r23] = "_BINARY_OP_SUBSCR_CHECK_FUNC_r23", [_BINARY_OP_SUBSCR_DICT] = "_BINARY_OP_SUBSCR_DICT", @@ -4696,6 +4790,14 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_BINARY_OP_SUBTRACT_INT_r03] = "_BINARY_OP_SUBTRACT_INT_r03", [_BINARY_OP_SUBTRACT_INT_r13] = "_BINARY_OP_SUBTRACT_INT_r13", [_BINARY_OP_SUBTRACT_INT_r23] = "_BINARY_OP_SUBTRACT_INT_r23", + [_BINARY_OP_SUBTRACT_INT_INPLACE] = "_BINARY_OP_SUBTRACT_INT_INPLACE", + [_BINARY_OP_SUBTRACT_INT_INPLACE_r03] = "_BINARY_OP_SUBTRACT_INT_INPLACE_r03", + [_BINARY_OP_SUBTRACT_INT_INPLACE_r13] = "_BINARY_OP_SUBTRACT_INT_INPLACE_r13", + [_BINARY_OP_SUBTRACT_INT_INPLACE_r23] = "_BINARY_OP_SUBTRACT_INT_INPLACE_r23", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13", + [_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23] = "_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23", [_BINARY_SLICE] = "_BINARY_SLICE", [_BINARY_SLICE_r31] = "_BINARY_SLICE_r31", [_BUILD_INTERPOLATION] = "_BUILD_INTERPOLATION", @@ -6006,6 +6108,18 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _BINARY_OP_SUBTRACT_INT: return 2; + case _BINARY_OP_ADD_INT_INPLACE: + return 2; + case _BINARY_OP_SUBTRACT_INT_INPLACE: + return 2; + case _BINARY_OP_MULTIPLY_INT_INPLACE: + return 2; + case _BINARY_OP_ADD_INT_INPLACE_RIGHT: + return 2; + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT: + return 2; + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT: + return 2; case _GUARD_NOS_FLOAT: return 0; case _GUARD_TOS_FLOAT: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 2005dd9b086..8d3da8b5a22 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3390,6 +3390,154 @@ def testfunc(args): uops = get_opnames(ex) self.assertNotIn("_UNARY_NEGATIVE_FLOAT_INPLACE", uops) + def test_int_add_inplace_unique_lhs(self): + # a * b produces a unique compact int; adding c reuses it in place + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += a * b + c + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 4000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 10000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_ADD_INT_INPLACE", uops) + + def test_int_add_inplace_unique_rhs(self): + # a * b produces a unique compact int on the right side of + + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += c + a * b + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 4000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 10000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_ADD_INT_INPLACE_RIGHT", uops) + + def test_int_add_no_inplace_non_unique(self): + # Both operands of a + b are locals — neither is unique, + # so the first add uses the regular op. But total += (a+b) + # has a unique RHS (result of a+b), so it uses _INPLACE_RIGHT. + def testfunc(args): + a, b, n = args + total = 0 + for _ in range(n): + total += a + b + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 5000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # a + b: both are locals, no inplace + self.assertIn("_BINARY_OP_ADD_INT", uops) + # total += result: result is unique RHS + self.assertIn("_BINARY_OP_ADD_INT_INPLACE_RIGHT", uops) + # No LHS inplace variant for the first add + self.assertNotIn("_BINARY_OP_ADD_INT_INPLACE", uops) + + def test_int_add_inplace_small_int_result(self): + # When the result is a small int, the inplace path falls back + # to _PyCompactLong_Add. Verify correctness (no singleton corruption). + def testfunc(args): + a, b, n = args + total = 0 + for _ in range(n): + total += a * b + 1 # a*b=6, +1=7, small int + return total + + res, ex = self._run_with_optimizer(testfunc, (2, 3, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 7) + # Verify small int singletons are not corrupted + self.assertEqual(7, 3 + 4) + + def test_int_subtract_inplace_unique_lhs(self): + # a * b produces a unique compact int; subtracting c reuses it + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += a * b - c + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 1000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 5000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBTRACT_INT_INPLACE", uops) + + def test_int_subtract_inplace_unique_rhs(self): + # a * b produces a unique compact int on the right of - + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += c - a * b + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 10000, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 4000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT", uops) + + def test_int_multiply_inplace_unique_lhs(self): + # (a + b) produces a unique compact int; multiplying by c reuses it + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += (a + b) * c + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3000, 4, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 20000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_MULTIPLY_INT_INPLACE", uops) + + def test_int_multiply_inplace_unique_rhs(self): + # (a + b) produces a unique compact int on the right side of * + def testfunc(args): + a, b, c, n = args + total = 0 + for _ in range(n): + total += c * (a + b) + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3000, 4, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 20000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT", uops) + + def test_int_inplace_chain_propagation(self): + # a * b + c * d: both products are unique, the + reuses one; + # result of + is also unique for the subsequent += + def testfunc(args): + a, b, c, d, n = args + total = 0 + for _ in range(n): + total += a * b + c * d + return total + + res, ex = self._run_with_optimizer(testfunc, (2000, 3, 4000, 5, TIER2_THRESHOLD)) + self.assertEqual(res, TIER2_THRESHOLD * 26000) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + inplace_add = ( + "_BINARY_OP_ADD_INT_INPLACE" in uops + or "_BINARY_OP_ADD_INT_INPLACE_RIGHT" in uops + ) + self.assertTrue(inplace_add, + "Expected an inplace add for unique intermediate results") + def test_load_attr_instance_value(self): def testfunc(n): class C(): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst new file mode 100644 index 00000000000..fdbdb6a285f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst @@ -0,0 +1,3 @@ +Optimize compact integer arithmetic in the JIT by mutating +uniquely-referenced operands in place, avoiding allocation of a new int +object. Speeds up the pyperformance ``spectral_norm`` benchmark by ~10%. diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 18fea9ae4a2..92f5b5d530c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -708,6 +708,63 @@ dummy_func( macro(BINARY_OP_SUBTRACT_INT) = _GUARD_TOS_INT + _GUARD_NOS_INT + unused/5 + _BINARY_OP_SUBTRACT_INT + _POP_TOP_INT + _POP_TOP_INT; + // Inplace compact int ops: mutate the uniquely-referenced operand + // when possible. The op handles decref of TARGET internally so + // the following _POP_TOP_INT becomes _POP_TOP_NOP. Tier 2 only. + tier2 op(_BINARY_OP_ADD_INT_INPLACE, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_SUBTRACT_INT_INPLACE, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_MULTIPLY_INT_INPLACE, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_ADD_INT_INPLACE_RIGHT, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + + tier2 op(_BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, (left, right -- res, l, r)) { + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + EXIT_IF(PyStackRef_IsNull(_int_inplace_res)); + res = _int_inplace_res; + l = left; + r = right; + INPUTS_DEAD(); + } + op(_GUARD_NOS_FLOAT, (left, unused -- left, unused)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); EXIT_IF(!PyFloat_CheckExact(left_o)); diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index de629deddf3..ad790c03865 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -562,3 +562,46 @@ gen_try_set_executing(PyGenObject *gen) ((PyFloatObject *)PyStackRef_AsPyObjectBorrow(TARGET)) \ ->ob_fval = _dres; \ } while (0) + +// Inplace compact int operation. TARGET is expected to be uniquely +// referenced at the optimizer level, but at runtime it may be a +// cached small int singleton. We check _Py_IsImmortal on TARGET +// to decide whether inplace mutation is safe. +// +// After the macro, _int_inplace_res holds the result (may be NULL +// on allocation failure). On success, TARGET was mutated in place +// and _int_inplace_res is a DUP'd reference to it. On fallback +// (small int target, small int result, or overflow), _int_inplace_res +// is from FUNC (_PyCompactLong_Add etc.). +// FUNC is the fallback function (_PyCompactLong_Add etc.) +#define INT_INPLACE_OP(left, right, TARGET, OP, FUNC) \ + _PyStackRef _int_inplace_res = PyStackRef_NULL; \ + do { \ + PyObject *target_o = PyStackRef_AsPyObjectBorrow(TARGET); \ + if (_Py_IsImmortal(target_o)) { \ + break; \ + } \ + assert(_PyObject_IsUniquelyReferenced(target_o)); \ + Py_ssize_t left_val = _PyLong_CompactValue( \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(left)); \ + Py_ssize_t right_val = _PyLong_CompactValue( \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(right)); \ + Py_ssize_t result = left_val OP right_val; \ + if (!_PY_IS_SMALL_INT(result) \ + && ((twodigits)((stwodigits)result) + PyLong_MASK \ + < (twodigits)PyLong_MASK + PyLong_BASE)) \ + { \ + _PyLong_SetSignAndDigitCount( \ + (PyLongObject *)target_o, result < 0 ? -1 : 1, 1); \ + ((PyLongObject *)target_o)->long_value.ob_digit[0] = \ + (digit)(result < 0 ? -result : result); \ + _int_inplace_res = PyStackRef_DUP(TARGET); \ + break; \ + } \ + } while (0); \ + if (PyStackRef_IsNull(_int_inplace_res)) { \ + _int_inplace_res = FUNC( \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(left), \ + (PyLongObject *)PyStackRef_AsPyObjectBorrow(right)); \ + } + diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 46740b3954e..36353b77f1b 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4504,6 +4504,552 @@ break; } + case _BINARY_OP_ADD_INT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, left, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, left, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, left, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, right, +, _PyCompactLong_Add); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, right, -, _PyCompactLong_Subtract); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + right = _stack_item_0; + left = stack_pointer[-1]; + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = right; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef right; + _PyStackRef left; + _PyStackRef res; + _PyStackRef l; + _PyStackRef r; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + right = _stack_item_1; + left = _stack_item_0; + INT_INPLACE_OP(left, right, right, *, _PyCompactLong_Multiply); + if (PyStackRef_IsNull(_int_inplace_res)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = right; + _tos_cache0 = left; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + res = _int_inplace_res; + l = left; + r = right; + _tos_cache2 = r; + _tos_cache1 = l; + _tos_cache0 = res; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_NOS_FLOAT_r02: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 792f83cdbd2..2fd235a2dda 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -309,21 +309,41 @@ dummy_func(void) { } op(_BINARY_OP_ADD_INT, (left, right -- res, l, r)) { - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE_RIGHT, 0, 0); + } + // Result may be a unique compact int or a cached small int + // at runtime. Mark as unique; inplace ops verify at runtime. + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, res); } op(_BINARY_OP_SUBTRACT_INT, (left, right -- res, l, r)) { - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, res); } op(_BINARY_OP_MULTIPLY_INT, (left, right -- res, l, r)) { - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, res); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 7539133fb92..8634189c707 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -596,7 +596,13 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; if ( @@ -660,7 +666,13 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_ADD_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; if ( @@ -724,7 +736,13 @@ JitOptRef r; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = sym_new_compact_int(ctx); + if (PyJitRef_IsUnique(left)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE, 0, 0); + } + else if (PyJitRef_IsUnique(right)) { + REPLACE_OP(this_instr, _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT, 0, 0); + } + res = PyJitRef_MakeUnique(sym_new_compact_int(ctx)); l = left; r = right; if ( @@ -780,6 +798,102 @@ break; } + case _BINARY_OP_ADD_INT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_ADD_INT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + + case _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT: { + JitOptRef res; + JitOptRef l; + JitOptRef r; + res = sym_new_not_null(ctx); + l = sym_new_not_null(ctx); + r = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = res; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _GUARD_NOS_FLOAT: { JitOptRef left; left = stack_pointer[-2]; From 3681d47a440865aead912a054d4599087b4270dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Fri, 3 Apr 2026 17:31:25 +0200 Subject: [PATCH 388/775] gh-143930: Tweak the exception message and increase test coverage (GH-146476) --- Lib/test/test_webbrowser.py | 21 +++++++++++++------ Lib/webbrowser.py | 2 +- ...-01-16-12-04-49.gh-issue-143930.zYC5x3.rst | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index d5bb1400d27..ea161ea1a43 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -57,6 +57,14 @@ def _test(self, meth, *, args=[URL], kw={}, options, arguments): popen_args.pop(popen_args.index(option)) self.assertEqual(popen_args, arguments) + def test_reject_dash_prefixes(self): + browser = self.browser_class(name=CMD_NAME) + with self.assertRaisesRegex( + ValueError, + r"^Invalid URL \(leading dash disallowed\): '--key=val http.*'$" + ): + browser.open(f"--key=val {URL}") + class GenericBrowserCommandTest(CommandTestMixin, unittest.TestCase): @@ -67,11 +75,6 @@ def test_open(self): options=[], arguments=[URL]) - def test_reject_dash_prefixes(self): - browser = self.browser_class(name=CMD_NAME) - with self.assertRaises(ValueError): - browser.open(f"--key=val {URL}") - class BackgroundBrowserCommandTest(CommandTestMixin, unittest.TestCase): @@ -326,7 +329,6 @@ def close(self): @unittest.skipUnless(sys.platform == "darwin", "macOS specific test") @requires_subprocess() class MacOSXOSAScriptTest(unittest.TestCase): - def setUp(self): # Ensure that 'BROWSER' is not set to 'open' or something else. # See: https://github.com/python/cpython/issues/131254. @@ -376,6 +378,13 @@ def test_explicit_browser(self): self.assertIn('tell application "safari"', script) self.assertIn('open location "https://python.org"', script) + def test_reject_dash_prefixes(self): + with self.assertRaisesRegex( + ValueError, + r"^Invalid URL \(leading dash disallowed\): '--key=val http.*'$" + ): + self.browser.open(f"--key=val {URL}") + class BrowserRegistrationTest(unittest.TestCase): diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index 9ead2990e81..deb6e64d174 100644 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -167,7 +167,7 @@ def open_new_tab(self, url): def _check_url(url): """Ensures that the URL is safe to pass to subprocesses as a parameter""" if url and url.lstrip().startswith("-"): - raise ValueError(f"Invalid URL: {url}") + raise ValueError(f"Invalid URL (leading dash disallowed): {url!r}") class GenericBrowser(BaseBrowser): diff --git a/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst b/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst index 0f27eae99a0..c561023c3c2 100644 --- a/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst +++ b/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst @@ -1 +1 @@ -Reject leading dashes in URLs passed to :func:`webbrowser.open` +Reject leading dashes in URLs passed to :func:`webbrowser.open`. From 198b04b75f7425c401ffe40a748688a89d28dd59 Mon Sep 17 00:00:00 2001 From: Hai Zhu Date: Fri, 3 Apr 2026 23:54:30 +0800 Subject: [PATCH 389/775] gh-146073: Add fitness/exit quality mechanism for JIT trace frontend (GH-147966) --- Include/cpython/pystats.h | 1 + Include/internal/pycore_interp_structs.h | 4 + Include/internal/pycore_optimizer.h | 20 +++- Python/optimizer.c | 130 +++++++++++++++++++++-- Python/pystate.c | 16 +++ Python/pystats.c | 1 + 6 files changed, 165 insertions(+), 7 deletions(-) diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h index e473110eca7..5d1f44988a6 100644 --- a/Include/cpython/pystats.h +++ b/Include/cpython/pystats.h @@ -144,6 +144,7 @@ typedef struct _optimization_stats { uint64_t unknown_callee; uint64_t trace_immediately_deopts; uint64_t executors_invalidated; + uint64_t fitness_terminated_traces; UOpStats opcode[PYSTATS_MAX_UOP_ID + 1]; uint64_t unsupported_opcode[256]; uint64_t trace_length_hist[_Py_UOP_HIST_SIZE]; diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index f76d4f41c55..0cebe1b4b9e 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -449,6 +449,10 @@ typedef struct _PyOptimizationConfig { uint16_t side_exit_initial_value; uint16_t side_exit_initial_backoff; + // Trace fitness thresholds + uint16_t fitness_initial; + uint16_t fitness_initial_side; + // Optimization flags bool specialization_enabled; bool uops_optimize_enabled; diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 2986afb142b..820ee32201c 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -15,6 +15,23 @@ extern "C" { #include "pycore_optimizer_types.h" #include +/* Default fitness configuration values for trace quality control. + * FITNESS_INITIAL and FITNESS_INITIAL_SIDE can be overridden via + * PYTHON_JIT_FITNESS_INITIAL and PYTHON_JIT_FITNESS_INITIAL_SIDE */ +#define FITNESS_PER_INSTRUCTION 2 +#define FITNESS_BRANCH_BASE 5 +#define FITNESS_INITIAL (FITNESS_PER_INSTRUCTION * 1000) +#define FITNESS_INITIAL_SIDE (FITNESS_INITIAL / 2) +#define FITNESS_BACKWARD_EDGE (FITNESS_INITIAL / 10) + +/* Exit quality constants for fitness-based trace termination. + * Higher values mean better places to stop the trace. */ + +#define EXIT_QUALITY_DEFAULT 200 +#define EXIT_QUALITY_CLOSE_LOOP (4 * EXIT_QUALITY_DEFAULT) +#define EXIT_QUALITY_ENTER_EXECUTOR (2 * EXIT_QUALITY_DEFAULT + 100) +#define EXIT_QUALITY_SPECIALIZABLE (EXIT_QUALITY_DEFAULT / 4) + typedef struct _PyJitUopBuffer { _PyUOpInstruction *start; @@ -101,7 +118,8 @@ typedef struct _PyJitTracerPreviousState { } _PyJitTracerPreviousState; typedef struct _PyJitTracerTranslatorState { - int jump_backward_seen; + int32_t fitness; // Current trace fitness, starts high, decrements + int frame_depth; // Current inline depth (0 = root frame) } _PyJitTracerTranslatorState; typedef struct _PyJitTracerState { diff --git a/Python/optimizer.c b/Python/optimizer.c index f09bf778587..c7a6b7e7465 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -549,8 +549,6 @@ dynamic_exit_uop[MAX_UOP_ID + 1] = { }; -#define CONFIDENCE_RANGE 1000 -#define CONFIDENCE_CUTOFF 333 #ifdef Py_DEBUG #define DPRINTF(level, ...) \ @@ -598,6 +596,46 @@ add_to_trace( ((uint32_t)((INSTR) - ((_Py_CODEUNIT *)(CODE)->co_code_adaptive))) +/* Compute branch fitness penalty based on how likely the traced path is. + * The penalty is small when the traced path is common, large when rare. + * A branch that historically goes the other way gets a heavy penalty. */ +static inline int +compute_branch_penalty(uint16_t history, bool branch_taken) +{ + int taken_count = _Py_popcount32((uint32_t)history); + int on_trace_count = branch_taken ? taken_count : 16 - taken_count; + int off_trace = 16 - on_trace_count; + /* Linear scaling: off_trace ranges from 0 (fully biased our way) + * to 16 (fully biased against us), so the penalty ranges from + * FITNESS_BRANCH_BASE to FITNESS_BRANCH_BASE + 32. */ + return FITNESS_BRANCH_BASE + off_trace * 2; +} + +/* Compute exit quality for the current trace position. + * Higher values mean better places to stop the trace. */ +static inline int32_t +compute_exit_quality(_Py_CODEUNIT *target_instr, int opcode, + const _PyJitTracerState *tracer) +{ + if (target_instr == tracer->initial_state.start_instr || + target_instr == tracer->initial_state.close_loop_instr) { + return EXIT_QUALITY_CLOSE_LOOP; + } + if (target_instr->op.code == ENTER_EXECUTOR) { + return EXIT_QUALITY_ENTER_EXECUTOR; + } + if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] > 0) { + return EXIT_QUALITY_SPECIALIZABLE; + } + return EXIT_QUALITY_DEFAULT; +} + +static inline int32_t +compute_frame_penalty(const _PyOptimizationConfig *cfg) +{ + return (int32_t)cfg->fitness_initial / 10 + 1; +} + static int is_terminator(const _PyUOpInstruction *uop) { @@ -637,6 +675,7 @@ _PyJit_translate_single_bytecode_to_trace( _Py_CODEUNIT *this_instr = tracer->prev_state.instr; _Py_CODEUNIT *target_instr = this_instr; uint32_t target = 0; + int end_trace_opcode = _DEOPT; target = Py_IsNone((PyObject *)old_code) ? (uint32_t)(target_instr - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR) @@ -734,16 +773,14 @@ _PyJit_translate_single_bytecode_to_trace( DPRINTF(2, "Unsupported: oparg too large\n"); unsupported: { - // Rewind to previous instruction and replace with _EXIT_TRACE. _PyUOpInstruction *curr = uop_buffer_last(trace); while (curr->opcode != _SET_IP && uop_buffer_length(trace) > 2) { trace->next--; curr = uop_buffer_last(trace); } - assert(curr->opcode == _SET_IP || uop_buffer_length(trace) == 2); if (curr->opcode == _SET_IP) { int32_t old_target = (int32_t)uop_get_target(curr); - curr->opcode = _DEOPT; + curr->opcode = end_trace_opcode; curr->format = UOP_FORMAT_TARGET; curr->target = old_target; } @@ -763,6 +800,23 @@ _PyJit_translate_single_bytecode_to_trace( return 1; } + // Fitness-based trace quality check (before reserving space for this instruction) + _PyJitTracerTranslatorState *ts = &tracer->translator_state; + int32_t eq = compute_exit_quality(target_instr, opcode, tracer); + DPRINTF(3, "Fitness check: %s(%d) fitness=%d, exit_quality=%d, depth=%d\n", + _PyOpcode_OpName[opcode], oparg, ts->fitness, eq, ts->frame_depth); + + // Check if fitness is depleted — should we stop the trace? + if (ts->fitness < eq) { + // This is a tracer heuristic rather than normal program control flow, + // so leave operand1 clear and let the resulting side exit increase chain_depth. + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); + OPT_STAT_INC(fitness_terminated_traces); + DPRINTF(2, "Fitness terminated: %s(%d) fitness=%d < exit_quality=%d\n", + _PyOpcode_OpName[opcode], oparg, ts->fitness, eq); + goto done; + } + // One for possible _DEOPT, one because _CHECK_VALIDITY itself might _DEOPT trace->end -= 2; @@ -816,6 +870,12 @@ _PyJit_translate_single_bytecode_to_trace( assert(jump_happened ? (next_instr == computed_jump_instr) : (next_instr == computed_next_instr)); uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_happened]; ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(jump_happened ? computed_next_instr : computed_jump_instr, old_code)); + int bp = compute_branch_penalty(target_instr[1].cache, jump_happened); + tracer->translator_state.fitness -= bp; + DPRINTF(3, " branch penalty: -%d (history=0x%04x, taken=%d) -> fitness=%d\n", + bp, target_instr[1].cache, jump_happened, + tracer->translator_state.fitness); + break; } case JUMP_BACKWARD_JIT: @@ -823,6 +883,9 @@ _PyJit_translate_single_bytecode_to_trace( case JUMP_BACKWARD_NO_JIT: case JUMP_BACKWARD: ADD_TO_TRACE(_CHECK_PERIODIC, 0, 0, target); + tracer->translator_state.fitness -= FITNESS_BACKWARD_EDGE; + DPRINTF(3, " backward edge penalty: -%d -> fitness=%d\n", + FITNESS_BACKWARD_EDGE, tracer->translator_state.fitness); _Py_FALLTHROUGH; case JUMP_BACKWARD_NO_INTERRUPT: { @@ -945,6 +1008,44 @@ _PyJit_translate_single_bytecode_to_trace( assert(next->op.code == STORE_FAST); operand = next->op.arg; } + else if (uop == _PUSH_FRAME) { + _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; + ts_depth->frame_depth++; + if (ts_depth->frame_depth >= MAX_ABSTRACT_FRAME_DEPTH) { + // The optimizer can't handle frames this deep, + // so there's no point continuing the trace. + DPRINTF(2, "Unsupported: frame depth %d >= MAX_ABSTRACT_FRAME_DEPTH\n", + ts_depth->frame_depth); + end_trace_opcode = _EXIT_TRACE; + goto unsupported; + } + int32_t frame_penalty = compute_frame_penalty(&tstate->interp->opt_config); + int32_t cost = frame_penalty * ts_depth->frame_depth; + ts_depth->fitness -= cost; + DPRINTF(3, " _PUSH_FRAME: depth=%d, penalty=-%d (per_frame=%d) -> fitness=%d\n", + ts_depth->frame_depth, cost, frame_penalty, + ts_depth->fitness); + } + else if (uop == _RETURN_VALUE || uop == _RETURN_GENERATOR || uop == _YIELD_VALUE) { + _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; + int32_t frame_penalty = compute_frame_penalty(&tstate->interp->opt_config); + if (ts_depth->frame_depth <= 0) { + // Underflow: returning from a frame we didn't enter + ts_depth->fitness -= frame_penalty * 2; + DPRINTF(3, " %s: underflow penalty=-%d -> fitness=%d\n", + _PyOpcode_uop_name[uop], frame_penalty * 2, + ts_depth->fitness); + } + else { + // Reward returning: small inlined calls should be encouraged + ts_depth->fitness += frame_penalty; + DPRINTF(3, " %s: return reward=+%d, depth=%d -> fitness=%d\n", + _PyOpcode_uop_name[uop], frame_penalty, + ts_depth->frame_depth - 1, + ts_depth->fitness); + } + ts_depth->frame_depth = ts_depth->frame_depth <= 0 ? 0 : ts_depth->frame_depth - 1; + } else if (_PyUop_Flags[uop] & HAS_RECORDS_VALUE_FLAG) { PyObject *recorded_value = tracer->prev_state.recorded_value; tracer->prev_state.recorded_value = NULL; @@ -986,7 +1087,13 @@ _PyJit_translate_single_bytecode_to_trace( ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); goto done; } - DPRINTF(2, "Trace continuing\n"); + // Update fitness AFTER translation, BEFORE returning to continue tracing. + // This ensures the next iteration's fitness check reflects the cost of + // all instructions translated so far. + tracer->translator_state.fitness -= FITNESS_PER_INSTRUCTION; + DPRINTF(3, " per-insn cost: -%d -> fitness=%d\n", + FITNESS_PER_INSTRUCTION, tracer->translator_state.fitness); + DPRINTF(2, "Trace continuing (fitness=%d)\n", tracer->translator_state.fitness); return 1; done: DPRINTF(2, "Trace done\n"); @@ -1069,6 +1176,17 @@ _PyJit_TryInitializeTracing( assert(curr_instr->op.code == JUMP_BACKWARD_JIT || curr_instr->op.code == RESUME_CHECK_JIT || (exit != NULL)); tracer->initial_state.jump_backward_instr = curr_instr; + // Initialize fitness tracking state + const _PyOptimizationConfig *cfg = &tstate->interp->opt_config; + _PyJitTracerTranslatorState *ts = &tracer->translator_state; + bool is_side_trace = (exit != NULL); + ts->fitness = is_side_trace + ? (int32_t)cfg->fitness_initial_side + : (int32_t)cfg->fitness_initial; + ts->frame_depth = 0; + DPRINTF(3, "Fitness init: %s trace, fitness=%d\n", + is_side_trace ? "side" : "root", ts->fitness); + tracer->is_tracing = true; return 1; } diff --git a/Python/pystate.c b/Python/pystate.c index 143175da0f4..78eab7cc7d2 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -635,6 +635,22 @@ init_interpreter(PyInterpreterState *interp, "PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF", SIDE_EXIT_INITIAL_BACKOFF, 0, MAX_BACKOFF); + // Trace fitness configuration + init_policy(&interp->opt_config.fitness_initial, + "PYTHON_JIT_FITNESS_INITIAL", + FITNESS_INITIAL, 100, 10000); + init_policy(&interp->opt_config.fitness_initial_side, + "PYTHON_JIT_FITNESS_INITIAL_SIDE", + FITNESS_INITIAL_SIDE, 50, 5000); + /* The tracer starts at start_instr, so initial fitness must not be below + * the close-loop exit quality or tracing will terminate immediately. */ + if (interp->opt_config.fitness_initial < EXIT_QUALITY_CLOSE_LOOP) { + interp->opt_config.fitness_initial = EXIT_QUALITY_CLOSE_LOOP; + } + if (interp->opt_config.fitness_initial_side < EXIT_QUALITY_CLOSE_LOOP) { + interp->opt_config.fitness_initial_side = EXIT_QUALITY_CLOSE_LOOP; + } + interp->opt_config.specialization_enabled = !is_env_enabled("PYTHON_SPECIALIZATION_OFF"); interp->opt_config.uops_optimize_enabled = !is_env_disabled("PYTHON_UOPS_OPTIMIZE"); if (interp != &runtime->_main_interpreter) { diff --git a/Python/pystats.c b/Python/pystats.c index a057ad88456..2fac2db1b73 100644 --- a/Python/pystats.c +++ b/Python/pystats.c @@ -274,6 +274,7 @@ print_optimization_stats(FILE *out, OptimizationStats *stats) fprintf(out, "Optimization low confidence: %" PRIu64 "\n", stats->low_confidence); fprintf(out, "Optimization unknown callee: %" PRIu64 "\n", stats->unknown_callee); fprintf(out, "Executors invalidated: %" PRIu64 "\n", stats->executors_invalidated); + fprintf(out, "Optimization fitness terminated: %" PRIu64 "\n", stats->fitness_terminated_traces); print_histogram(out, "Trace length", stats->trace_length_hist); print_histogram(out, "Trace run length", stats->trace_run_length_hist); From cb76ab3819f778e55a3f49ddb1f681ee20978eda Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 3 Apr 2026 19:23:29 +0300 Subject: [PATCH 390/775] gh-145098: Use `macos-15-intel` instead of unstable `macos-26-intel` (#148038) --- .github/workflows/build.yml | 8 ++++---- .github/workflows/reusable-macos.yml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 025032a3ae6..a80262e3c02 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -206,16 +206,16 @@ jobs: strategy: fail-fast: false matrix: - # macos-26 is Apple Silicon, macos-26-intel is Intel. - # macos-26-intel only runs tests against the GIL-enabled CPython. + # macos-26 is Apple Silicon, macos-15-intel is Intel. + # macos-15-intel only runs tests against the GIL-enabled CPython. os: - macos-26 - - macos-26-intel + - macos-15-intel free-threading: - false - true exclude: - - os: macos-26-intel + - os: macos-15-intel free-threading: true uses: ./.github/workflows/reusable-macos.yml with: diff --git a/.github/workflows/reusable-macos.yml b/.github/workflows/reusable-macos.yml index 9d8e6b03464..785dcc77f54 100644 --- a/.github/workflows/reusable-macos.yml +++ b/.github/workflows/reusable-macos.yml @@ -52,15 +52,15 @@ jobs: --prefix=/opt/python-dev \ --with-openssl="$(brew --prefix openssl@3.5)" - name: Build CPython - if : ${{ inputs.free-threading || inputs.os != 'macos-26-intel' }} + if : ${{ inputs.free-threading || inputs.os != 'macos-15-intel' }} run: gmake -j8 - name: Build CPython for compiler warning check - if : ${{ !inputs.free-threading && inputs.os == 'macos-26-intel' }} + if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }} run: set -o pipefail; gmake -j8 --output-sync 2>&1 | tee compiler_output_macos.txt - name: Display build info run: make pythoninfo - name: Check compiler warnings - if : ${{ !inputs.free-threading && inputs.os == 'macos-26-intel' }} + if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }} run: >- python3 Tools/build/check_warnings.py --compiler-output-file-path=compiler_output_macos.txt From 80d0a85d969d305c7436dc54f8939d7b6f441b5f Mon Sep 17 00:00:00 2001 From: Joshua Swanson <22283299+joshuaswanson@users.noreply.github.com> Date: Fri, 3 Apr 2026 20:07:03 +0200 Subject: [PATCH 391/775] gh-126676: Expand argparse docs for type=bool with warning and alternatives (#146435) Co-authored-by: joshuaswanson Co-authored-by: Savannah Ostrowski --- Doc/library/argparse.rst | 10 +++++++++- .../2026-03-25-00-00-00.gh-issue-126676.052336.rst | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 5a463ee9821..8ba11b7d12d 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1118,7 +1118,15 @@ User defined functions can be used as well: The :func:`bool` function is not recommended as a type converter. All it does is convert empty strings to ``False`` and non-empty strings to ``True``. -This is usually not what is desired. +This is usually not what is desired:: + + >>> parser = argparse.ArgumentParser() + >>> _ = parser.add_argument('--verbose', type=bool) + >>> parser.parse_args(['--verbose', 'False']) + Namespace(verbose=True) + +See :class:`BooleanOptionalAction` or ``action='store_true'`` for common +alternatives. In general, the ``type`` keyword is a convenience that should only be used for simple conversions that can only raise one of the three supported exceptions. diff --git a/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst b/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst new file mode 100644 index 00000000000..d2e275fdf08 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst @@ -0,0 +1,2 @@ +Expand :mod:`argparse` documentation for ``type=bool`` with a demonstration +of the surprising behavior and pointers to common alternatives. From dea4083aa952c955a7c3a7657034bd38889a4e22 Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Fri, 3 Apr 2026 21:42:13 +0200 Subject: [PATCH 392/775] GH-146210: Fix building the jit stencils on Windows when the interpreter is built with a different clang version (#146338) Co-authored-by: Savannah Ostrowski --- .../2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst | 2 ++ Tools/jit/_llvm.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst diff --git a/Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst b/Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst new file mode 100644 index 00000000000..ce59a9a3a57 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst @@ -0,0 +1,2 @@ +Fix building the jit stencils on Windows when the interpreter is built with +a different clang version. Patch by Chris Eibl. diff --git a/Tools/jit/_llvm.py b/Tools/jit/_llvm.py index 8b68c1e8636..a4aaacdf412 100644 --- a/Tools/jit/_llvm.py +++ b/Tools/jit/_llvm.py @@ -42,9 +42,19 @@ async def _run(tool: str, args: typing.Iterable[str], echo: bool = False) -> str async with _CORES: if echo: print(shlex.join(command)) + + if os.name == "nt": + # When building with /p:PlatformToolset=ClangCL, the VS build + # system puts that clang's include path into INCLUDE. The JIT's + # clang may be a different version, and mismatched headers cause + # build errors. See https://github.com/python/cpython/issues/146210. + env = os.environ.copy() + env.pop("INCLUDE", None) + else: + env = None try: process = await asyncio.create_subprocess_exec( - *command, stdout=subprocess.PIPE + *command, stdout=subprocess.PIPE, env=env ) except FileNotFoundError: return None From 848bbe9ff21ae0a3ee412cc25843835ace4f75df Mon Sep 17 00:00:00 2001 From: Robert Kirkman <31490854+robertkirkman@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:27:27 -0500 Subject: [PATCH 393/775] gh-146541: Allow building the Android testbed for 32-bit targets (#146542) Allows building the Android testbed for 32-bit targets, adding the target triplets `arm-linux-androideabi` and `i686-linux-android`. Co-authored-by: Malcolm Smith --- Android/android.py | 9 +++++++-- Android/testbed/app/build.gradle.kts | 2 ++ Lib/sysconfig/__init__.py | 8 ++++++-- Lib/test/test_sysconfig.py | 10 ++++++---- .../2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst | 1 + 5 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst diff --git a/Android/android.py b/Android/android.py index 317875ef336..f8829e53306 100755 --- a/Android/android.py +++ b/Android/android.py @@ -34,7 +34,12 @@ TESTBED_DIR = ANDROID_DIR / "testbed" CROSS_BUILD_DIR = PYTHON_DIR / "cross-build" -HOSTS = ["aarch64-linux-android", "x86_64-linux-android"] +HOSTS = [ + "aarch64-linux-android", + "arm-linux-androideabi", + "i686-linux-android", + "x86_64-linux-android", +] APP_ID = "org.python.testbed" DECODE_ARGS = ("UTF-8", "backslashreplace") @@ -209,7 +214,7 @@ def unpack_deps(host, prefix_dir): os.chdir(prefix_dir) deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download" for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.5.5-0", - "sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-1"]: + "sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-2"]: filename = f"{name_ver}-{host}.tar.gz" download(f"{deps_url}/{name_ver}/{filename}") shutil.unpack_archive(filename) diff --git a/Android/testbed/app/build.gradle.kts b/Android/testbed/app/build.gradle.kts index 53cdc591fa3..7529fdb8f78 100644 --- a/Android/testbed/app/build.gradle.kts +++ b/Android/testbed/app/build.gradle.kts @@ -15,6 +15,8 @@ val inSourceTree = ( val KNOWN_ABIS = mapOf( "aarch64-linux-android" to "arm64-v8a", + "arm-linux-androideabi" to "armeabi-v7a", + "i686-linux-android" to "x86", "x86_64-linux-android" to "x86_64", ) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 1418293dcba..47415adce04 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -697,12 +697,16 @@ def get_platform(): # When Python is running on 32-bit ARM Android on a 64-bit ARM kernel, # 'os.uname().machine' is 'armv8l'. Such devices run the same userspace # code as 'armv7l' devices. + # During the build process of the Android testbed when targeting 32-bit ARM, + # '_PYTHON_HOST_PLATFORM' is 'arm-linux-androideabi', so 'machine' becomes + # 'arm'. machine = { - "x86_64": "x86_64", - "i686": "x86", "aarch64": "arm64_v8a", + "arm": "armeabi_v7a", "armv7l": "armeabi_v7a", "armv8l": "armeabi_v7a", + "i686": "x86", + "x86_64": "x86_64", }[machine] elif osname == "linux": # At least on Linux/Intel, 'machine' is the processor -- diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 6cd568eb3d0..e6433f76a97 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -371,11 +371,12 @@ def test_get_platform(self): sys.platform = 'android' get_config_vars()['ANDROID_API_LEVEL'] = 9 for machine, abi in { - 'x86_64': 'x86_64', - 'i686': 'x86', 'aarch64': 'arm64_v8a', + 'arm': 'armeabi_v7a', 'armv7l': 'armeabi_v7a', 'armv8l': 'armeabi_v7a', + 'i686': 'x86', + 'x86_64': 'x86_64', }.items(): with self.subTest(machine): self._set_uname(('Linux', 'localhost', '3.18.91+', @@ -580,11 +581,12 @@ def test_android_ext_suffix(self): machine = platform.machine() suffix = sysconfig.get_config_var('EXT_SUFFIX') expected_triplet = { - "x86_64": "x86_64-linux-android", - "i686": "i686-linux-android", "aarch64": "aarch64-linux-android", + "arm": "arm-linux-androideabi", "armv7l": "arm-linux-androideabi", "armv8l": "arm-linux-androideabi", + "i686": "i686-linux-android", + "x86_64": "x86_64-linux-android", }[machine] self.assertEndsWith(suffix, f"-{expected_triplet}.so") diff --git a/Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst b/Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst new file mode 100644 index 00000000000..351071b0bec --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst @@ -0,0 +1 @@ +The Android testbed can now be built for 32-bit ARM and x86 targets. From b8470deb5d52f524ae18c6f232fecfc99b133397 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 4 Apr 2026 11:42:04 +0800 Subject: [PATCH 394/775] gh-146450: Normalise feature set of Android build script with other platform build scripts (#146451) Allows for cleaning a subset of targets, customization of the download cache and cross-build directories, and modifies the build command to allow 'all', 'build' and 'hosts' targets. --- Android/android.py | 140 ++++++++++++++---- ...-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst | 2 + 2 files changed, 112 insertions(+), 30 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst diff --git a/Android/android.py b/Android/android.py index f8829e53306..adcc7c708d9 100755 --- a/Android/android.py +++ b/Android/android.py @@ -210,38 +210,48 @@ def make_build_python(context): # # If you're a member of the Python core team, and you'd like to be able to push # these tags yourself, please contact Malcolm Smith or Russell Keith-Magee. -def unpack_deps(host, prefix_dir): +def unpack_deps(host, prefix_dir, cache_dir): os.chdir(prefix_dir) deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download" for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.5.5-0", "sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-2"]: filename = f"{name_ver}-{host}.tar.gz" - download(f"{deps_url}/{name_ver}/{filename}") - shutil.unpack_archive(filename) - os.remove(filename) + out_path = download(f"{deps_url}/{name_ver}/{filename}", cache_dir) + shutil.unpack_archive(out_path) -def download(url, target_dir="."): - out_path = f"{target_dir}/{basename(url)}" - run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url]) +def download(url, cache_dir): + out_path = cache_dir / basename(url) + cache_dir.mkdir(parents=True, exist_ok=True) + if not out_path.is_file(): + run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url]) + else: + print(f"Using cached version of {basename(url)}") return out_path -def configure_host_python(context): +def configure_host_python(context, host=None): + if host is None: + host = context.host if context.clean: - clean(context.host) + clean(host) - host_dir = subdir(context.host, create=True) + host_dir = subdir(host, create=True) prefix_dir = host_dir / "prefix" if not prefix_dir.exists(): prefix_dir.mkdir() - unpack_deps(context.host, prefix_dir) + cache_dir = ( + Path(context.cache_dir).resolve() + if context.cache_dir + else CROSS_BUILD_DIR / "downloads" + ) + unpack_deps(host, prefix_dir, cache_dir) os.chdir(host_dir) command = [ # Basic cross-compiling configuration relpath(PYTHON_DIR / "configure"), - f"--host={context.host}", + f"--host={host}", f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}", f"--with-build-python={build_python_path()}", "--without-ensurepip", @@ -257,14 +267,16 @@ def configure_host_python(context): if context.args: command.extend(context.args) - run(command, host=context.host) + run(command, host=host) -def make_host_python(context): +def make_host_python(context, host=None): + if host is None: + host = context.host # The CFLAGS and LDFLAGS set in android-env include the prefix dir, so # delete any previous Python installation to prevent it being used during # the build. - host_dir = subdir(context.host) + host_dir = subdir(host) prefix_dir = host_dir / "prefix" for pattern in ("include/python*", "lib/libpython*", "lib/python*"): delete_glob(f"{prefix_dir}/{pattern}") @@ -283,20 +295,28 @@ def make_host_python(context): ) -def build_all(context): - steps = [configure_build_python, make_build_python, configure_host_python, - make_host_python] - for step in steps: - step(context) +def build_targets(context): + if context.target in {"all", "build"}: + configure_build_python(context) + make_build_python(context) + + for host in HOSTS: + if context.target in {"all", "hosts", host}: + configure_host_python(context, host) + make_host_python(context, host) def clean(host): delete_glob(CROSS_BUILD_DIR / host) -def clean_all(context): - for host in HOSTS + ["build"]: - clean(host) +def clean_targets(context): + if context.target in {"all", "build"}: + clean("build") + + for host in HOSTS: + if context.target in {"all", "hosts", host}: + clean(host) def setup_ci(): @@ -859,18 +879,23 @@ def add_parser(*args, **kwargs): # Subcommands build = add_parser( - "build", help="Run configure-build, make-build, configure-host and " - "make-host") + "build", + help="Run configure and make for the selected target" + ) configure_build = add_parser( "configure-build", help="Run `configure` for the build Python") - add_parser( + make_build = add_parser( "make-build", help="Run `make` for the build Python") configure_host = add_parser( "configure-host", help="Run `configure` for Android") make_host = add_parser( "make-host", help="Run `make` for Android") - add_parser("clean", help="Delete all build directories") + clean = add_parser( + "clean", + help="Delete build directories for the selected target" + ) + add_parser("build-testbed", help="Build the testbed app") test = add_parser("test", help="Run the testbed app") package = add_parser("package", help="Make a release package") @@ -878,12 +903,61 @@ def add_parser(*args, **kwargs): env = add_parser("env", help="Print environment variables") # Common arguments + # --cross-build-dir argument + for cmd in [ + clean, + configure_build, + make_build, + configure_host, + make_host, + build, + package, + test, + ci, + ]: + cmd.add_argument( + "--cross-build-dir", + action="store", + default=os.environ.get("CROSS_BUILD_DIR"), + dest="cross_build_dir", + type=Path, + help=( + "Path to the cross-build directory " + f"(default: {CROSS_BUILD_DIR}). Can also be set " + "with the CROSS_BUILD_DIR environment variable." + ), + ) + + # --cache-dir option + for cmd in [configure_host, build, ci]: + cmd.add_argument( + "--cache-dir", + default=os.environ.get("CACHE_DIR"), + help="The directory to store cached downloads.", + ) + + # --clean option for subcommand in [build, configure_build, configure_host, ci]: subcommand.add_argument( "--clean", action="store_true", default=False, dest="clean", help="Delete the relevant build directories first") - host_commands = [build, configure_host, make_host, package, ci] + # Allow "all", "build" and "hosts" targets for some commands + for subcommand in [clean, build]: + subcommand.add_argument( + "target", + nargs="?", + default="all", + choices=["all", "build", "hosts"] + HOSTS, + help=( + "The host triplet (e.g., aarch64-linux-android), " + "or 'build' for just the build platform, or 'hosts' for all " + "host platforms, or 'all' for the build platform and all " + "hosts. Defaults to 'all'" + ), + ) + + host_commands = [configure_host, make_host, package, ci] if in_source_tree: host_commands.append(env) for subcommand in host_commands: @@ -945,13 +1019,19 @@ def main(): stream.reconfigure(line_buffering=True) context = parse_args() + + # Set the CROSS_BUILD_DIR if an argument was provided + if context.cross_build_dir: + global CROSS_BUILD_DIR + CROSS_BUILD_DIR = context.cross_build_dir.resolve() + dispatch = { "configure-build": configure_build_python, "make-build": make_build_python, "configure-host": configure_host_python, "make-host": make_host_python, - "build": build_all, - "clean": clean_all, + "build": build_targets, + "clean": clean_targets, "build-testbed": build_testbed, "test": run_testbed, "package": package, diff --git a/Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst b/Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst new file mode 100644 index 00000000000..32cb5b8221a --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst @@ -0,0 +1,2 @@ +The Android build script was modified to improve parity with other platform +build scripts. From 7e275d49658390fc788437b28dabef9f7fc65a27 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 4 Apr 2026 09:12:13 +0530 Subject: [PATCH 395/775] gh-131798: JIT inline function addresses of builtin methods (#146906) --- Include/internal/pycore_ceval.h | 4 +- Include/internal/pycore_uop_ids.h | 2490 +++++++++++----------- Include/internal/pycore_uop_metadata.h | 60 + Lib/test/test_capi/test_opt.py | 12 +- Modules/_testinternalcapi/test_cases.c.h | 14 +- Python/bytecodes.c | 87 +- Python/ceval.c | 9 +- Python/executor_cases.c.h | 187 +- Python/generated_cases.c.h | 14 +- Python/optimizer_bytecodes.c | 40 + Python/optimizer_cases.c.h | 89 + 11 files changed, 1724 insertions(+), 1282 deletions(-) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 9fd3be74404..2479630021b 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -447,7 +447,7 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal( PyAPI_FUNC(PyObject *) _PyCallMethodDescriptorFast_StackRefSteal( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFast cfunc, PyObject *self, _PyStackRef *arguments, int total_args); @@ -455,7 +455,7 @@ _PyCallMethodDescriptorFast_StackRefSteal( PyAPI_FUNC(PyObject *) _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFastWithKeywords cfunc, PyObject *self, _PyStackRef *arguments, int total_args); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 922fef91fa2..ae548eb3d68 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -63,169 +63,173 @@ extern "C" { #define _CALL_LEN 343 #define _CALL_LIST_APPEND 344 #define _CALL_METHOD_DESCRIPTOR_FAST 345 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 346 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 347 -#define _CALL_METHOD_DESCRIPTOR_O 348 -#define _CALL_NON_PY_GENERAL 349 -#define _CALL_STR_1 350 -#define _CALL_TUPLE_1 351 -#define _CALL_TYPE_1 352 -#define _CHECK_AND_ALLOCATE_OBJECT 353 -#define _CHECK_ATTR_CLASS 354 -#define _CHECK_ATTR_METHOD_LAZY_DICT 355 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 356 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE 346 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 347 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE 348 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 349 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE 350 +#define _CALL_METHOD_DESCRIPTOR_O 351 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE 352 +#define _CALL_NON_PY_GENERAL 353 +#define _CALL_STR_1 354 +#define _CALL_TUPLE_1 355 +#define _CALL_TYPE_1 356 +#define _CHECK_AND_ALLOCATE_OBJECT 357 +#define _CHECK_ATTR_CLASS 358 +#define _CHECK_ATTR_METHOD_LAZY_DICT 359 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 360 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION_EXACT_ARGS 357 -#define _CHECK_FUNCTION_VERSION 358 -#define _CHECK_FUNCTION_VERSION_INLINE 359 -#define _CHECK_FUNCTION_VERSION_KW 360 -#define _CHECK_IS_NOT_PY_CALLABLE 361 -#define _CHECK_IS_NOT_PY_CALLABLE_EX 362 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 363 -#define _CHECK_IS_PY_CALLABLE_EX 364 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 365 -#define _CHECK_METHOD_VERSION 366 -#define _CHECK_METHOD_VERSION_KW 367 -#define _CHECK_PEP_523 368 -#define _CHECK_PERIODIC 369 -#define _CHECK_PERIODIC_AT_END 370 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 371 -#define _CHECK_RECURSION_REMAINING 372 -#define _CHECK_STACK_SPACE 373 -#define _CHECK_STACK_SPACE_OPERAND 374 -#define _CHECK_VALIDITY 375 -#define _COLD_DYNAMIC_EXIT 376 -#define _COLD_EXIT 377 -#define _COMPARE_OP 378 -#define _COMPARE_OP_FLOAT 379 -#define _COMPARE_OP_INT 380 -#define _COMPARE_OP_STR 381 -#define _CONTAINS_OP 382 -#define _CONTAINS_OP_DICT 383 -#define _CONTAINS_OP_SET 384 +#define _CHECK_FUNCTION_EXACT_ARGS 361 +#define _CHECK_FUNCTION_VERSION 362 +#define _CHECK_FUNCTION_VERSION_INLINE 363 +#define _CHECK_FUNCTION_VERSION_KW 364 +#define _CHECK_IS_NOT_PY_CALLABLE 365 +#define _CHECK_IS_NOT_PY_CALLABLE_EX 366 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 367 +#define _CHECK_IS_PY_CALLABLE_EX 368 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 369 +#define _CHECK_METHOD_VERSION 370 +#define _CHECK_METHOD_VERSION_KW 371 +#define _CHECK_PEP_523 372 +#define _CHECK_PERIODIC 373 +#define _CHECK_PERIODIC_AT_END 374 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 375 +#define _CHECK_RECURSION_REMAINING 376 +#define _CHECK_STACK_SPACE 377 +#define _CHECK_STACK_SPACE_OPERAND 378 +#define _CHECK_VALIDITY 379 +#define _COLD_DYNAMIC_EXIT 380 +#define _COLD_EXIT 381 +#define _COMPARE_OP 382 +#define _COMPARE_OP_FLOAT 383 +#define _COMPARE_OP_INT 384 +#define _COMPARE_OP_STR 385 +#define _CONTAINS_OP 386 +#define _CONTAINS_OP_DICT 387 +#define _CONTAINS_OP_SET 388 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 385 -#define _COPY_1 386 -#define _COPY_2 387 -#define _COPY_3 388 +#define _COPY 389 +#define _COPY_1 390 +#define _COPY_2 391 +#define _COPY_3 392 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 389 +#define _CREATE_INIT_FRAME 393 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 390 -#define _DICT_MERGE 391 -#define _DICT_UPDATE 392 -#define _DO_CALL 393 -#define _DO_CALL_FUNCTION_EX 394 -#define _DO_CALL_KW 395 -#define _DYNAMIC_EXIT 396 +#define _DEOPT 394 +#define _DICT_MERGE 395 +#define _DICT_UPDATE 396 +#define _DO_CALL 397 +#define _DO_CALL_FUNCTION_EX 398 +#define _DO_CALL_KW 399 +#define _DYNAMIC_EXIT 400 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 397 +#define _ERROR_POP_N 401 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 398 -#define _EXPAND_METHOD_KW 399 -#define _FATAL_ERROR 400 +#define _EXPAND_METHOD 402 +#define _EXPAND_METHOD_KW 403 +#define _FATAL_ERROR 404 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 401 -#define _FOR_ITER_GEN_FRAME 402 -#define _FOR_ITER_TIER_TWO 403 +#define _FOR_ITER 405 +#define _FOR_ITER_GEN_FRAME 406 +#define _FOR_ITER_TIER_TWO 407 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN -#define _GUARD_BINARY_OP_EXTEND 404 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 405 -#define _GUARD_BIT_IS_SET_POP 406 -#define _GUARD_BIT_IS_SET_POP_4 407 -#define _GUARD_BIT_IS_SET_POP_5 408 -#define _GUARD_BIT_IS_SET_POP_6 409 -#define _GUARD_BIT_IS_SET_POP_7 410 -#define _GUARD_BIT_IS_UNSET_POP 411 -#define _GUARD_BIT_IS_UNSET_POP_4 412 -#define _GUARD_BIT_IS_UNSET_POP_5 413 -#define _GUARD_BIT_IS_UNSET_POP_6 414 -#define _GUARD_BIT_IS_UNSET_POP_7 415 -#define _GUARD_CALLABLE_BUILTIN_FAST 416 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 417 -#define _GUARD_CALLABLE_BUILTIN_O 418 -#define _GUARD_CALLABLE_ISINSTANCE 419 -#define _GUARD_CALLABLE_LEN 420 -#define _GUARD_CALLABLE_LIST_APPEND 421 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 422 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 423 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 424 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 425 -#define _GUARD_CALLABLE_STR_1 426 -#define _GUARD_CALLABLE_TUPLE_1 427 -#define _GUARD_CALLABLE_TYPE_1 428 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR 429 -#define _GUARD_CODE_VERSION_RETURN_VALUE 430 -#define _GUARD_CODE_VERSION_YIELD_VALUE 431 -#define _GUARD_CODE_VERSION__PUSH_FRAME 432 -#define _GUARD_DORV_NO_DICT 433 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 434 -#define _GUARD_GLOBALS_VERSION 435 -#define _GUARD_IP_RETURN_GENERATOR 436 -#define _GUARD_IP_RETURN_VALUE 437 -#define _GUARD_IP_YIELD_VALUE 438 -#define _GUARD_IP__PUSH_FRAME 439 -#define _GUARD_IS_FALSE_POP 440 -#define _GUARD_IS_NONE_POP 441 -#define _GUARD_IS_NOT_NONE_POP 442 -#define _GUARD_IS_TRUE_POP 443 -#define _GUARD_KEYS_VERSION 444 -#define _GUARD_NOS_ANY_DICT 445 -#define _GUARD_NOS_COMPACT_ASCII 446 -#define _GUARD_NOS_DICT 447 -#define _GUARD_NOS_FLOAT 448 -#define _GUARD_NOS_INT 449 -#define _GUARD_NOS_LIST 450 -#define _GUARD_NOS_NOT_NULL 451 -#define _GUARD_NOS_NULL 452 -#define _GUARD_NOS_OVERFLOWED 453 -#define _GUARD_NOS_TUPLE 454 -#define _GUARD_NOS_UNICODE 455 -#define _GUARD_NOT_EXHAUSTED_LIST 456 -#define _GUARD_NOT_EXHAUSTED_RANGE 457 -#define _GUARD_NOT_EXHAUSTED_TUPLE 458 -#define _GUARD_THIRD_NULL 459 -#define _GUARD_TOS_ANY_DICT 460 -#define _GUARD_TOS_ANY_SET 461 -#define _GUARD_TOS_DICT 462 -#define _GUARD_TOS_FLOAT 463 -#define _GUARD_TOS_FROZENDICT 464 -#define _GUARD_TOS_FROZENSET 465 -#define _GUARD_TOS_INT 466 -#define _GUARD_TOS_LIST 467 -#define _GUARD_TOS_OVERFLOWED 468 -#define _GUARD_TOS_SET 469 -#define _GUARD_TOS_SLICE 470 -#define _GUARD_TOS_TUPLE 471 -#define _GUARD_TOS_UNICODE 472 -#define _GUARD_TYPE_VERSION 473 -#define _GUARD_TYPE_VERSION_LOCKED 474 -#define _HANDLE_PENDING_AND_DEOPT 475 +#define _GUARD_BINARY_OP_EXTEND 408 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 409 +#define _GUARD_BIT_IS_SET_POP 410 +#define _GUARD_BIT_IS_SET_POP_4 411 +#define _GUARD_BIT_IS_SET_POP_5 412 +#define _GUARD_BIT_IS_SET_POP_6 413 +#define _GUARD_BIT_IS_SET_POP_7 414 +#define _GUARD_BIT_IS_UNSET_POP 415 +#define _GUARD_BIT_IS_UNSET_POP_4 416 +#define _GUARD_BIT_IS_UNSET_POP_5 417 +#define _GUARD_BIT_IS_UNSET_POP_6 418 +#define _GUARD_BIT_IS_UNSET_POP_7 419 +#define _GUARD_CALLABLE_BUILTIN_FAST 420 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 421 +#define _GUARD_CALLABLE_BUILTIN_O 422 +#define _GUARD_CALLABLE_ISINSTANCE 423 +#define _GUARD_CALLABLE_LEN 424 +#define _GUARD_CALLABLE_LIST_APPEND 425 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 426 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 427 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 428 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 429 +#define _GUARD_CALLABLE_STR_1 430 +#define _GUARD_CALLABLE_TUPLE_1 431 +#define _GUARD_CALLABLE_TYPE_1 432 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR 433 +#define _GUARD_CODE_VERSION_RETURN_VALUE 434 +#define _GUARD_CODE_VERSION_YIELD_VALUE 435 +#define _GUARD_CODE_VERSION__PUSH_FRAME 436 +#define _GUARD_DORV_NO_DICT 437 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 438 +#define _GUARD_GLOBALS_VERSION 439 +#define _GUARD_IP_RETURN_GENERATOR 440 +#define _GUARD_IP_RETURN_VALUE 441 +#define _GUARD_IP_YIELD_VALUE 442 +#define _GUARD_IP__PUSH_FRAME 443 +#define _GUARD_IS_FALSE_POP 444 +#define _GUARD_IS_NONE_POP 445 +#define _GUARD_IS_NOT_NONE_POP 446 +#define _GUARD_IS_TRUE_POP 447 +#define _GUARD_KEYS_VERSION 448 +#define _GUARD_NOS_ANY_DICT 449 +#define _GUARD_NOS_COMPACT_ASCII 450 +#define _GUARD_NOS_DICT 451 +#define _GUARD_NOS_FLOAT 452 +#define _GUARD_NOS_INT 453 +#define _GUARD_NOS_LIST 454 +#define _GUARD_NOS_NOT_NULL 455 +#define _GUARD_NOS_NULL 456 +#define _GUARD_NOS_OVERFLOWED 457 +#define _GUARD_NOS_TUPLE 458 +#define _GUARD_NOS_UNICODE 459 +#define _GUARD_NOT_EXHAUSTED_LIST 460 +#define _GUARD_NOT_EXHAUSTED_RANGE 461 +#define _GUARD_NOT_EXHAUSTED_TUPLE 462 +#define _GUARD_THIRD_NULL 463 +#define _GUARD_TOS_ANY_DICT 464 +#define _GUARD_TOS_ANY_SET 465 +#define _GUARD_TOS_DICT 466 +#define _GUARD_TOS_FLOAT 467 +#define _GUARD_TOS_FROZENDICT 468 +#define _GUARD_TOS_FROZENSET 469 +#define _GUARD_TOS_INT 470 +#define _GUARD_TOS_LIST 471 +#define _GUARD_TOS_OVERFLOWED 472 +#define _GUARD_TOS_SET 473 +#define _GUARD_TOS_SLICE 474 +#define _GUARD_TOS_TUPLE 475 +#define _GUARD_TOS_UNICODE 476 +#define _GUARD_TYPE_VERSION 477 +#define _GUARD_TYPE_VERSION_LOCKED 478 +#define _HANDLE_PENDING_AND_DEOPT 479 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 476 -#define _INIT_CALL_PY_EXACT_ARGS 477 -#define _INIT_CALL_PY_EXACT_ARGS_0 478 -#define _INIT_CALL_PY_EXACT_ARGS_1 479 -#define _INIT_CALL_PY_EXACT_ARGS_2 480 -#define _INIT_CALL_PY_EXACT_ARGS_3 481 -#define _INIT_CALL_PY_EXACT_ARGS_4 482 -#define _INSERT_1_LOAD_CONST_INLINE 483 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 484 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 485 -#define _INSERT_NULL 486 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 480 +#define _INIT_CALL_PY_EXACT_ARGS 481 +#define _INIT_CALL_PY_EXACT_ARGS_0 482 +#define _INIT_CALL_PY_EXACT_ARGS_1 483 +#define _INIT_CALL_PY_EXACT_ARGS_2 484 +#define _INIT_CALL_PY_EXACT_ARGS_3 485 +#define _INIT_CALL_PY_EXACT_ARGS_4 486 +#define _INSERT_1_LOAD_CONST_INLINE 487 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW 488 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW 489 +#define _INSERT_NULL 490 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -235,1146 +239,1150 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 487 -#define _IS_OP 488 -#define _ITER_CHECK_LIST 489 -#define _ITER_CHECK_RANGE 490 -#define _ITER_CHECK_TUPLE 491 -#define _ITER_JUMP_LIST 492 -#define _ITER_JUMP_RANGE 493 -#define _ITER_JUMP_TUPLE 494 -#define _ITER_NEXT_LIST 495 -#define _ITER_NEXT_LIST_TIER_TWO 496 -#define _ITER_NEXT_RANGE 497 -#define _ITER_NEXT_TUPLE 498 +#define _IS_NONE 491 +#define _IS_OP 492 +#define _ITER_CHECK_LIST 493 +#define _ITER_CHECK_RANGE 494 +#define _ITER_CHECK_TUPLE 495 +#define _ITER_JUMP_LIST 496 +#define _ITER_JUMP_RANGE 497 +#define _ITER_JUMP_TUPLE 498 +#define _ITER_NEXT_LIST 499 +#define _ITER_NEXT_LIST_TIER_TWO 500 +#define _ITER_NEXT_RANGE 501 +#define _ITER_NEXT_TUPLE 502 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 499 +#define _JUMP_TO_TOP 503 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND 500 -#define _LOAD_ATTR 501 -#define _LOAD_ATTR_CLASS 502 +#define _LIST_EXTEND 504 +#define _LOAD_ATTR 505 +#define _LOAD_ATTR_CLASS 506 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 503 -#define _LOAD_ATTR_METHOD_LAZY_DICT 504 -#define _LOAD_ATTR_METHOD_NO_DICT 505 -#define _LOAD_ATTR_METHOD_WITH_VALUES 506 -#define _LOAD_ATTR_MODULE 507 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 508 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 509 -#define _LOAD_ATTR_PROPERTY_FRAME 510 -#define _LOAD_ATTR_SLOT 511 -#define _LOAD_ATTR_WITH_HINT 512 +#define _LOAD_ATTR_INSTANCE_VALUE 507 +#define _LOAD_ATTR_METHOD_LAZY_DICT 508 +#define _LOAD_ATTR_METHOD_NO_DICT 509 +#define _LOAD_ATTR_METHOD_WITH_VALUES 510 +#define _LOAD_ATTR_MODULE 511 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 512 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 513 +#define _LOAD_ATTR_PROPERTY_FRAME 514 +#define _LOAD_ATTR_SLOT 515 +#define _LOAD_ATTR_WITH_HINT 516 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 513 +#define _LOAD_BYTECODE 517 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 514 -#define _LOAD_CONST_INLINE_BORROW 515 -#define _LOAD_CONST_UNDER_INLINE 516 -#define _LOAD_CONST_UNDER_INLINE_BORROW 517 +#define _LOAD_CONST_INLINE 518 +#define _LOAD_CONST_INLINE_BORROW 519 +#define _LOAD_CONST_UNDER_INLINE 520 +#define _LOAD_CONST_UNDER_INLINE_BORROW 521 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 518 -#define _LOAD_FAST_0 519 -#define _LOAD_FAST_1 520 -#define _LOAD_FAST_2 521 -#define _LOAD_FAST_3 522 -#define _LOAD_FAST_4 523 -#define _LOAD_FAST_5 524 -#define _LOAD_FAST_6 525 -#define _LOAD_FAST_7 526 +#define _LOAD_FAST 522 +#define _LOAD_FAST_0 523 +#define _LOAD_FAST_1 524 +#define _LOAD_FAST_2 525 +#define _LOAD_FAST_3 526 +#define _LOAD_FAST_4 527 +#define _LOAD_FAST_5 528 +#define _LOAD_FAST_6 529 +#define _LOAD_FAST_7 530 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 527 -#define _LOAD_FAST_BORROW_0 528 -#define _LOAD_FAST_BORROW_1 529 -#define _LOAD_FAST_BORROW_2 530 -#define _LOAD_FAST_BORROW_3 531 -#define _LOAD_FAST_BORROW_4 532 -#define _LOAD_FAST_BORROW_5 533 -#define _LOAD_FAST_BORROW_6 534 -#define _LOAD_FAST_BORROW_7 535 +#define _LOAD_FAST_BORROW 531 +#define _LOAD_FAST_BORROW_0 532 +#define _LOAD_FAST_BORROW_1 533 +#define _LOAD_FAST_BORROW_2 534 +#define _LOAD_FAST_BORROW_3 535 +#define _LOAD_FAST_BORROW_4 536 +#define _LOAD_FAST_BORROW_5 537 +#define _LOAD_FAST_BORROW_6 538 +#define _LOAD_FAST_BORROW_7 539 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 536 -#define _LOAD_GLOBAL_BUILTINS 537 -#define _LOAD_GLOBAL_MODULE 538 +#define _LOAD_GLOBAL 540 +#define _LOAD_GLOBAL_BUILTINS 541 +#define _LOAD_GLOBAL_MODULE 542 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 539 -#define _LOAD_SMALL_INT_0 540 -#define _LOAD_SMALL_INT_1 541 -#define _LOAD_SMALL_INT_2 542 -#define _LOAD_SMALL_INT_3 543 -#define _LOAD_SPECIAL 544 +#define _LOAD_SMALL_INT 543 +#define _LOAD_SMALL_INT_0 544 +#define _LOAD_SMALL_INT_1 545 +#define _LOAD_SMALL_INT_2 546 +#define _LOAD_SMALL_INT_3 547 +#define _LOAD_SPECIAL 548 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _LOCK_OBJECT 545 -#define _MAKE_CALLARGS_A_TUPLE 546 +#define _LOCK_OBJECT 549 +#define _MAKE_CALLARGS_A_TUPLE 550 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_HEAP_SAFE 547 -#define _MAKE_WARM 548 +#define _MAKE_HEAP_SAFE 551 +#define _MAKE_WARM 552 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 549 +#define _MATCH_CLASS 553 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 550 -#define _MAYBE_EXPAND_METHOD_KW 551 -#define _MONITOR_CALL 552 -#define _MONITOR_CALL_KW 553 -#define _MONITOR_JUMP_BACKWARD 554 -#define _MONITOR_RESUME 555 +#define _MAYBE_EXPAND_METHOD 554 +#define _MAYBE_EXPAND_METHOD_KW 555 +#define _MONITOR_CALL 556 +#define _MONITOR_CALL_KW 557 +#define _MONITOR_JUMP_BACKWARD 558 +#define _MONITOR_RESUME 559 #define _NOP NOP -#define _POP_CALL 556 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 557 -#define _POP_CALL_ONE 558 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 559 -#define _POP_CALL_TWO 560 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 561 +#define _POP_CALL 560 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 561 +#define _POP_CALL_ONE 562 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 563 +#define _POP_CALL_TWO 564 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 565 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 562 -#define _POP_JUMP_IF_TRUE 563 +#define _POP_JUMP_IF_FALSE 566 +#define _POP_JUMP_IF_TRUE 567 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 564 -#define _POP_TOP_INT 565 -#define _POP_TOP_LOAD_CONST_INLINE 566 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 567 -#define _POP_TOP_NOP 568 -#define _POP_TOP_UNICODE 569 -#define _POP_TWO 570 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 571 +#define _POP_TOP_FLOAT 568 +#define _POP_TOP_INT 569 +#define _POP_TOP_LOAD_CONST_INLINE 570 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 571 +#define _POP_TOP_NOP 572 +#define _POP_TOP_UNICODE 573 +#define _POP_TWO 574 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 575 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 572 +#define _PUSH_FRAME 576 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 573 -#define _PY_FRAME_EX 574 -#define _PY_FRAME_GENERAL 575 -#define _PY_FRAME_KW 576 -#define _RECORD_3OS_GEN_FUNC 577 -#define _RECORD_4OS 578 -#define _RECORD_BOUND_METHOD 579 -#define _RECORD_CALLABLE 580 -#define _RECORD_CODE 581 -#define _RECORD_NOS 582 -#define _RECORD_NOS_GEN_FUNC 583 -#define _RECORD_TOS 584 -#define _RECORD_TOS_TYPE 585 -#define _REPLACE_WITH_TRUE 586 -#define _RESUME_CHECK 587 +#define _PUSH_NULL_CONDITIONAL 577 +#define _PY_FRAME_EX 578 +#define _PY_FRAME_GENERAL 579 +#define _PY_FRAME_KW 580 +#define _RECORD_3OS_GEN_FUNC 581 +#define _RECORD_4OS 582 +#define _RECORD_BOUND_METHOD 583 +#define _RECORD_CALLABLE 584 +#define _RECORD_CODE 585 +#define _RECORD_NOS 586 +#define _RECORD_NOS_GEN_FUNC 587 +#define _RECORD_TOS 588 +#define _RECORD_TOS_TYPE 589 +#define _REPLACE_WITH_TRUE 590 +#define _RESUME_CHECK 591 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 588 -#define _SAVE_RETURN_OFFSET 589 -#define _SEND 590 -#define _SEND_GEN_FRAME 591 +#define _RETURN_VALUE 592 +#define _SAVE_RETURN_OFFSET 593 +#define _SEND 594 +#define _SEND_GEN_FRAME 595 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 592 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 593 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 594 -#define _SPILL_OR_RELOAD 595 -#define _START_EXECUTOR 596 -#define _STORE_ATTR 597 -#define _STORE_ATTR_INSTANCE_VALUE 598 -#define _STORE_ATTR_SLOT 599 -#define _STORE_ATTR_WITH_HINT 600 +#define _SET_UPDATE 596 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 597 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 598 +#define _SPILL_OR_RELOAD 599 +#define _START_EXECUTOR 600 +#define _STORE_ATTR 601 +#define _STORE_ATTR_INSTANCE_VALUE 602 +#define _STORE_ATTR_SLOT 603 +#define _STORE_ATTR_WITH_HINT 604 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 601 -#define _STORE_SUBSCR 602 -#define _STORE_SUBSCR_DICT 603 -#define _STORE_SUBSCR_DICT_KNOWN_HASH 604 -#define _STORE_SUBSCR_LIST_INT 605 -#define _SWAP 606 -#define _SWAP_2 607 -#define _SWAP_3 608 -#define _SWAP_FAST 609 -#define _SWAP_FAST_0 610 -#define _SWAP_FAST_1 611 -#define _SWAP_FAST_2 612 -#define _SWAP_FAST_3 613 -#define _SWAP_FAST_4 614 -#define _SWAP_FAST_5 615 -#define _SWAP_FAST_6 616 -#define _SWAP_FAST_7 617 -#define _TIER2_RESUME_CHECK 618 -#define _TO_BOOL 619 +#define _STORE_SLICE 605 +#define _STORE_SUBSCR 606 +#define _STORE_SUBSCR_DICT 607 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 608 +#define _STORE_SUBSCR_LIST_INT 609 +#define _SWAP 610 +#define _SWAP_2 611 +#define _SWAP_3 612 +#define _SWAP_FAST 613 +#define _SWAP_FAST_0 614 +#define _SWAP_FAST_1 615 +#define _SWAP_FAST_2 616 +#define _SWAP_FAST_3 617 +#define _SWAP_FAST_4 618 +#define _SWAP_FAST_5 619 +#define _SWAP_FAST_6 620 +#define _SWAP_FAST_7 621 +#define _TIER2_RESUME_CHECK 622 +#define _TO_BOOL 623 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 620 -#define _TO_BOOL_LIST 621 +#define _TO_BOOL_INT 624 +#define _TO_BOOL_LIST 625 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 622 +#define _TO_BOOL_STR 626 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 623 -#define _UNARY_NEGATIVE 624 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 625 +#define _UNARY_INVERT 627 +#define _UNARY_NEGATIVE 628 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 629 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 626 -#define _UNPACK_SEQUENCE_LIST 627 -#define _UNPACK_SEQUENCE_TUPLE 628 -#define _UNPACK_SEQUENCE_TWO_TUPLE 629 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 630 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 631 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 632 +#define _UNPACK_SEQUENCE 630 +#define _UNPACK_SEQUENCE_LIST 631 +#define _UNPACK_SEQUENCE_TUPLE 632 +#define _UNPACK_SEQUENCE_TWO_TUPLE 633 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 634 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 635 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 636 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 633 -#define MAX_UOP_ID 633 -#define _BINARY_OP_r23 634 -#define _BINARY_OP_ADD_FLOAT_r03 635 -#define _BINARY_OP_ADD_FLOAT_r13 636 -#define _BINARY_OP_ADD_FLOAT_r23 637 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 638 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 639 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 640 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 641 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 642 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 643 -#define _BINARY_OP_ADD_INT_r03 644 -#define _BINARY_OP_ADD_INT_r13 645 -#define _BINARY_OP_ADD_INT_r23 646 -#define _BINARY_OP_ADD_INT_INPLACE_r03 647 -#define _BINARY_OP_ADD_INT_INPLACE_r13 648 -#define _BINARY_OP_ADD_INT_INPLACE_r23 649 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 650 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 651 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 652 -#define _BINARY_OP_ADD_UNICODE_r03 653 -#define _BINARY_OP_ADD_UNICODE_r13 654 -#define _BINARY_OP_ADD_UNICODE_r23 655 -#define _BINARY_OP_EXTEND_r23 656 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 657 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 658 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 659 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 660 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 661 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 662 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 663 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 664 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 665 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 666 -#define _BINARY_OP_MULTIPLY_INT_r03 667 -#define _BINARY_OP_MULTIPLY_INT_r13 668 -#define _BINARY_OP_MULTIPLY_INT_r23 669 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 670 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 671 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 672 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 673 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 674 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 675 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 676 -#define _BINARY_OP_SUBSCR_DICT_r23 677 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 678 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 679 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 680 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 681 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 682 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 683 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 684 -#define _BINARY_OP_SUBSCR_STR_INT_r23 685 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 686 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 687 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 688 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 689 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 690 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 691 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 692 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 693 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 694 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 695 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 696 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 697 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 698 -#define _BINARY_OP_SUBTRACT_INT_r03 699 -#define _BINARY_OP_SUBTRACT_INT_r13 700 -#define _BINARY_OP_SUBTRACT_INT_r23 701 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 702 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 703 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 704 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 705 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 706 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 707 -#define _BINARY_SLICE_r31 708 -#define _BUILD_INTERPOLATION_r01 709 -#define _BUILD_LIST_r01 710 -#define _BUILD_MAP_r01 711 -#define _BUILD_SET_r01 712 -#define _BUILD_SLICE_r01 713 -#define _BUILD_STRING_r01 714 -#define _BUILD_TEMPLATE_r21 715 -#define _BUILD_TUPLE_r01 716 -#define _CALL_BUILTIN_CLASS_r01 717 -#define _CALL_BUILTIN_FAST_r01 718 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 719 -#define _CALL_BUILTIN_O_r03 720 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 721 -#define _CALL_INTRINSIC_1_r12 722 -#define _CALL_INTRINSIC_2_r23 723 -#define _CALL_ISINSTANCE_r31 724 -#define _CALL_KW_NON_PY_r11 725 -#define _CALL_LEN_r33 726 -#define _CALL_LIST_APPEND_r03 727 -#define _CALL_LIST_APPEND_r13 728 -#define _CALL_LIST_APPEND_r23 729 -#define _CALL_LIST_APPEND_r33 730 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 731 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 732 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 733 -#define _CALL_METHOD_DESCRIPTOR_O_r03 734 -#define _CALL_NON_PY_GENERAL_r01 735 -#define _CALL_STR_1_r32 736 -#define _CALL_TUPLE_1_r32 737 -#define _CALL_TYPE_1_r02 738 -#define _CALL_TYPE_1_r12 739 -#define _CALL_TYPE_1_r22 740 -#define _CALL_TYPE_1_r32 741 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 742 -#define _CHECK_ATTR_CLASS_r01 743 -#define _CHECK_ATTR_CLASS_r11 744 -#define _CHECK_ATTR_CLASS_r22 745 -#define _CHECK_ATTR_CLASS_r33 746 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 747 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 748 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 749 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 750 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 751 -#define _CHECK_EG_MATCH_r22 752 -#define _CHECK_EXC_MATCH_r22 753 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 754 -#define _CHECK_FUNCTION_VERSION_r00 755 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 756 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 757 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 758 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 759 -#define _CHECK_FUNCTION_VERSION_KW_r11 760 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 761 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 762 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 763 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 764 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 765 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 766 -#define _CHECK_IS_PY_CALLABLE_EX_r03 767 -#define _CHECK_IS_PY_CALLABLE_EX_r13 768 -#define _CHECK_IS_PY_CALLABLE_EX_r23 769 -#define _CHECK_IS_PY_CALLABLE_EX_r33 770 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 771 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 772 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 773 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 774 -#define _CHECK_METHOD_VERSION_r00 775 -#define _CHECK_METHOD_VERSION_KW_r11 776 -#define _CHECK_PEP_523_r00 777 -#define _CHECK_PEP_523_r11 778 -#define _CHECK_PEP_523_r22 779 -#define _CHECK_PEP_523_r33 780 -#define _CHECK_PERIODIC_r00 781 -#define _CHECK_PERIODIC_AT_END_r00 782 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 783 -#define _CHECK_RECURSION_REMAINING_r00 784 -#define _CHECK_RECURSION_REMAINING_r11 785 -#define _CHECK_RECURSION_REMAINING_r22 786 -#define _CHECK_RECURSION_REMAINING_r33 787 -#define _CHECK_STACK_SPACE_r00 788 -#define _CHECK_STACK_SPACE_OPERAND_r00 789 -#define _CHECK_STACK_SPACE_OPERAND_r11 790 -#define _CHECK_STACK_SPACE_OPERAND_r22 791 -#define _CHECK_STACK_SPACE_OPERAND_r33 792 -#define _CHECK_VALIDITY_r00 793 -#define _CHECK_VALIDITY_r11 794 -#define _CHECK_VALIDITY_r22 795 -#define _CHECK_VALIDITY_r33 796 -#define _COLD_DYNAMIC_EXIT_r00 797 -#define _COLD_EXIT_r00 798 -#define _COMPARE_OP_r21 799 -#define _COMPARE_OP_FLOAT_r03 800 -#define _COMPARE_OP_FLOAT_r13 801 -#define _COMPARE_OP_FLOAT_r23 802 -#define _COMPARE_OP_INT_r23 803 -#define _COMPARE_OP_STR_r23 804 -#define _CONTAINS_OP_r23 805 -#define _CONTAINS_OP_DICT_r23 806 -#define _CONTAINS_OP_SET_r23 807 -#define _CONVERT_VALUE_r11 808 -#define _COPY_r01 809 -#define _COPY_1_r02 810 -#define _COPY_1_r12 811 -#define _COPY_1_r23 812 -#define _COPY_2_r03 813 -#define _COPY_2_r13 814 -#define _COPY_2_r23 815 -#define _COPY_3_r03 816 -#define _COPY_3_r13 817 -#define _COPY_3_r23 818 -#define _COPY_3_r33 819 -#define _COPY_FREE_VARS_r00 820 -#define _COPY_FREE_VARS_r11 821 -#define _COPY_FREE_VARS_r22 822 -#define _COPY_FREE_VARS_r33 823 -#define _CREATE_INIT_FRAME_r01 824 -#define _DELETE_ATTR_r10 825 -#define _DELETE_DEREF_r00 826 -#define _DELETE_FAST_r00 827 -#define _DELETE_GLOBAL_r00 828 -#define _DELETE_NAME_r00 829 -#define _DELETE_SUBSCR_r20 830 -#define _DEOPT_r00 831 -#define _DEOPT_r10 832 -#define _DEOPT_r20 833 -#define _DEOPT_r30 834 -#define _DICT_MERGE_r11 835 -#define _DICT_UPDATE_r11 836 -#define _DO_CALL_r01 837 -#define _DO_CALL_FUNCTION_EX_r31 838 -#define _DO_CALL_KW_r11 839 -#define _DYNAMIC_EXIT_r00 840 -#define _DYNAMIC_EXIT_r10 841 -#define _DYNAMIC_EXIT_r20 842 -#define _DYNAMIC_EXIT_r30 843 -#define _END_FOR_r10 844 -#define _END_SEND_r31 845 -#define _ERROR_POP_N_r00 846 -#define _EXIT_INIT_CHECK_r10 847 -#define _EXIT_TRACE_r00 848 -#define _EXIT_TRACE_r10 849 -#define _EXIT_TRACE_r20 850 -#define _EXIT_TRACE_r30 851 -#define _EXPAND_METHOD_r00 852 -#define _EXPAND_METHOD_KW_r11 853 -#define _FATAL_ERROR_r00 854 -#define _FATAL_ERROR_r11 855 -#define _FATAL_ERROR_r22 856 -#define _FATAL_ERROR_r33 857 -#define _FORMAT_SIMPLE_r11 858 -#define _FORMAT_WITH_SPEC_r21 859 -#define _FOR_ITER_r23 860 -#define _FOR_ITER_GEN_FRAME_r03 861 -#define _FOR_ITER_GEN_FRAME_r13 862 -#define _FOR_ITER_GEN_FRAME_r23 863 -#define _FOR_ITER_TIER_TWO_r23 864 -#define _GET_AITER_r11 865 -#define _GET_ANEXT_r12 866 -#define _GET_AWAITABLE_r11 867 -#define _GET_ITER_r12 868 -#define _GET_LEN_r12 869 -#define _GUARD_BINARY_OP_EXTEND_r22 870 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 871 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 872 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 873 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 874 -#define _GUARD_BIT_IS_SET_POP_r00 875 -#define _GUARD_BIT_IS_SET_POP_r10 876 -#define _GUARD_BIT_IS_SET_POP_r21 877 -#define _GUARD_BIT_IS_SET_POP_r32 878 -#define _GUARD_BIT_IS_SET_POP_4_r00 879 -#define _GUARD_BIT_IS_SET_POP_4_r10 880 -#define _GUARD_BIT_IS_SET_POP_4_r21 881 -#define _GUARD_BIT_IS_SET_POP_4_r32 882 -#define _GUARD_BIT_IS_SET_POP_5_r00 883 -#define _GUARD_BIT_IS_SET_POP_5_r10 884 -#define _GUARD_BIT_IS_SET_POP_5_r21 885 -#define _GUARD_BIT_IS_SET_POP_5_r32 886 -#define _GUARD_BIT_IS_SET_POP_6_r00 887 -#define _GUARD_BIT_IS_SET_POP_6_r10 888 -#define _GUARD_BIT_IS_SET_POP_6_r21 889 -#define _GUARD_BIT_IS_SET_POP_6_r32 890 -#define _GUARD_BIT_IS_SET_POP_7_r00 891 -#define _GUARD_BIT_IS_SET_POP_7_r10 892 -#define _GUARD_BIT_IS_SET_POP_7_r21 893 -#define _GUARD_BIT_IS_SET_POP_7_r32 894 -#define _GUARD_BIT_IS_UNSET_POP_r00 895 -#define _GUARD_BIT_IS_UNSET_POP_r10 896 -#define _GUARD_BIT_IS_UNSET_POP_r21 897 -#define _GUARD_BIT_IS_UNSET_POP_r32 898 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 899 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 900 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 901 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 902 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 903 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 904 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 905 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 906 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 907 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 908 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 909 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 910 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 911 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 912 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 913 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 914 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 915 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 916 -#define _GUARD_CALLABLE_BUILTIN_O_r00 917 -#define _GUARD_CALLABLE_ISINSTANCE_r03 918 -#define _GUARD_CALLABLE_ISINSTANCE_r13 919 -#define _GUARD_CALLABLE_ISINSTANCE_r23 920 -#define _GUARD_CALLABLE_ISINSTANCE_r33 921 -#define _GUARD_CALLABLE_LEN_r03 922 -#define _GUARD_CALLABLE_LEN_r13 923 -#define _GUARD_CALLABLE_LEN_r23 924 -#define _GUARD_CALLABLE_LEN_r33 925 -#define _GUARD_CALLABLE_LIST_APPEND_r03 926 -#define _GUARD_CALLABLE_LIST_APPEND_r13 927 -#define _GUARD_CALLABLE_LIST_APPEND_r23 928 -#define _GUARD_CALLABLE_LIST_APPEND_r33 929 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 930 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 931 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 932 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 933 -#define _GUARD_CALLABLE_STR_1_r03 934 -#define _GUARD_CALLABLE_STR_1_r13 935 -#define _GUARD_CALLABLE_STR_1_r23 936 -#define _GUARD_CALLABLE_STR_1_r33 937 -#define _GUARD_CALLABLE_TUPLE_1_r03 938 -#define _GUARD_CALLABLE_TUPLE_1_r13 939 -#define _GUARD_CALLABLE_TUPLE_1_r23 940 -#define _GUARD_CALLABLE_TUPLE_1_r33 941 -#define _GUARD_CALLABLE_TYPE_1_r03 942 -#define _GUARD_CALLABLE_TYPE_1_r13 943 -#define _GUARD_CALLABLE_TYPE_1_r23 944 -#define _GUARD_CALLABLE_TYPE_1_r33 945 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 946 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 947 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 948 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 949 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 950 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 951 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 952 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 953 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 954 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 955 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 956 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 957 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 958 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 959 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 960 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 961 -#define _GUARD_DORV_NO_DICT_r01 962 -#define _GUARD_DORV_NO_DICT_r11 963 -#define _GUARD_DORV_NO_DICT_r22 964 -#define _GUARD_DORV_NO_DICT_r33 965 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 966 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 967 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 968 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 969 -#define _GUARD_GLOBALS_VERSION_r00 970 -#define _GUARD_GLOBALS_VERSION_r11 971 -#define _GUARD_GLOBALS_VERSION_r22 972 -#define _GUARD_GLOBALS_VERSION_r33 973 -#define _GUARD_IP_RETURN_GENERATOR_r00 974 -#define _GUARD_IP_RETURN_GENERATOR_r11 975 -#define _GUARD_IP_RETURN_GENERATOR_r22 976 -#define _GUARD_IP_RETURN_GENERATOR_r33 977 -#define _GUARD_IP_RETURN_VALUE_r00 978 -#define _GUARD_IP_RETURN_VALUE_r11 979 -#define _GUARD_IP_RETURN_VALUE_r22 980 -#define _GUARD_IP_RETURN_VALUE_r33 981 -#define _GUARD_IP_YIELD_VALUE_r00 982 -#define _GUARD_IP_YIELD_VALUE_r11 983 -#define _GUARD_IP_YIELD_VALUE_r22 984 -#define _GUARD_IP_YIELD_VALUE_r33 985 -#define _GUARD_IP__PUSH_FRAME_r00 986 -#define _GUARD_IP__PUSH_FRAME_r11 987 -#define _GUARD_IP__PUSH_FRAME_r22 988 -#define _GUARD_IP__PUSH_FRAME_r33 989 -#define _GUARD_IS_FALSE_POP_r00 990 -#define _GUARD_IS_FALSE_POP_r10 991 -#define _GUARD_IS_FALSE_POP_r21 992 -#define _GUARD_IS_FALSE_POP_r32 993 -#define _GUARD_IS_NONE_POP_r00 994 -#define _GUARD_IS_NONE_POP_r10 995 -#define _GUARD_IS_NONE_POP_r21 996 -#define _GUARD_IS_NONE_POP_r32 997 -#define _GUARD_IS_NOT_NONE_POP_r10 998 -#define _GUARD_IS_TRUE_POP_r00 999 -#define _GUARD_IS_TRUE_POP_r10 1000 -#define _GUARD_IS_TRUE_POP_r21 1001 -#define _GUARD_IS_TRUE_POP_r32 1002 -#define _GUARD_KEYS_VERSION_r01 1003 -#define _GUARD_KEYS_VERSION_r11 1004 -#define _GUARD_KEYS_VERSION_r22 1005 -#define _GUARD_KEYS_VERSION_r33 1006 -#define _GUARD_NOS_ANY_DICT_r02 1007 -#define _GUARD_NOS_ANY_DICT_r12 1008 -#define _GUARD_NOS_ANY_DICT_r22 1009 -#define _GUARD_NOS_ANY_DICT_r33 1010 -#define _GUARD_NOS_COMPACT_ASCII_r02 1011 -#define _GUARD_NOS_COMPACT_ASCII_r12 1012 -#define _GUARD_NOS_COMPACT_ASCII_r22 1013 -#define _GUARD_NOS_COMPACT_ASCII_r33 1014 -#define _GUARD_NOS_DICT_r02 1015 -#define _GUARD_NOS_DICT_r12 1016 -#define _GUARD_NOS_DICT_r22 1017 -#define _GUARD_NOS_DICT_r33 1018 -#define _GUARD_NOS_FLOAT_r02 1019 -#define _GUARD_NOS_FLOAT_r12 1020 -#define _GUARD_NOS_FLOAT_r22 1021 -#define _GUARD_NOS_FLOAT_r33 1022 -#define _GUARD_NOS_INT_r02 1023 -#define _GUARD_NOS_INT_r12 1024 -#define _GUARD_NOS_INT_r22 1025 -#define _GUARD_NOS_INT_r33 1026 -#define _GUARD_NOS_LIST_r02 1027 -#define _GUARD_NOS_LIST_r12 1028 -#define _GUARD_NOS_LIST_r22 1029 -#define _GUARD_NOS_LIST_r33 1030 -#define _GUARD_NOS_NOT_NULL_r02 1031 -#define _GUARD_NOS_NOT_NULL_r12 1032 -#define _GUARD_NOS_NOT_NULL_r22 1033 -#define _GUARD_NOS_NOT_NULL_r33 1034 -#define _GUARD_NOS_NULL_r02 1035 -#define _GUARD_NOS_NULL_r12 1036 -#define _GUARD_NOS_NULL_r22 1037 -#define _GUARD_NOS_NULL_r33 1038 -#define _GUARD_NOS_OVERFLOWED_r02 1039 -#define _GUARD_NOS_OVERFLOWED_r12 1040 -#define _GUARD_NOS_OVERFLOWED_r22 1041 -#define _GUARD_NOS_OVERFLOWED_r33 1042 -#define _GUARD_NOS_TUPLE_r02 1043 -#define _GUARD_NOS_TUPLE_r12 1044 -#define _GUARD_NOS_TUPLE_r22 1045 -#define _GUARD_NOS_TUPLE_r33 1046 -#define _GUARD_NOS_UNICODE_r02 1047 -#define _GUARD_NOS_UNICODE_r12 1048 -#define _GUARD_NOS_UNICODE_r22 1049 -#define _GUARD_NOS_UNICODE_r33 1050 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1051 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1052 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1053 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1054 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1055 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1056 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1057 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1058 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1059 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1060 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1061 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1062 -#define _GUARD_THIRD_NULL_r03 1063 -#define _GUARD_THIRD_NULL_r13 1064 -#define _GUARD_THIRD_NULL_r23 1065 -#define _GUARD_THIRD_NULL_r33 1066 -#define _GUARD_TOS_ANY_DICT_r01 1067 -#define _GUARD_TOS_ANY_DICT_r11 1068 -#define _GUARD_TOS_ANY_DICT_r22 1069 -#define _GUARD_TOS_ANY_DICT_r33 1070 -#define _GUARD_TOS_ANY_SET_r01 1071 -#define _GUARD_TOS_ANY_SET_r11 1072 -#define _GUARD_TOS_ANY_SET_r22 1073 -#define _GUARD_TOS_ANY_SET_r33 1074 -#define _GUARD_TOS_DICT_r01 1075 -#define _GUARD_TOS_DICT_r11 1076 -#define _GUARD_TOS_DICT_r22 1077 -#define _GUARD_TOS_DICT_r33 1078 -#define _GUARD_TOS_FLOAT_r01 1079 -#define _GUARD_TOS_FLOAT_r11 1080 -#define _GUARD_TOS_FLOAT_r22 1081 -#define _GUARD_TOS_FLOAT_r33 1082 -#define _GUARD_TOS_FROZENDICT_r01 1083 -#define _GUARD_TOS_FROZENDICT_r11 1084 -#define _GUARD_TOS_FROZENDICT_r22 1085 -#define _GUARD_TOS_FROZENDICT_r33 1086 -#define _GUARD_TOS_FROZENSET_r01 1087 -#define _GUARD_TOS_FROZENSET_r11 1088 -#define _GUARD_TOS_FROZENSET_r22 1089 -#define _GUARD_TOS_FROZENSET_r33 1090 -#define _GUARD_TOS_INT_r01 1091 -#define _GUARD_TOS_INT_r11 1092 -#define _GUARD_TOS_INT_r22 1093 -#define _GUARD_TOS_INT_r33 1094 -#define _GUARD_TOS_LIST_r01 1095 -#define _GUARD_TOS_LIST_r11 1096 -#define _GUARD_TOS_LIST_r22 1097 -#define _GUARD_TOS_LIST_r33 1098 -#define _GUARD_TOS_OVERFLOWED_r01 1099 -#define _GUARD_TOS_OVERFLOWED_r11 1100 -#define _GUARD_TOS_OVERFLOWED_r22 1101 -#define _GUARD_TOS_OVERFLOWED_r33 1102 -#define _GUARD_TOS_SET_r01 1103 -#define _GUARD_TOS_SET_r11 1104 -#define _GUARD_TOS_SET_r22 1105 -#define _GUARD_TOS_SET_r33 1106 -#define _GUARD_TOS_SLICE_r01 1107 -#define _GUARD_TOS_SLICE_r11 1108 -#define _GUARD_TOS_SLICE_r22 1109 -#define _GUARD_TOS_SLICE_r33 1110 -#define _GUARD_TOS_TUPLE_r01 1111 -#define _GUARD_TOS_TUPLE_r11 1112 -#define _GUARD_TOS_TUPLE_r22 1113 -#define _GUARD_TOS_TUPLE_r33 1114 -#define _GUARD_TOS_UNICODE_r01 1115 -#define _GUARD_TOS_UNICODE_r11 1116 -#define _GUARD_TOS_UNICODE_r22 1117 -#define _GUARD_TOS_UNICODE_r33 1118 -#define _GUARD_TYPE_VERSION_r01 1119 -#define _GUARD_TYPE_VERSION_r11 1120 -#define _GUARD_TYPE_VERSION_r22 1121 -#define _GUARD_TYPE_VERSION_r33 1122 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1123 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1124 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1125 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1126 -#define _HANDLE_PENDING_AND_DEOPT_r00 1127 -#define _HANDLE_PENDING_AND_DEOPT_r10 1128 -#define _HANDLE_PENDING_AND_DEOPT_r20 1129 -#define _HANDLE_PENDING_AND_DEOPT_r30 1130 -#define _IMPORT_FROM_r12 1131 -#define _IMPORT_NAME_r21 1132 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1133 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1134 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1135 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1136 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1137 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1138 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1139 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1140 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1141 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1142 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1143 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1144 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1145 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1146 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1147 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1148 -#define _INSERT_NULL_r10 1149 -#define _INSTRUMENTED_FOR_ITER_r23 1150 -#define _INSTRUMENTED_INSTRUCTION_r00 1151 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1152 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1153 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1154 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1155 -#define _INSTRUMENTED_LINE_r00 1156 -#define _INSTRUMENTED_NOT_TAKEN_r00 1157 -#define _INSTRUMENTED_NOT_TAKEN_r11 1158 -#define _INSTRUMENTED_NOT_TAKEN_r22 1159 -#define _INSTRUMENTED_NOT_TAKEN_r33 1160 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1161 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1162 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1163 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1164 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1165 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1166 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1167 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1168 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1169 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1170 -#define _IS_NONE_r11 1171 -#define _IS_OP_r03 1172 -#define _IS_OP_r13 1173 -#define _IS_OP_r23 1174 -#define _ITER_CHECK_LIST_r02 1175 -#define _ITER_CHECK_LIST_r12 1176 -#define _ITER_CHECK_LIST_r22 1177 -#define _ITER_CHECK_LIST_r33 1178 -#define _ITER_CHECK_RANGE_r02 1179 -#define _ITER_CHECK_RANGE_r12 1180 -#define _ITER_CHECK_RANGE_r22 1181 -#define _ITER_CHECK_RANGE_r33 1182 -#define _ITER_CHECK_TUPLE_r02 1183 -#define _ITER_CHECK_TUPLE_r12 1184 -#define _ITER_CHECK_TUPLE_r22 1185 -#define _ITER_CHECK_TUPLE_r33 1186 -#define _ITER_JUMP_LIST_r02 1187 -#define _ITER_JUMP_LIST_r12 1188 -#define _ITER_JUMP_LIST_r22 1189 -#define _ITER_JUMP_LIST_r33 1190 -#define _ITER_JUMP_RANGE_r02 1191 -#define _ITER_JUMP_RANGE_r12 1192 -#define _ITER_JUMP_RANGE_r22 1193 -#define _ITER_JUMP_RANGE_r33 1194 -#define _ITER_JUMP_TUPLE_r02 1195 -#define _ITER_JUMP_TUPLE_r12 1196 -#define _ITER_JUMP_TUPLE_r22 1197 -#define _ITER_JUMP_TUPLE_r33 1198 -#define _ITER_NEXT_LIST_r23 1199 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1200 -#define _ITER_NEXT_RANGE_r03 1201 -#define _ITER_NEXT_RANGE_r13 1202 -#define _ITER_NEXT_RANGE_r23 1203 -#define _ITER_NEXT_TUPLE_r03 1204 -#define _ITER_NEXT_TUPLE_r13 1205 -#define _ITER_NEXT_TUPLE_r23 1206 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1207 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1208 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1209 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1210 -#define _JUMP_TO_TOP_r00 1211 -#define _LIST_APPEND_r10 1212 -#define _LIST_EXTEND_r11 1213 -#define _LOAD_ATTR_r10 1214 -#define _LOAD_ATTR_CLASS_r11 1215 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1216 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1217 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1218 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1219 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1220 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1221 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1222 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1223 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1224 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1225 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1226 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1227 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1228 -#define _LOAD_ATTR_MODULE_r12 1229 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1230 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1231 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1232 -#define _LOAD_ATTR_SLOT_r02 1233 -#define _LOAD_ATTR_SLOT_r12 1234 -#define _LOAD_ATTR_SLOT_r23 1235 -#define _LOAD_ATTR_WITH_HINT_r12 1236 -#define _LOAD_BUILD_CLASS_r01 1237 -#define _LOAD_BYTECODE_r00 1238 -#define _LOAD_COMMON_CONSTANT_r01 1239 -#define _LOAD_COMMON_CONSTANT_r12 1240 -#define _LOAD_COMMON_CONSTANT_r23 1241 -#define _LOAD_CONST_r01 1242 -#define _LOAD_CONST_r12 1243 -#define _LOAD_CONST_r23 1244 -#define _LOAD_CONST_INLINE_r01 1245 -#define _LOAD_CONST_INLINE_r12 1246 -#define _LOAD_CONST_INLINE_r23 1247 -#define _LOAD_CONST_INLINE_BORROW_r01 1248 -#define _LOAD_CONST_INLINE_BORROW_r12 1249 -#define _LOAD_CONST_INLINE_BORROW_r23 1250 -#define _LOAD_CONST_UNDER_INLINE_r02 1251 -#define _LOAD_CONST_UNDER_INLINE_r12 1252 -#define _LOAD_CONST_UNDER_INLINE_r23 1253 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1254 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1255 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1256 -#define _LOAD_DEREF_r01 1257 -#define _LOAD_FAST_r01 1258 -#define _LOAD_FAST_r12 1259 -#define _LOAD_FAST_r23 1260 -#define _LOAD_FAST_0_r01 1261 -#define _LOAD_FAST_0_r12 1262 -#define _LOAD_FAST_0_r23 1263 -#define _LOAD_FAST_1_r01 1264 -#define _LOAD_FAST_1_r12 1265 -#define _LOAD_FAST_1_r23 1266 -#define _LOAD_FAST_2_r01 1267 -#define _LOAD_FAST_2_r12 1268 -#define _LOAD_FAST_2_r23 1269 -#define _LOAD_FAST_3_r01 1270 -#define _LOAD_FAST_3_r12 1271 -#define _LOAD_FAST_3_r23 1272 -#define _LOAD_FAST_4_r01 1273 -#define _LOAD_FAST_4_r12 1274 -#define _LOAD_FAST_4_r23 1275 -#define _LOAD_FAST_5_r01 1276 -#define _LOAD_FAST_5_r12 1277 -#define _LOAD_FAST_5_r23 1278 -#define _LOAD_FAST_6_r01 1279 -#define _LOAD_FAST_6_r12 1280 -#define _LOAD_FAST_6_r23 1281 -#define _LOAD_FAST_7_r01 1282 -#define _LOAD_FAST_7_r12 1283 -#define _LOAD_FAST_7_r23 1284 -#define _LOAD_FAST_AND_CLEAR_r01 1285 -#define _LOAD_FAST_AND_CLEAR_r12 1286 -#define _LOAD_FAST_AND_CLEAR_r23 1287 -#define _LOAD_FAST_BORROW_r01 1288 -#define _LOAD_FAST_BORROW_r12 1289 -#define _LOAD_FAST_BORROW_r23 1290 -#define _LOAD_FAST_BORROW_0_r01 1291 -#define _LOAD_FAST_BORROW_0_r12 1292 -#define _LOAD_FAST_BORROW_0_r23 1293 -#define _LOAD_FAST_BORROW_1_r01 1294 -#define _LOAD_FAST_BORROW_1_r12 1295 -#define _LOAD_FAST_BORROW_1_r23 1296 -#define _LOAD_FAST_BORROW_2_r01 1297 -#define _LOAD_FAST_BORROW_2_r12 1298 -#define _LOAD_FAST_BORROW_2_r23 1299 -#define _LOAD_FAST_BORROW_3_r01 1300 -#define _LOAD_FAST_BORROW_3_r12 1301 -#define _LOAD_FAST_BORROW_3_r23 1302 -#define _LOAD_FAST_BORROW_4_r01 1303 -#define _LOAD_FAST_BORROW_4_r12 1304 -#define _LOAD_FAST_BORROW_4_r23 1305 -#define _LOAD_FAST_BORROW_5_r01 1306 -#define _LOAD_FAST_BORROW_5_r12 1307 -#define _LOAD_FAST_BORROW_5_r23 1308 -#define _LOAD_FAST_BORROW_6_r01 1309 -#define _LOAD_FAST_BORROW_6_r12 1310 -#define _LOAD_FAST_BORROW_6_r23 1311 -#define _LOAD_FAST_BORROW_7_r01 1312 -#define _LOAD_FAST_BORROW_7_r12 1313 -#define _LOAD_FAST_BORROW_7_r23 1314 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1315 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1316 -#define _LOAD_FAST_CHECK_r01 1317 -#define _LOAD_FAST_CHECK_r12 1318 -#define _LOAD_FAST_CHECK_r23 1319 -#define _LOAD_FAST_LOAD_FAST_r02 1320 -#define _LOAD_FAST_LOAD_FAST_r13 1321 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1322 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1323 -#define _LOAD_GLOBAL_r00 1324 -#define _LOAD_GLOBAL_BUILTINS_r01 1325 -#define _LOAD_GLOBAL_MODULE_r01 1326 -#define _LOAD_LOCALS_r01 1327 -#define _LOAD_LOCALS_r12 1328 -#define _LOAD_LOCALS_r23 1329 -#define _LOAD_NAME_r01 1330 -#define _LOAD_SMALL_INT_r01 1331 -#define _LOAD_SMALL_INT_r12 1332 -#define _LOAD_SMALL_INT_r23 1333 -#define _LOAD_SMALL_INT_0_r01 1334 -#define _LOAD_SMALL_INT_0_r12 1335 -#define _LOAD_SMALL_INT_0_r23 1336 -#define _LOAD_SMALL_INT_1_r01 1337 -#define _LOAD_SMALL_INT_1_r12 1338 -#define _LOAD_SMALL_INT_1_r23 1339 -#define _LOAD_SMALL_INT_2_r01 1340 -#define _LOAD_SMALL_INT_2_r12 1341 -#define _LOAD_SMALL_INT_2_r23 1342 -#define _LOAD_SMALL_INT_3_r01 1343 -#define _LOAD_SMALL_INT_3_r12 1344 -#define _LOAD_SMALL_INT_3_r23 1345 -#define _LOAD_SPECIAL_r00 1346 -#define _LOAD_SUPER_ATTR_ATTR_r31 1347 -#define _LOAD_SUPER_ATTR_METHOD_r32 1348 -#define _LOCK_OBJECT_r01 1349 -#define _LOCK_OBJECT_r11 1350 -#define _LOCK_OBJECT_r22 1351 -#define _LOCK_OBJECT_r33 1352 -#define _MAKE_CALLARGS_A_TUPLE_r33 1353 -#define _MAKE_CELL_r00 1354 -#define _MAKE_FUNCTION_r11 1355 -#define _MAKE_HEAP_SAFE_r01 1356 -#define _MAKE_HEAP_SAFE_r11 1357 -#define _MAKE_HEAP_SAFE_r22 1358 -#define _MAKE_HEAP_SAFE_r33 1359 -#define _MAKE_WARM_r00 1360 -#define _MAKE_WARM_r11 1361 -#define _MAKE_WARM_r22 1362 -#define _MAKE_WARM_r33 1363 -#define _MAP_ADD_r20 1364 -#define _MATCH_CLASS_r33 1365 -#define _MATCH_KEYS_r23 1366 -#define _MATCH_MAPPING_r02 1367 -#define _MATCH_MAPPING_r12 1368 -#define _MATCH_MAPPING_r23 1369 -#define _MATCH_SEQUENCE_r02 1370 -#define _MATCH_SEQUENCE_r12 1371 -#define _MATCH_SEQUENCE_r23 1372 -#define _MAYBE_EXPAND_METHOD_r00 1373 -#define _MAYBE_EXPAND_METHOD_KW_r11 1374 -#define _MONITOR_CALL_r00 1375 -#define _MONITOR_CALL_KW_r11 1376 -#define _MONITOR_JUMP_BACKWARD_r00 1377 -#define _MONITOR_JUMP_BACKWARD_r11 1378 -#define _MONITOR_JUMP_BACKWARD_r22 1379 -#define _MONITOR_JUMP_BACKWARD_r33 1380 -#define _MONITOR_RESUME_r00 1381 -#define _NOP_r00 1382 -#define _NOP_r11 1383 -#define _NOP_r22 1384 -#define _NOP_r33 1385 -#define _POP_CALL_r20 1386 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1387 -#define _POP_CALL_ONE_r30 1388 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1389 -#define _POP_CALL_TWO_r30 1390 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1391 -#define _POP_EXCEPT_r10 1392 -#define _POP_ITER_r20 1393 -#define _POP_JUMP_IF_FALSE_r00 1394 -#define _POP_JUMP_IF_FALSE_r10 1395 -#define _POP_JUMP_IF_FALSE_r21 1396 -#define _POP_JUMP_IF_FALSE_r32 1397 -#define _POP_JUMP_IF_TRUE_r00 1398 -#define _POP_JUMP_IF_TRUE_r10 1399 -#define _POP_JUMP_IF_TRUE_r21 1400 -#define _POP_JUMP_IF_TRUE_r32 1401 -#define _POP_TOP_r10 1402 -#define _POP_TOP_FLOAT_r00 1403 -#define _POP_TOP_FLOAT_r10 1404 -#define _POP_TOP_FLOAT_r21 1405 -#define _POP_TOP_FLOAT_r32 1406 -#define _POP_TOP_INT_r00 1407 -#define _POP_TOP_INT_r10 1408 -#define _POP_TOP_INT_r21 1409 -#define _POP_TOP_INT_r32 1410 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1411 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1412 -#define _POP_TOP_NOP_r00 1413 -#define _POP_TOP_NOP_r10 1414 -#define _POP_TOP_NOP_r21 1415 -#define _POP_TOP_NOP_r32 1416 -#define _POP_TOP_UNICODE_r00 1417 -#define _POP_TOP_UNICODE_r10 1418 -#define _POP_TOP_UNICODE_r21 1419 -#define _POP_TOP_UNICODE_r32 1420 -#define _POP_TWO_r20 1421 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1422 -#define _PUSH_EXC_INFO_r02 1423 -#define _PUSH_EXC_INFO_r12 1424 -#define _PUSH_EXC_INFO_r23 1425 -#define _PUSH_FRAME_r10 1426 -#define _PUSH_NULL_r01 1427 -#define _PUSH_NULL_r12 1428 -#define _PUSH_NULL_r23 1429 -#define _PUSH_NULL_CONDITIONAL_r00 1430 -#define _PY_FRAME_EX_r31 1431 -#define _PY_FRAME_GENERAL_r01 1432 -#define _PY_FRAME_KW_r11 1433 -#define _REPLACE_WITH_TRUE_r02 1434 -#define _REPLACE_WITH_TRUE_r12 1435 -#define _REPLACE_WITH_TRUE_r23 1436 -#define _RESUME_CHECK_r00 1437 -#define _RESUME_CHECK_r11 1438 -#define _RESUME_CHECK_r22 1439 -#define _RESUME_CHECK_r33 1440 -#define _RETURN_GENERATOR_r01 1441 -#define _RETURN_VALUE_r11 1442 -#define _SAVE_RETURN_OFFSET_r00 1443 -#define _SAVE_RETURN_OFFSET_r11 1444 -#define _SAVE_RETURN_OFFSET_r22 1445 -#define _SAVE_RETURN_OFFSET_r33 1446 -#define _SEND_r33 1447 -#define _SEND_GEN_FRAME_r33 1448 -#define _SETUP_ANNOTATIONS_r00 1449 -#define _SET_ADD_r10 1450 -#define _SET_FUNCTION_ATTRIBUTE_r01 1451 -#define _SET_FUNCTION_ATTRIBUTE_r11 1452 -#define _SET_FUNCTION_ATTRIBUTE_r21 1453 -#define _SET_FUNCTION_ATTRIBUTE_r32 1454 -#define _SET_IP_r00 1455 -#define _SET_IP_r11 1456 -#define _SET_IP_r22 1457 -#define _SET_IP_r33 1458 -#define _SET_UPDATE_r11 1459 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1460 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1461 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1462 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1463 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1464 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1465 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1466 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1467 -#define _SPILL_OR_RELOAD_r01 1468 -#define _SPILL_OR_RELOAD_r02 1469 -#define _SPILL_OR_RELOAD_r03 1470 -#define _SPILL_OR_RELOAD_r10 1471 -#define _SPILL_OR_RELOAD_r12 1472 -#define _SPILL_OR_RELOAD_r13 1473 -#define _SPILL_OR_RELOAD_r20 1474 -#define _SPILL_OR_RELOAD_r21 1475 -#define _SPILL_OR_RELOAD_r23 1476 -#define _SPILL_OR_RELOAD_r30 1477 -#define _SPILL_OR_RELOAD_r31 1478 -#define _SPILL_OR_RELOAD_r32 1479 -#define _START_EXECUTOR_r00 1480 -#define _STORE_ATTR_r20 1481 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1482 -#define _STORE_ATTR_SLOT_r21 1483 -#define _STORE_ATTR_WITH_HINT_r21 1484 -#define _STORE_DEREF_r10 1485 -#define _STORE_FAST_LOAD_FAST_r11 1486 -#define _STORE_FAST_STORE_FAST_r20 1487 -#define _STORE_GLOBAL_r10 1488 -#define _STORE_NAME_r10 1489 -#define _STORE_SLICE_r30 1490 -#define _STORE_SUBSCR_r30 1491 -#define _STORE_SUBSCR_DICT_r31 1492 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1493 -#define _STORE_SUBSCR_LIST_INT_r32 1494 -#define _SWAP_r11 1495 -#define _SWAP_2_r02 1496 -#define _SWAP_2_r12 1497 -#define _SWAP_2_r22 1498 -#define _SWAP_2_r33 1499 -#define _SWAP_3_r03 1500 -#define _SWAP_3_r13 1501 -#define _SWAP_3_r23 1502 -#define _SWAP_3_r33 1503 -#define _SWAP_FAST_r01 1504 -#define _SWAP_FAST_r11 1505 -#define _SWAP_FAST_r22 1506 -#define _SWAP_FAST_r33 1507 -#define _SWAP_FAST_0_r01 1508 -#define _SWAP_FAST_0_r11 1509 -#define _SWAP_FAST_0_r22 1510 -#define _SWAP_FAST_0_r33 1511 -#define _SWAP_FAST_1_r01 1512 -#define _SWAP_FAST_1_r11 1513 -#define _SWAP_FAST_1_r22 1514 -#define _SWAP_FAST_1_r33 1515 -#define _SWAP_FAST_2_r01 1516 -#define _SWAP_FAST_2_r11 1517 -#define _SWAP_FAST_2_r22 1518 -#define _SWAP_FAST_2_r33 1519 -#define _SWAP_FAST_3_r01 1520 -#define _SWAP_FAST_3_r11 1521 -#define _SWAP_FAST_3_r22 1522 -#define _SWAP_FAST_3_r33 1523 -#define _SWAP_FAST_4_r01 1524 -#define _SWAP_FAST_4_r11 1525 -#define _SWAP_FAST_4_r22 1526 -#define _SWAP_FAST_4_r33 1527 -#define _SWAP_FAST_5_r01 1528 -#define _SWAP_FAST_5_r11 1529 -#define _SWAP_FAST_5_r22 1530 -#define _SWAP_FAST_5_r33 1531 -#define _SWAP_FAST_6_r01 1532 -#define _SWAP_FAST_6_r11 1533 -#define _SWAP_FAST_6_r22 1534 -#define _SWAP_FAST_6_r33 1535 -#define _SWAP_FAST_7_r01 1536 -#define _SWAP_FAST_7_r11 1537 -#define _SWAP_FAST_7_r22 1538 -#define _SWAP_FAST_7_r33 1539 -#define _TIER2_RESUME_CHECK_r00 1540 -#define _TIER2_RESUME_CHECK_r11 1541 -#define _TIER2_RESUME_CHECK_r22 1542 -#define _TIER2_RESUME_CHECK_r33 1543 -#define _TO_BOOL_r11 1544 -#define _TO_BOOL_BOOL_r01 1545 -#define _TO_BOOL_BOOL_r11 1546 -#define _TO_BOOL_BOOL_r22 1547 -#define _TO_BOOL_BOOL_r33 1548 -#define _TO_BOOL_INT_r02 1549 -#define _TO_BOOL_INT_r12 1550 -#define _TO_BOOL_INT_r23 1551 -#define _TO_BOOL_LIST_r02 1552 -#define _TO_BOOL_LIST_r12 1553 -#define _TO_BOOL_LIST_r23 1554 -#define _TO_BOOL_NONE_r01 1555 -#define _TO_BOOL_NONE_r11 1556 -#define _TO_BOOL_NONE_r22 1557 -#define _TO_BOOL_NONE_r33 1558 -#define _TO_BOOL_STR_r02 1559 -#define _TO_BOOL_STR_r12 1560 -#define _TO_BOOL_STR_r23 1561 -#define _TRACE_RECORD_r00 1562 -#define _UNARY_INVERT_r12 1563 -#define _UNARY_NEGATIVE_r12 1564 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1565 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1566 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1567 -#define _UNARY_NOT_r01 1568 -#define _UNARY_NOT_r11 1569 -#define _UNARY_NOT_r22 1570 -#define _UNARY_NOT_r33 1571 -#define _UNPACK_EX_r10 1572 -#define _UNPACK_SEQUENCE_r10 1573 -#define _UNPACK_SEQUENCE_LIST_r10 1574 -#define _UNPACK_SEQUENCE_TUPLE_r10 1575 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1576 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1577 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1578 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1579 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1580 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1581 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1582 -#define _WITH_EXCEPT_START_r33 1583 -#define _YIELD_VALUE_r11 1584 -#define MAX_UOP_REGS_ID 1584 +#define _YIELD_VALUE 637 +#define MAX_UOP_ID 637 +#define _BINARY_OP_r23 638 +#define _BINARY_OP_ADD_FLOAT_r03 639 +#define _BINARY_OP_ADD_FLOAT_r13 640 +#define _BINARY_OP_ADD_FLOAT_r23 641 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 642 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 643 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 644 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 645 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 646 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 647 +#define _BINARY_OP_ADD_INT_r03 648 +#define _BINARY_OP_ADD_INT_r13 649 +#define _BINARY_OP_ADD_INT_r23 650 +#define _BINARY_OP_ADD_INT_INPLACE_r03 651 +#define _BINARY_OP_ADD_INT_INPLACE_r13 652 +#define _BINARY_OP_ADD_INT_INPLACE_r23 653 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 654 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 655 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 656 +#define _BINARY_OP_ADD_UNICODE_r03 657 +#define _BINARY_OP_ADD_UNICODE_r13 658 +#define _BINARY_OP_ADD_UNICODE_r23 659 +#define _BINARY_OP_EXTEND_r23 660 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 661 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 662 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 663 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 664 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 665 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 666 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 667 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 668 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 669 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 670 +#define _BINARY_OP_MULTIPLY_INT_r03 671 +#define _BINARY_OP_MULTIPLY_INT_r13 672 +#define _BINARY_OP_MULTIPLY_INT_r23 673 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 674 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 675 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 676 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 677 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 678 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 679 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 680 +#define _BINARY_OP_SUBSCR_DICT_r23 681 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 682 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 683 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 684 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 685 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 686 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 687 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 688 +#define _BINARY_OP_SUBSCR_STR_INT_r23 689 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 690 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 691 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 692 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 693 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 694 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 695 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 696 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 697 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 698 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 699 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 700 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 701 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 702 +#define _BINARY_OP_SUBTRACT_INT_r03 703 +#define _BINARY_OP_SUBTRACT_INT_r13 704 +#define _BINARY_OP_SUBTRACT_INT_r23 705 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 706 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 707 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 708 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 709 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 710 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 711 +#define _BINARY_SLICE_r31 712 +#define _BUILD_INTERPOLATION_r01 713 +#define _BUILD_LIST_r01 714 +#define _BUILD_MAP_r01 715 +#define _BUILD_SET_r01 716 +#define _BUILD_SLICE_r01 717 +#define _BUILD_STRING_r01 718 +#define _BUILD_TEMPLATE_r21 719 +#define _BUILD_TUPLE_r01 720 +#define _CALL_BUILTIN_CLASS_r01 721 +#define _CALL_BUILTIN_FAST_r01 722 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 723 +#define _CALL_BUILTIN_O_r03 724 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 725 +#define _CALL_INTRINSIC_1_r12 726 +#define _CALL_INTRINSIC_2_r23 727 +#define _CALL_ISINSTANCE_r31 728 +#define _CALL_KW_NON_PY_r11 729 +#define _CALL_LEN_r33 730 +#define _CALL_LIST_APPEND_r03 731 +#define _CALL_LIST_APPEND_r13 732 +#define _CALL_LIST_APPEND_r23 733 +#define _CALL_LIST_APPEND_r33 734 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 735 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01 736 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 737 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01 738 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 739 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01 740 +#define _CALL_METHOD_DESCRIPTOR_O_r03 741 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 742 +#define _CALL_NON_PY_GENERAL_r01 743 +#define _CALL_STR_1_r32 744 +#define _CALL_TUPLE_1_r32 745 +#define _CALL_TYPE_1_r02 746 +#define _CALL_TYPE_1_r12 747 +#define _CALL_TYPE_1_r22 748 +#define _CALL_TYPE_1_r32 749 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 750 +#define _CHECK_ATTR_CLASS_r01 751 +#define _CHECK_ATTR_CLASS_r11 752 +#define _CHECK_ATTR_CLASS_r22 753 +#define _CHECK_ATTR_CLASS_r33 754 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 755 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 756 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 757 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 758 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 759 +#define _CHECK_EG_MATCH_r22 760 +#define _CHECK_EXC_MATCH_r22 761 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 762 +#define _CHECK_FUNCTION_VERSION_r00 763 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 764 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 765 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 766 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 767 +#define _CHECK_FUNCTION_VERSION_KW_r11 768 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 769 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 770 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 771 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 772 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 773 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 774 +#define _CHECK_IS_PY_CALLABLE_EX_r03 775 +#define _CHECK_IS_PY_CALLABLE_EX_r13 776 +#define _CHECK_IS_PY_CALLABLE_EX_r23 777 +#define _CHECK_IS_PY_CALLABLE_EX_r33 778 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 779 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 780 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 781 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 782 +#define _CHECK_METHOD_VERSION_r00 783 +#define _CHECK_METHOD_VERSION_KW_r11 784 +#define _CHECK_PEP_523_r00 785 +#define _CHECK_PEP_523_r11 786 +#define _CHECK_PEP_523_r22 787 +#define _CHECK_PEP_523_r33 788 +#define _CHECK_PERIODIC_r00 789 +#define _CHECK_PERIODIC_AT_END_r00 790 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 791 +#define _CHECK_RECURSION_REMAINING_r00 792 +#define _CHECK_RECURSION_REMAINING_r11 793 +#define _CHECK_RECURSION_REMAINING_r22 794 +#define _CHECK_RECURSION_REMAINING_r33 795 +#define _CHECK_STACK_SPACE_r00 796 +#define _CHECK_STACK_SPACE_OPERAND_r00 797 +#define _CHECK_STACK_SPACE_OPERAND_r11 798 +#define _CHECK_STACK_SPACE_OPERAND_r22 799 +#define _CHECK_STACK_SPACE_OPERAND_r33 800 +#define _CHECK_VALIDITY_r00 801 +#define _CHECK_VALIDITY_r11 802 +#define _CHECK_VALIDITY_r22 803 +#define _CHECK_VALIDITY_r33 804 +#define _COLD_DYNAMIC_EXIT_r00 805 +#define _COLD_EXIT_r00 806 +#define _COMPARE_OP_r21 807 +#define _COMPARE_OP_FLOAT_r03 808 +#define _COMPARE_OP_FLOAT_r13 809 +#define _COMPARE_OP_FLOAT_r23 810 +#define _COMPARE_OP_INT_r23 811 +#define _COMPARE_OP_STR_r23 812 +#define _CONTAINS_OP_r23 813 +#define _CONTAINS_OP_DICT_r23 814 +#define _CONTAINS_OP_SET_r23 815 +#define _CONVERT_VALUE_r11 816 +#define _COPY_r01 817 +#define _COPY_1_r02 818 +#define _COPY_1_r12 819 +#define _COPY_1_r23 820 +#define _COPY_2_r03 821 +#define _COPY_2_r13 822 +#define _COPY_2_r23 823 +#define _COPY_3_r03 824 +#define _COPY_3_r13 825 +#define _COPY_3_r23 826 +#define _COPY_3_r33 827 +#define _COPY_FREE_VARS_r00 828 +#define _COPY_FREE_VARS_r11 829 +#define _COPY_FREE_VARS_r22 830 +#define _COPY_FREE_VARS_r33 831 +#define _CREATE_INIT_FRAME_r01 832 +#define _DELETE_ATTR_r10 833 +#define _DELETE_DEREF_r00 834 +#define _DELETE_FAST_r00 835 +#define _DELETE_GLOBAL_r00 836 +#define _DELETE_NAME_r00 837 +#define _DELETE_SUBSCR_r20 838 +#define _DEOPT_r00 839 +#define _DEOPT_r10 840 +#define _DEOPT_r20 841 +#define _DEOPT_r30 842 +#define _DICT_MERGE_r11 843 +#define _DICT_UPDATE_r11 844 +#define _DO_CALL_r01 845 +#define _DO_CALL_FUNCTION_EX_r31 846 +#define _DO_CALL_KW_r11 847 +#define _DYNAMIC_EXIT_r00 848 +#define _DYNAMIC_EXIT_r10 849 +#define _DYNAMIC_EXIT_r20 850 +#define _DYNAMIC_EXIT_r30 851 +#define _END_FOR_r10 852 +#define _END_SEND_r31 853 +#define _ERROR_POP_N_r00 854 +#define _EXIT_INIT_CHECK_r10 855 +#define _EXIT_TRACE_r00 856 +#define _EXIT_TRACE_r10 857 +#define _EXIT_TRACE_r20 858 +#define _EXIT_TRACE_r30 859 +#define _EXPAND_METHOD_r00 860 +#define _EXPAND_METHOD_KW_r11 861 +#define _FATAL_ERROR_r00 862 +#define _FATAL_ERROR_r11 863 +#define _FATAL_ERROR_r22 864 +#define _FATAL_ERROR_r33 865 +#define _FORMAT_SIMPLE_r11 866 +#define _FORMAT_WITH_SPEC_r21 867 +#define _FOR_ITER_r23 868 +#define _FOR_ITER_GEN_FRAME_r03 869 +#define _FOR_ITER_GEN_FRAME_r13 870 +#define _FOR_ITER_GEN_FRAME_r23 871 +#define _FOR_ITER_TIER_TWO_r23 872 +#define _GET_AITER_r11 873 +#define _GET_ANEXT_r12 874 +#define _GET_AWAITABLE_r11 875 +#define _GET_ITER_r12 876 +#define _GET_LEN_r12 877 +#define _GUARD_BINARY_OP_EXTEND_r22 878 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 879 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 880 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 881 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 882 +#define _GUARD_BIT_IS_SET_POP_r00 883 +#define _GUARD_BIT_IS_SET_POP_r10 884 +#define _GUARD_BIT_IS_SET_POP_r21 885 +#define _GUARD_BIT_IS_SET_POP_r32 886 +#define _GUARD_BIT_IS_SET_POP_4_r00 887 +#define _GUARD_BIT_IS_SET_POP_4_r10 888 +#define _GUARD_BIT_IS_SET_POP_4_r21 889 +#define _GUARD_BIT_IS_SET_POP_4_r32 890 +#define _GUARD_BIT_IS_SET_POP_5_r00 891 +#define _GUARD_BIT_IS_SET_POP_5_r10 892 +#define _GUARD_BIT_IS_SET_POP_5_r21 893 +#define _GUARD_BIT_IS_SET_POP_5_r32 894 +#define _GUARD_BIT_IS_SET_POP_6_r00 895 +#define _GUARD_BIT_IS_SET_POP_6_r10 896 +#define _GUARD_BIT_IS_SET_POP_6_r21 897 +#define _GUARD_BIT_IS_SET_POP_6_r32 898 +#define _GUARD_BIT_IS_SET_POP_7_r00 899 +#define _GUARD_BIT_IS_SET_POP_7_r10 900 +#define _GUARD_BIT_IS_SET_POP_7_r21 901 +#define _GUARD_BIT_IS_SET_POP_7_r32 902 +#define _GUARD_BIT_IS_UNSET_POP_r00 903 +#define _GUARD_BIT_IS_UNSET_POP_r10 904 +#define _GUARD_BIT_IS_UNSET_POP_r21 905 +#define _GUARD_BIT_IS_UNSET_POP_r32 906 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 907 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 908 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 909 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 910 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 911 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 912 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 913 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 914 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 915 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 916 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 917 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 918 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 919 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 920 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 921 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 922 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 923 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 924 +#define _GUARD_CALLABLE_BUILTIN_O_r00 925 +#define _GUARD_CALLABLE_ISINSTANCE_r03 926 +#define _GUARD_CALLABLE_ISINSTANCE_r13 927 +#define _GUARD_CALLABLE_ISINSTANCE_r23 928 +#define _GUARD_CALLABLE_ISINSTANCE_r33 929 +#define _GUARD_CALLABLE_LEN_r03 930 +#define _GUARD_CALLABLE_LEN_r13 931 +#define _GUARD_CALLABLE_LEN_r23 932 +#define _GUARD_CALLABLE_LEN_r33 933 +#define _GUARD_CALLABLE_LIST_APPEND_r03 934 +#define _GUARD_CALLABLE_LIST_APPEND_r13 935 +#define _GUARD_CALLABLE_LIST_APPEND_r23 936 +#define _GUARD_CALLABLE_LIST_APPEND_r33 937 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 938 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 939 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 940 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 941 +#define _GUARD_CALLABLE_STR_1_r03 942 +#define _GUARD_CALLABLE_STR_1_r13 943 +#define _GUARD_CALLABLE_STR_1_r23 944 +#define _GUARD_CALLABLE_STR_1_r33 945 +#define _GUARD_CALLABLE_TUPLE_1_r03 946 +#define _GUARD_CALLABLE_TUPLE_1_r13 947 +#define _GUARD_CALLABLE_TUPLE_1_r23 948 +#define _GUARD_CALLABLE_TUPLE_1_r33 949 +#define _GUARD_CALLABLE_TYPE_1_r03 950 +#define _GUARD_CALLABLE_TYPE_1_r13 951 +#define _GUARD_CALLABLE_TYPE_1_r23 952 +#define _GUARD_CALLABLE_TYPE_1_r33 953 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 954 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 955 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 956 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 957 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 958 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 959 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 960 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 961 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 962 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 963 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 964 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 965 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 966 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 967 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 968 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 969 +#define _GUARD_DORV_NO_DICT_r01 970 +#define _GUARD_DORV_NO_DICT_r11 971 +#define _GUARD_DORV_NO_DICT_r22 972 +#define _GUARD_DORV_NO_DICT_r33 973 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 974 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 975 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 976 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 977 +#define _GUARD_GLOBALS_VERSION_r00 978 +#define _GUARD_GLOBALS_VERSION_r11 979 +#define _GUARD_GLOBALS_VERSION_r22 980 +#define _GUARD_GLOBALS_VERSION_r33 981 +#define _GUARD_IP_RETURN_GENERATOR_r00 982 +#define _GUARD_IP_RETURN_GENERATOR_r11 983 +#define _GUARD_IP_RETURN_GENERATOR_r22 984 +#define _GUARD_IP_RETURN_GENERATOR_r33 985 +#define _GUARD_IP_RETURN_VALUE_r00 986 +#define _GUARD_IP_RETURN_VALUE_r11 987 +#define _GUARD_IP_RETURN_VALUE_r22 988 +#define _GUARD_IP_RETURN_VALUE_r33 989 +#define _GUARD_IP_YIELD_VALUE_r00 990 +#define _GUARD_IP_YIELD_VALUE_r11 991 +#define _GUARD_IP_YIELD_VALUE_r22 992 +#define _GUARD_IP_YIELD_VALUE_r33 993 +#define _GUARD_IP__PUSH_FRAME_r00 994 +#define _GUARD_IP__PUSH_FRAME_r11 995 +#define _GUARD_IP__PUSH_FRAME_r22 996 +#define _GUARD_IP__PUSH_FRAME_r33 997 +#define _GUARD_IS_FALSE_POP_r00 998 +#define _GUARD_IS_FALSE_POP_r10 999 +#define _GUARD_IS_FALSE_POP_r21 1000 +#define _GUARD_IS_FALSE_POP_r32 1001 +#define _GUARD_IS_NONE_POP_r00 1002 +#define _GUARD_IS_NONE_POP_r10 1003 +#define _GUARD_IS_NONE_POP_r21 1004 +#define _GUARD_IS_NONE_POP_r32 1005 +#define _GUARD_IS_NOT_NONE_POP_r10 1006 +#define _GUARD_IS_TRUE_POP_r00 1007 +#define _GUARD_IS_TRUE_POP_r10 1008 +#define _GUARD_IS_TRUE_POP_r21 1009 +#define _GUARD_IS_TRUE_POP_r32 1010 +#define _GUARD_KEYS_VERSION_r01 1011 +#define _GUARD_KEYS_VERSION_r11 1012 +#define _GUARD_KEYS_VERSION_r22 1013 +#define _GUARD_KEYS_VERSION_r33 1014 +#define _GUARD_NOS_ANY_DICT_r02 1015 +#define _GUARD_NOS_ANY_DICT_r12 1016 +#define _GUARD_NOS_ANY_DICT_r22 1017 +#define _GUARD_NOS_ANY_DICT_r33 1018 +#define _GUARD_NOS_COMPACT_ASCII_r02 1019 +#define _GUARD_NOS_COMPACT_ASCII_r12 1020 +#define _GUARD_NOS_COMPACT_ASCII_r22 1021 +#define _GUARD_NOS_COMPACT_ASCII_r33 1022 +#define _GUARD_NOS_DICT_r02 1023 +#define _GUARD_NOS_DICT_r12 1024 +#define _GUARD_NOS_DICT_r22 1025 +#define _GUARD_NOS_DICT_r33 1026 +#define _GUARD_NOS_FLOAT_r02 1027 +#define _GUARD_NOS_FLOAT_r12 1028 +#define _GUARD_NOS_FLOAT_r22 1029 +#define _GUARD_NOS_FLOAT_r33 1030 +#define _GUARD_NOS_INT_r02 1031 +#define _GUARD_NOS_INT_r12 1032 +#define _GUARD_NOS_INT_r22 1033 +#define _GUARD_NOS_INT_r33 1034 +#define _GUARD_NOS_LIST_r02 1035 +#define _GUARD_NOS_LIST_r12 1036 +#define _GUARD_NOS_LIST_r22 1037 +#define _GUARD_NOS_LIST_r33 1038 +#define _GUARD_NOS_NOT_NULL_r02 1039 +#define _GUARD_NOS_NOT_NULL_r12 1040 +#define _GUARD_NOS_NOT_NULL_r22 1041 +#define _GUARD_NOS_NOT_NULL_r33 1042 +#define _GUARD_NOS_NULL_r02 1043 +#define _GUARD_NOS_NULL_r12 1044 +#define _GUARD_NOS_NULL_r22 1045 +#define _GUARD_NOS_NULL_r33 1046 +#define _GUARD_NOS_OVERFLOWED_r02 1047 +#define _GUARD_NOS_OVERFLOWED_r12 1048 +#define _GUARD_NOS_OVERFLOWED_r22 1049 +#define _GUARD_NOS_OVERFLOWED_r33 1050 +#define _GUARD_NOS_TUPLE_r02 1051 +#define _GUARD_NOS_TUPLE_r12 1052 +#define _GUARD_NOS_TUPLE_r22 1053 +#define _GUARD_NOS_TUPLE_r33 1054 +#define _GUARD_NOS_UNICODE_r02 1055 +#define _GUARD_NOS_UNICODE_r12 1056 +#define _GUARD_NOS_UNICODE_r22 1057 +#define _GUARD_NOS_UNICODE_r33 1058 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1059 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1060 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1061 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1062 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1063 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1064 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1065 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1066 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1067 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1068 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1069 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1070 +#define _GUARD_THIRD_NULL_r03 1071 +#define _GUARD_THIRD_NULL_r13 1072 +#define _GUARD_THIRD_NULL_r23 1073 +#define _GUARD_THIRD_NULL_r33 1074 +#define _GUARD_TOS_ANY_DICT_r01 1075 +#define _GUARD_TOS_ANY_DICT_r11 1076 +#define _GUARD_TOS_ANY_DICT_r22 1077 +#define _GUARD_TOS_ANY_DICT_r33 1078 +#define _GUARD_TOS_ANY_SET_r01 1079 +#define _GUARD_TOS_ANY_SET_r11 1080 +#define _GUARD_TOS_ANY_SET_r22 1081 +#define _GUARD_TOS_ANY_SET_r33 1082 +#define _GUARD_TOS_DICT_r01 1083 +#define _GUARD_TOS_DICT_r11 1084 +#define _GUARD_TOS_DICT_r22 1085 +#define _GUARD_TOS_DICT_r33 1086 +#define _GUARD_TOS_FLOAT_r01 1087 +#define _GUARD_TOS_FLOAT_r11 1088 +#define _GUARD_TOS_FLOAT_r22 1089 +#define _GUARD_TOS_FLOAT_r33 1090 +#define _GUARD_TOS_FROZENDICT_r01 1091 +#define _GUARD_TOS_FROZENDICT_r11 1092 +#define _GUARD_TOS_FROZENDICT_r22 1093 +#define _GUARD_TOS_FROZENDICT_r33 1094 +#define _GUARD_TOS_FROZENSET_r01 1095 +#define _GUARD_TOS_FROZENSET_r11 1096 +#define _GUARD_TOS_FROZENSET_r22 1097 +#define _GUARD_TOS_FROZENSET_r33 1098 +#define _GUARD_TOS_INT_r01 1099 +#define _GUARD_TOS_INT_r11 1100 +#define _GUARD_TOS_INT_r22 1101 +#define _GUARD_TOS_INT_r33 1102 +#define _GUARD_TOS_LIST_r01 1103 +#define _GUARD_TOS_LIST_r11 1104 +#define _GUARD_TOS_LIST_r22 1105 +#define _GUARD_TOS_LIST_r33 1106 +#define _GUARD_TOS_OVERFLOWED_r01 1107 +#define _GUARD_TOS_OVERFLOWED_r11 1108 +#define _GUARD_TOS_OVERFLOWED_r22 1109 +#define _GUARD_TOS_OVERFLOWED_r33 1110 +#define _GUARD_TOS_SET_r01 1111 +#define _GUARD_TOS_SET_r11 1112 +#define _GUARD_TOS_SET_r22 1113 +#define _GUARD_TOS_SET_r33 1114 +#define _GUARD_TOS_SLICE_r01 1115 +#define _GUARD_TOS_SLICE_r11 1116 +#define _GUARD_TOS_SLICE_r22 1117 +#define _GUARD_TOS_SLICE_r33 1118 +#define _GUARD_TOS_TUPLE_r01 1119 +#define _GUARD_TOS_TUPLE_r11 1120 +#define _GUARD_TOS_TUPLE_r22 1121 +#define _GUARD_TOS_TUPLE_r33 1122 +#define _GUARD_TOS_UNICODE_r01 1123 +#define _GUARD_TOS_UNICODE_r11 1124 +#define _GUARD_TOS_UNICODE_r22 1125 +#define _GUARD_TOS_UNICODE_r33 1126 +#define _GUARD_TYPE_VERSION_r01 1127 +#define _GUARD_TYPE_VERSION_r11 1128 +#define _GUARD_TYPE_VERSION_r22 1129 +#define _GUARD_TYPE_VERSION_r33 1130 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1131 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1132 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1133 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1134 +#define _HANDLE_PENDING_AND_DEOPT_r00 1135 +#define _HANDLE_PENDING_AND_DEOPT_r10 1136 +#define _HANDLE_PENDING_AND_DEOPT_r20 1137 +#define _HANDLE_PENDING_AND_DEOPT_r30 1138 +#define _IMPORT_FROM_r12 1139 +#define _IMPORT_NAME_r21 1140 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1141 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1142 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1143 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1144 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1145 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1146 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1147 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1148 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1149 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1150 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1151 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1152 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1153 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1154 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1155 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1156 +#define _INSERT_NULL_r10 1157 +#define _INSTRUMENTED_FOR_ITER_r23 1158 +#define _INSTRUMENTED_INSTRUCTION_r00 1159 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1160 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1161 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1162 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1163 +#define _INSTRUMENTED_LINE_r00 1164 +#define _INSTRUMENTED_NOT_TAKEN_r00 1165 +#define _INSTRUMENTED_NOT_TAKEN_r11 1166 +#define _INSTRUMENTED_NOT_TAKEN_r22 1167 +#define _INSTRUMENTED_NOT_TAKEN_r33 1168 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1169 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1170 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1171 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1172 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1173 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1174 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1175 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1176 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1177 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1178 +#define _IS_NONE_r11 1179 +#define _IS_OP_r03 1180 +#define _IS_OP_r13 1181 +#define _IS_OP_r23 1182 +#define _ITER_CHECK_LIST_r02 1183 +#define _ITER_CHECK_LIST_r12 1184 +#define _ITER_CHECK_LIST_r22 1185 +#define _ITER_CHECK_LIST_r33 1186 +#define _ITER_CHECK_RANGE_r02 1187 +#define _ITER_CHECK_RANGE_r12 1188 +#define _ITER_CHECK_RANGE_r22 1189 +#define _ITER_CHECK_RANGE_r33 1190 +#define _ITER_CHECK_TUPLE_r02 1191 +#define _ITER_CHECK_TUPLE_r12 1192 +#define _ITER_CHECK_TUPLE_r22 1193 +#define _ITER_CHECK_TUPLE_r33 1194 +#define _ITER_JUMP_LIST_r02 1195 +#define _ITER_JUMP_LIST_r12 1196 +#define _ITER_JUMP_LIST_r22 1197 +#define _ITER_JUMP_LIST_r33 1198 +#define _ITER_JUMP_RANGE_r02 1199 +#define _ITER_JUMP_RANGE_r12 1200 +#define _ITER_JUMP_RANGE_r22 1201 +#define _ITER_JUMP_RANGE_r33 1202 +#define _ITER_JUMP_TUPLE_r02 1203 +#define _ITER_JUMP_TUPLE_r12 1204 +#define _ITER_JUMP_TUPLE_r22 1205 +#define _ITER_JUMP_TUPLE_r33 1206 +#define _ITER_NEXT_LIST_r23 1207 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1208 +#define _ITER_NEXT_RANGE_r03 1209 +#define _ITER_NEXT_RANGE_r13 1210 +#define _ITER_NEXT_RANGE_r23 1211 +#define _ITER_NEXT_TUPLE_r03 1212 +#define _ITER_NEXT_TUPLE_r13 1213 +#define _ITER_NEXT_TUPLE_r23 1214 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1215 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1216 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1217 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1218 +#define _JUMP_TO_TOP_r00 1219 +#define _LIST_APPEND_r10 1220 +#define _LIST_EXTEND_r11 1221 +#define _LOAD_ATTR_r10 1222 +#define _LOAD_ATTR_CLASS_r11 1223 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1224 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1225 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1226 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1227 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1228 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1229 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1230 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1231 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1232 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1233 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1234 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1235 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1236 +#define _LOAD_ATTR_MODULE_r12 1237 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1238 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1239 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1240 +#define _LOAD_ATTR_SLOT_r02 1241 +#define _LOAD_ATTR_SLOT_r12 1242 +#define _LOAD_ATTR_SLOT_r23 1243 +#define _LOAD_ATTR_WITH_HINT_r12 1244 +#define _LOAD_BUILD_CLASS_r01 1245 +#define _LOAD_BYTECODE_r00 1246 +#define _LOAD_COMMON_CONSTANT_r01 1247 +#define _LOAD_COMMON_CONSTANT_r12 1248 +#define _LOAD_COMMON_CONSTANT_r23 1249 +#define _LOAD_CONST_r01 1250 +#define _LOAD_CONST_r12 1251 +#define _LOAD_CONST_r23 1252 +#define _LOAD_CONST_INLINE_r01 1253 +#define _LOAD_CONST_INLINE_r12 1254 +#define _LOAD_CONST_INLINE_r23 1255 +#define _LOAD_CONST_INLINE_BORROW_r01 1256 +#define _LOAD_CONST_INLINE_BORROW_r12 1257 +#define _LOAD_CONST_INLINE_BORROW_r23 1258 +#define _LOAD_CONST_UNDER_INLINE_r02 1259 +#define _LOAD_CONST_UNDER_INLINE_r12 1260 +#define _LOAD_CONST_UNDER_INLINE_r23 1261 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1262 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1263 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1264 +#define _LOAD_DEREF_r01 1265 +#define _LOAD_FAST_r01 1266 +#define _LOAD_FAST_r12 1267 +#define _LOAD_FAST_r23 1268 +#define _LOAD_FAST_0_r01 1269 +#define _LOAD_FAST_0_r12 1270 +#define _LOAD_FAST_0_r23 1271 +#define _LOAD_FAST_1_r01 1272 +#define _LOAD_FAST_1_r12 1273 +#define _LOAD_FAST_1_r23 1274 +#define _LOAD_FAST_2_r01 1275 +#define _LOAD_FAST_2_r12 1276 +#define _LOAD_FAST_2_r23 1277 +#define _LOAD_FAST_3_r01 1278 +#define _LOAD_FAST_3_r12 1279 +#define _LOAD_FAST_3_r23 1280 +#define _LOAD_FAST_4_r01 1281 +#define _LOAD_FAST_4_r12 1282 +#define _LOAD_FAST_4_r23 1283 +#define _LOAD_FAST_5_r01 1284 +#define _LOAD_FAST_5_r12 1285 +#define _LOAD_FAST_5_r23 1286 +#define _LOAD_FAST_6_r01 1287 +#define _LOAD_FAST_6_r12 1288 +#define _LOAD_FAST_6_r23 1289 +#define _LOAD_FAST_7_r01 1290 +#define _LOAD_FAST_7_r12 1291 +#define _LOAD_FAST_7_r23 1292 +#define _LOAD_FAST_AND_CLEAR_r01 1293 +#define _LOAD_FAST_AND_CLEAR_r12 1294 +#define _LOAD_FAST_AND_CLEAR_r23 1295 +#define _LOAD_FAST_BORROW_r01 1296 +#define _LOAD_FAST_BORROW_r12 1297 +#define _LOAD_FAST_BORROW_r23 1298 +#define _LOAD_FAST_BORROW_0_r01 1299 +#define _LOAD_FAST_BORROW_0_r12 1300 +#define _LOAD_FAST_BORROW_0_r23 1301 +#define _LOAD_FAST_BORROW_1_r01 1302 +#define _LOAD_FAST_BORROW_1_r12 1303 +#define _LOAD_FAST_BORROW_1_r23 1304 +#define _LOAD_FAST_BORROW_2_r01 1305 +#define _LOAD_FAST_BORROW_2_r12 1306 +#define _LOAD_FAST_BORROW_2_r23 1307 +#define _LOAD_FAST_BORROW_3_r01 1308 +#define _LOAD_FAST_BORROW_3_r12 1309 +#define _LOAD_FAST_BORROW_3_r23 1310 +#define _LOAD_FAST_BORROW_4_r01 1311 +#define _LOAD_FAST_BORROW_4_r12 1312 +#define _LOAD_FAST_BORROW_4_r23 1313 +#define _LOAD_FAST_BORROW_5_r01 1314 +#define _LOAD_FAST_BORROW_5_r12 1315 +#define _LOAD_FAST_BORROW_5_r23 1316 +#define _LOAD_FAST_BORROW_6_r01 1317 +#define _LOAD_FAST_BORROW_6_r12 1318 +#define _LOAD_FAST_BORROW_6_r23 1319 +#define _LOAD_FAST_BORROW_7_r01 1320 +#define _LOAD_FAST_BORROW_7_r12 1321 +#define _LOAD_FAST_BORROW_7_r23 1322 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1323 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1324 +#define _LOAD_FAST_CHECK_r01 1325 +#define _LOAD_FAST_CHECK_r12 1326 +#define _LOAD_FAST_CHECK_r23 1327 +#define _LOAD_FAST_LOAD_FAST_r02 1328 +#define _LOAD_FAST_LOAD_FAST_r13 1329 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1330 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1331 +#define _LOAD_GLOBAL_r00 1332 +#define _LOAD_GLOBAL_BUILTINS_r01 1333 +#define _LOAD_GLOBAL_MODULE_r01 1334 +#define _LOAD_LOCALS_r01 1335 +#define _LOAD_LOCALS_r12 1336 +#define _LOAD_LOCALS_r23 1337 +#define _LOAD_NAME_r01 1338 +#define _LOAD_SMALL_INT_r01 1339 +#define _LOAD_SMALL_INT_r12 1340 +#define _LOAD_SMALL_INT_r23 1341 +#define _LOAD_SMALL_INT_0_r01 1342 +#define _LOAD_SMALL_INT_0_r12 1343 +#define _LOAD_SMALL_INT_0_r23 1344 +#define _LOAD_SMALL_INT_1_r01 1345 +#define _LOAD_SMALL_INT_1_r12 1346 +#define _LOAD_SMALL_INT_1_r23 1347 +#define _LOAD_SMALL_INT_2_r01 1348 +#define _LOAD_SMALL_INT_2_r12 1349 +#define _LOAD_SMALL_INT_2_r23 1350 +#define _LOAD_SMALL_INT_3_r01 1351 +#define _LOAD_SMALL_INT_3_r12 1352 +#define _LOAD_SMALL_INT_3_r23 1353 +#define _LOAD_SPECIAL_r00 1354 +#define _LOAD_SUPER_ATTR_ATTR_r31 1355 +#define _LOAD_SUPER_ATTR_METHOD_r32 1356 +#define _LOCK_OBJECT_r01 1357 +#define _LOCK_OBJECT_r11 1358 +#define _LOCK_OBJECT_r22 1359 +#define _LOCK_OBJECT_r33 1360 +#define _MAKE_CALLARGS_A_TUPLE_r33 1361 +#define _MAKE_CELL_r00 1362 +#define _MAKE_FUNCTION_r11 1363 +#define _MAKE_HEAP_SAFE_r01 1364 +#define _MAKE_HEAP_SAFE_r11 1365 +#define _MAKE_HEAP_SAFE_r22 1366 +#define _MAKE_HEAP_SAFE_r33 1367 +#define _MAKE_WARM_r00 1368 +#define _MAKE_WARM_r11 1369 +#define _MAKE_WARM_r22 1370 +#define _MAKE_WARM_r33 1371 +#define _MAP_ADD_r20 1372 +#define _MATCH_CLASS_r33 1373 +#define _MATCH_KEYS_r23 1374 +#define _MATCH_MAPPING_r02 1375 +#define _MATCH_MAPPING_r12 1376 +#define _MATCH_MAPPING_r23 1377 +#define _MATCH_SEQUENCE_r02 1378 +#define _MATCH_SEQUENCE_r12 1379 +#define _MATCH_SEQUENCE_r23 1380 +#define _MAYBE_EXPAND_METHOD_r00 1381 +#define _MAYBE_EXPAND_METHOD_KW_r11 1382 +#define _MONITOR_CALL_r00 1383 +#define _MONITOR_CALL_KW_r11 1384 +#define _MONITOR_JUMP_BACKWARD_r00 1385 +#define _MONITOR_JUMP_BACKWARD_r11 1386 +#define _MONITOR_JUMP_BACKWARD_r22 1387 +#define _MONITOR_JUMP_BACKWARD_r33 1388 +#define _MONITOR_RESUME_r00 1389 +#define _NOP_r00 1390 +#define _NOP_r11 1391 +#define _NOP_r22 1392 +#define _NOP_r33 1393 +#define _POP_CALL_r20 1394 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1395 +#define _POP_CALL_ONE_r30 1396 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1397 +#define _POP_CALL_TWO_r30 1398 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1399 +#define _POP_EXCEPT_r10 1400 +#define _POP_ITER_r20 1401 +#define _POP_JUMP_IF_FALSE_r00 1402 +#define _POP_JUMP_IF_FALSE_r10 1403 +#define _POP_JUMP_IF_FALSE_r21 1404 +#define _POP_JUMP_IF_FALSE_r32 1405 +#define _POP_JUMP_IF_TRUE_r00 1406 +#define _POP_JUMP_IF_TRUE_r10 1407 +#define _POP_JUMP_IF_TRUE_r21 1408 +#define _POP_JUMP_IF_TRUE_r32 1409 +#define _POP_TOP_r10 1410 +#define _POP_TOP_FLOAT_r00 1411 +#define _POP_TOP_FLOAT_r10 1412 +#define _POP_TOP_FLOAT_r21 1413 +#define _POP_TOP_FLOAT_r32 1414 +#define _POP_TOP_INT_r00 1415 +#define _POP_TOP_INT_r10 1416 +#define _POP_TOP_INT_r21 1417 +#define _POP_TOP_INT_r32 1418 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1419 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1420 +#define _POP_TOP_NOP_r00 1421 +#define _POP_TOP_NOP_r10 1422 +#define _POP_TOP_NOP_r21 1423 +#define _POP_TOP_NOP_r32 1424 +#define _POP_TOP_UNICODE_r00 1425 +#define _POP_TOP_UNICODE_r10 1426 +#define _POP_TOP_UNICODE_r21 1427 +#define _POP_TOP_UNICODE_r32 1428 +#define _POP_TWO_r20 1429 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1430 +#define _PUSH_EXC_INFO_r02 1431 +#define _PUSH_EXC_INFO_r12 1432 +#define _PUSH_EXC_INFO_r23 1433 +#define _PUSH_FRAME_r10 1434 +#define _PUSH_NULL_r01 1435 +#define _PUSH_NULL_r12 1436 +#define _PUSH_NULL_r23 1437 +#define _PUSH_NULL_CONDITIONAL_r00 1438 +#define _PY_FRAME_EX_r31 1439 +#define _PY_FRAME_GENERAL_r01 1440 +#define _PY_FRAME_KW_r11 1441 +#define _REPLACE_WITH_TRUE_r02 1442 +#define _REPLACE_WITH_TRUE_r12 1443 +#define _REPLACE_WITH_TRUE_r23 1444 +#define _RESUME_CHECK_r00 1445 +#define _RESUME_CHECK_r11 1446 +#define _RESUME_CHECK_r22 1447 +#define _RESUME_CHECK_r33 1448 +#define _RETURN_GENERATOR_r01 1449 +#define _RETURN_VALUE_r11 1450 +#define _SAVE_RETURN_OFFSET_r00 1451 +#define _SAVE_RETURN_OFFSET_r11 1452 +#define _SAVE_RETURN_OFFSET_r22 1453 +#define _SAVE_RETURN_OFFSET_r33 1454 +#define _SEND_r33 1455 +#define _SEND_GEN_FRAME_r33 1456 +#define _SETUP_ANNOTATIONS_r00 1457 +#define _SET_ADD_r10 1458 +#define _SET_FUNCTION_ATTRIBUTE_r01 1459 +#define _SET_FUNCTION_ATTRIBUTE_r11 1460 +#define _SET_FUNCTION_ATTRIBUTE_r21 1461 +#define _SET_FUNCTION_ATTRIBUTE_r32 1462 +#define _SET_IP_r00 1463 +#define _SET_IP_r11 1464 +#define _SET_IP_r22 1465 +#define _SET_IP_r33 1466 +#define _SET_UPDATE_r11 1467 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1468 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1469 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1470 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1471 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1472 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1473 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1474 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1475 +#define _SPILL_OR_RELOAD_r01 1476 +#define _SPILL_OR_RELOAD_r02 1477 +#define _SPILL_OR_RELOAD_r03 1478 +#define _SPILL_OR_RELOAD_r10 1479 +#define _SPILL_OR_RELOAD_r12 1480 +#define _SPILL_OR_RELOAD_r13 1481 +#define _SPILL_OR_RELOAD_r20 1482 +#define _SPILL_OR_RELOAD_r21 1483 +#define _SPILL_OR_RELOAD_r23 1484 +#define _SPILL_OR_RELOAD_r30 1485 +#define _SPILL_OR_RELOAD_r31 1486 +#define _SPILL_OR_RELOAD_r32 1487 +#define _START_EXECUTOR_r00 1488 +#define _STORE_ATTR_r20 1489 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1490 +#define _STORE_ATTR_SLOT_r21 1491 +#define _STORE_ATTR_WITH_HINT_r21 1492 +#define _STORE_DEREF_r10 1493 +#define _STORE_FAST_LOAD_FAST_r11 1494 +#define _STORE_FAST_STORE_FAST_r20 1495 +#define _STORE_GLOBAL_r10 1496 +#define _STORE_NAME_r10 1497 +#define _STORE_SLICE_r30 1498 +#define _STORE_SUBSCR_r30 1499 +#define _STORE_SUBSCR_DICT_r31 1500 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1501 +#define _STORE_SUBSCR_LIST_INT_r32 1502 +#define _SWAP_r11 1503 +#define _SWAP_2_r02 1504 +#define _SWAP_2_r12 1505 +#define _SWAP_2_r22 1506 +#define _SWAP_2_r33 1507 +#define _SWAP_3_r03 1508 +#define _SWAP_3_r13 1509 +#define _SWAP_3_r23 1510 +#define _SWAP_3_r33 1511 +#define _SWAP_FAST_r01 1512 +#define _SWAP_FAST_r11 1513 +#define _SWAP_FAST_r22 1514 +#define _SWAP_FAST_r33 1515 +#define _SWAP_FAST_0_r01 1516 +#define _SWAP_FAST_0_r11 1517 +#define _SWAP_FAST_0_r22 1518 +#define _SWAP_FAST_0_r33 1519 +#define _SWAP_FAST_1_r01 1520 +#define _SWAP_FAST_1_r11 1521 +#define _SWAP_FAST_1_r22 1522 +#define _SWAP_FAST_1_r33 1523 +#define _SWAP_FAST_2_r01 1524 +#define _SWAP_FAST_2_r11 1525 +#define _SWAP_FAST_2_r22 1526 +#define _SWAP_FAST_2_r33 1527 +#define _SWAP_FAST_3_r01 1528 +#define _SWAP_FAST_3_r11 1529 +#define _SWAP_FAST_3_r22 1530 +#define _SWAP_FAST_3_r33 1531 +#define _SWAP_FAST_4_r01 1532 +#define _SWAP_FAST_4_r11 1533 +#define _SWAP_FAST_4_r22 1534 +#define _SWAP_FAST_4_r33 1535 +#define _SWAP_FAST_5_r01 1536 +#define _SWAP_FAST_5_r11 1537 +#define _SWAP_FAST_5_r22 1538 +#define _SWAP_FAST_5_r33 1539 +#define _SWAP_FAST_6_r01 1540 +#define _SWAP_FAST_6_r11 1541 +#define _SWAP_FAST_6_r22 1542 +#define _SWAP_FAST_6_r33 1543 +#define _SWAP_FAST_7_r01 1544 +#define _SWAP_FAST_7_r11 1545 +#define _SWAP_FAST_7_r22 1546 +#define _SWAP_FAST_7_r33 1547 +#define _TIER2_RESUME_CHECK_r00 1548 +#define _TIER2_RESUME_CHECK_r11 1549 +#define _TIER2_RESUME_CHECK_r22 1550 +#define _TIER2_RESUME_CHECK_r33 1551 +#define _TO_BOOL_r11 1552 +#define _TO_BOOL_BOOL_r01 1553 +#define _TO_BOOL_BOOL_r11 1554 +#define _TO_BOOL_BOOL_r22 1555 +#define _TO_BOOL_BOOL_r33 1556 +#define _TO_BOOL_INT_r02 1557 +#define _TO_BOOL_INT_r12 1558 +#define _TO_BOOL_INT_r23 1559 +#define _TO_BOOL_LIST_r02 1560 +#define _TO_BOOL_LIST_r12 1561 +#define _TO_BOOL_LIST_r23 1562 +#define _TO_BOOL_NONE_r01 1563 +#define _TO_BOOL_NONE_r11 1564 +#define _TO_BOOL_NONE_r22 1565 +#define _TO_BOOL_NONE_r33 1566 +#define _TO_BOOL_STR_r02 1567 +#define _TO_BOOL_STR_r12 1568 +#define _TO_BOOL_STR_r23 1569 +#define _TRACE_RECORD_r00 1570 +#define _UNARY_INVERT_r12 1571 +#define _UNARY_NEGATIVE_r12 1572 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1573 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1574 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1575 +#define _UNARY_NOT_r01 1576 +#define _UNARY_NOT_r11 1577 +#define _UNARY_NOT_r22 1578 +#define _UNARY_NOT_r33 1579 +#define _UNPACK_EX_r10 1580 +#define _UNPACK_SEQUENCE_r10 1581 +#define _UNPACK_SEQUENCE_LIST_r10 1582 +#define _UNPACK_SEQUENCE_TUPLE_r10 1583 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1584 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1585 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1586 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1587 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1588 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1589 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1590 +#define _WITH_EXCEPT_START_r33 1591 +#define _YIELD_VALUE_r11 1592 +#define MAX_UOP_REGS_ID 1592 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 52bec0bd0b8..19d19e5aee8 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -319,12 +319,16 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CALL_LIST_APPEND] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_O_INLINE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_MAYBE_EXPAND_METHOD_KW] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_PY_FRAME_KW] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG, [_CHECK_FUNCTION_VERSION_KW] = HAS_ARG_FLAG | HAS_EXIT_FLAG, @@ -2989,6 +2993,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_CALL_METHOD_DESCRIPTOR_O_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 3, 0, _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -3007,6 +3020,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -3025,6 +3047,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 1, 0, _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -3043,6 +3074,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = { + .best = { 0, 0, 0, 0 }, + .entries = { + { 1, 0, _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_MAYBE_EXPAND_METHOD_KW] = { .best = { 1, 1, 1, 1 }, .entries = { @@ -4436,12 +4476,16 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CALL_LIST_APPEND_r33] = _CALL_LIST_APPEND, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_O, [_CALL_METHOD_DESCRIPTOR_O_r03] = _CALL_METHOD_DESCRIPTOR_O, + [_CALL_METHOD_DESCRIPTOR_O_INLINE_r03] = _CALL_METHOD_DESCRIPTOR_O_INLINE, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, [_CALL_METHOD_DESCRIPTOR_NOARGS_r01] = _CALL_METHOD_DESCRIPTOR_NOARGS, + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01] = _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, [_CALL_METHOD_DESCRIPTOR_FAST_r01] = _CALL_METHOD_DESCRIPTOR_FAST, + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01] = _CALL_METHOD_DESCRIPTOR_FAST_INLINE, [_MAYBE_EXPAND_METHOD_KW_r11] = _MAYBE_EXPAND_METHOD_KW, [_PY_FRAME_KW_r11] = _PY_FRAME_KW, [_CHECK_FUNCTION_VERSION_KW_r11] = _CHECK_FUNCTION_VERSION_KW, @@ -4843,12 +4887,20 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CALL_LIST_APPEND_r33] = "_CALL_LIST_APPEND_r33", [_CALL_METHOD_DESCRIPTOR_FAST] = "_CALL_METHOD_DESCRIPTOR_FAST", [_CALL_METHOD_DESCRIPTOR_FAST_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_r01", + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = "_CALL_METHOD_DESCRIPTOR_FAST_INLINE", + [_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01", [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE", + [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01", [_CALL_METHOD_DESCRIPTOR_NOARGS] = "_CALL_METHOD_DESCRIPTOR_NOARGS", [_CALL_METHOD_DESCRIPTOR_NOARGS_r01] = "_CALL_METHOD_DESCRIPTOR_NOARGS_r01", + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = "_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01] = "_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01", [_CALL_METHOD_DESCRIPTOR_O] = "_CALL_METHOD_DESCRIPTOR_O", [_CALL_METHOD_DESCRIPTOR_O_r03] = "_CALL_METHOD_DESCRIPTOR_O_r03", + [_CALL_METHOD_DESCRIPTOR_O_INLINE] = "_CALL_METHOD_DESCRIPTOR_O_INLINE", + [_CALL_METHOD_DESCRIPTOR_O_INLINE_r03] = "_CALL_METHOD_DESCRIPTOR_O_INLINE_r03", [_CALL_NON_PY_GENERAL] = "_CALL_NON_PY_GENERAL", [_CALL_NON_PY_GENERAL_r01] = "_CALL_NON_PY_GENERAL_r01", [_CALL_STR_1] = "_CALL_STR_1", @@ -6530,18 +6582,26 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _CALL_METHOD_DESCRIPTOR_O: return 2 + oparg; + case _CALL_METHOD_DESCRIPTOR_O_INLINE: + return 1 + oparg; case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: return 0; case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: return 2 + oparg; + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE: + return 1 + oparg; case _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS: return 0; case _CALL_METHOD_DESCRIPTOR_NOARGS: return 2 + oparg; + case _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE: + return 1 + oparg; case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST: return 0; case _CALL_METHOD_DESCRIPTOR_FAST: return 2 + oparg; + case _CALL_METHOD_DESCRIPTOR_FAST_INLINE: + return 1 + oparg; case _MAYBE_EXPAND_METHOD_KW: return 0; case _PY_FRAME_KW: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 8d3da8b5a22..1d92c476f93 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2757,7 +2757,8 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_CALL_METHOD_DESCRIPTOR_O", uops) + self.assertIn("_CALL_METHOD_DESCRIPTOR_O_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_O", uops) self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_O", uops) self.assertIn("_POP_TOP_NOP", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 4) @@ -2775,7 +2776,8 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD * 5) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_CALL_METHOD_DESCRIPTOR_NOARGS", uops) + self.assertIn("_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_NOARGS", uops) self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS", uops) def test_call_method_descriptor_fast(self): @@ -2791,7 +2793,8 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_CALL_METHOD_DESCRIPTOR_FAST", uops) + self.assertIn("_CALL_METHOD_DESCRIPTOR_FAST_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_FAST", uops) self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST", uops) def test_call_method_descriptor_fast_with_keywords(self): @@ -2806,7 +2809,8 @@ def testfunc(n): self.assertEqual(res, TIER2_THRESHOLD * 5) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops) + self.assertIn("_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE", uops) + self.assertNotIn("_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops) self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops) def test_call_intrinsic_1(self): diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index a3c840980ed..7e3668622d9 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -3827,9 +3827,10 @@ assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -3923,9 +3924,10 @@ assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -4122,14 +4124,12 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 92f5b5d530c..4b58efaf921 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4813,13 +4813,11 @@ dummy_func( } // CPython promises to check all non-vectorcall function calls. EXIT_IF(_Py_ReachedRecursionLimit(tstate)); - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); if (res_o == NULL) { @@ -4832,6 +4830,26 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } + tier2 op(_CALL_METHOD_DESCRIPTOR_O_INLINE, (callable, args[oparg], cfunc/4 -- res, c, s, a)) { + assert(oparg == 2); + EXIT_IF(_Py_ReachedRecursionLimit(tstate)); + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(args[1]); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, arg); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + if (res_o == NULL) { + ERROR_NO_POP(); + } + c = callable; + s = args[0]; + a = args[1]; + INPUTS_DEAD(); + res = PyStackRef_FromPyObjectSteal(res_o); + } + macro(CALL_METHOD_DESCRIPTOR_O) = _RECORD_CALLABLE + unused/1 + @@ -4872,9 +4890,10 @@ dummy_func( PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); assert(self != NULL); STAT_INC(CALL, hit); + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -4886,6 +4905,24 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } + tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, (callable, args[oparg], cfunc/4 -- res)) { + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + assert(self != NULL); + STAT_INC(CALL, hit); + volatile PyCFunctionFastWithKeywords cfunc_v = _PyCFunctionFastWithKeywords_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + callable, + cfunc_v, + self, + args, + oparg + ); + DEAD(args); + DEAD(callable); + ERROR_IF(res_o == NULL); + res = PyStackRef_FromPyObjectSteal(res_o); + } + macro(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) = _RECORD_CALLABLE + unused/1 + @@ -4934,6 +4971,23 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } + tier2 op(_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, (callable, args[oparg], cfunc/4 -- res)) { + assert(oparg == 1); + _PyStackRef self_stackref = args[0]; + PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + EXIT_IF(_Py_ReachedRecursionLimit(tstate)); + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, NULL); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + PyStackRef_CLOSE(self_stackref); + DEAD(args); + PyStackRef_CLOSE(callable); + ERROR_IF(res_o == NULL); + res = PyStackRef_FromPyObjectSteal(res_o); + } + macro(CALL_METHOD_DESCRIPTOR_NOARGS) = _RECORD_CALLABLE + unused/1 + @@ -4971,9 +5025,10 @@ dummy_func( PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); assert(self != NULL); STAT_INC(CALL, hit); + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -4985,6 +5040,24 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } + tier2 op(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, (callable, args[oparg], cfunc/4 -- res)) { + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + assert(self != NULL); + STAT_INC(CALL, hit); + volatile PyCFunctionFast cfunc_v = _PyCFunctionFast_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + callable, + cfunc_v, + self, + args, + oparg + ); + DEAD(args); + DEAD(callable); + ERROR_IF(res_o == NULL); + res = PyStackRef_FromPyObjectSteal(res_o); + } + macro(CALL_METHOD_DESCRIPTOR_FAST) = unused/1 + unused/2 + diff --git a/Python/ceval.c b/Python/ceval.c index bf550f2da36..4390e024dca 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -874,7 +874,7 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal( PyObject * _PyCallMethodDescriptorFast_StackRefSteal( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFast cfunc, PyObject *self, _PyStackRef *arguments, int total_args) @@ -885,10 +885,8 @@ _PyCallMethodDescriptorFast_StackRefSteal( res = NULL; goto cleanup; } - assert(((PyMethodDescrObject *)PyStackRef_AsPyObjectBorrow(callable))->d_method == meth); assert(self == PyStackRef_AsPyObjectBorrow(arguments[0])); - PyCFunctionFast cfunc = _PyCFunctionFast_CAST(meth->ml_meth); res = cfunc(self, (args_o + 1), total_args - 1); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); @@ -907,7 +905,7 @@ _PyCallMethodDescriptorFast_StackRefSteal( PyObject * _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( _PyStackRef callable, - PyMethodDef *meth, + PyCFunctionFastWithKeywords cfunc, PyObject *self, _PyStackRef *arguments, int total_args) @@ -918,11 +916,8 @@ _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( res = NULL; goto cleanup; } - assert(((PyMethodDescrObject *)PyStackRef_AsPyObjectBorrow(callable))->d_method == meth); assert(self == PyStackRef_AsPyObjectBorrow(arguments[0])); - PyCFunctionFastWithKeywords cfunc = - _PyCFunctionFastWithKeywords_CAST(meth->ml_meth); res = cfunc(self, (args_o + 1), total_args-1, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res != NULL) ^ (PyErr_Occurred() != NULL)); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 36353b77f1b..0b68274a378 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -17091,14 +17091,12 @@ SET_CURRENT_CACHED_VALUES(0); JUMP_TO_JUMP_TARGET(); } - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -17121,6 +17119,53 @@ break; } + case _CALL_METHOD_DESCRIPTOR_O_INLINE_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef callable; + _PyStackRef res; + _PyStackRef c; + _PyStackRef s; + _PyStackRef a; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + callable = stack_pointer[-1 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + assert(oparg == 2); + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(args[1]); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + c = callable; + s = args[0]; + a = args[1]; + res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache2 = a; + _tos_cache1 = s; + _tos_cache0 = c; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer[-1 - oparg] = res; + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -17188,9 +17233,10 @@ assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -17213,6 +17259,46 @@ break; } + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef callable; + _PyStackRef res; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + callable = stack_pointer[-1 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + assert(self != NULL); + STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); + volatile PyCFunctionFastWithKeywords cfunc_v = _PyCFunctionFastWithKeywords_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( + callable, + cfunc_v, + self, + args, + oparg + ); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache0 = res; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -17308,6 +17394,52 @@ break; } + case _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef callable; + _PyStackRef res; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + callable = stack_pointer[-1 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + assert(oparg == 1); + _PyStackRef self_stackref = args[0]; + PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(CALL, hit); + volatile PyCFunction cfunc_v = (PyCFunction)cfunc; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); + _Py_LeaveRecursiveCallTstate(tstate); + assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(self_stackref); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(callable); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache0 = res; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -17374,9 +17506,10 @@ assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -17399,6 +17532,46 @@ break; } + case _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef *args; + _PyStackRef callable; + _PyStackRef res; + oparg = CURRENT_OPARG(); + args = &stack_pointer[-oparg]; + callable = stack_pointer[-1 - oparg]; + PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); + PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); + assert(self != NULL); + STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); + volatile PyCFunctionFast cfunc_v = _PyCFunctionFast_CAST(cfunc); + PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( + callable, + cfunc_v, + self, + args, + oparg + ); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) { + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + res = PyStackRef_FromPyObjectSteal(res_o); + _tos_cache0 = res; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + /* _MONITOR_CALL_KW is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ case _MAYBE_EXPAND_METHOD_KW_r11: { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 4bec8db1419..7573bf5510b 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3827,9 +3827,10 @@ assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFast cfunc = _PyCFunctionFast_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFast_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -3923,9 +3924,10 @@ assert(self != NULL); STAT_INC(CALL, hit); _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(method->d_method->ml_meth); PyObject *res_o = _PyCallMethodDescriptorFastWithKeywords_StackRefSteal( callable, - method->d_method, + cfunc, self, arguments, total_args @@ -4122,14 +4124,12 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - _PyStackRef arg_stackref = arguments[1]; - _PyStackRef self_stackref = arguments[0]; STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; + PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); + PyObject *arg = PyStackRef_AsPyObjectBorrow(arguments[1]); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, - PyStackRef_AsPyObjectBorrow(self_stackref), - PyStackRef_AsPyObjectBorrow(arg_stackref)); + PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, arg); stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 2fd235a2dda..52a320fc70f 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1394,6 +1394,39 @@ dummy_func(void) { } } + op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res)) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, oparg + 1, (uintptr_t)cfunc); + } + res = sym_new_not_null(ctx); + } + + op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg + 1, (uintptr_t)cfunc); + } + res = sym_new_not_null(ctx); + } + + op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- res)) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg + 1, (uintptr_t)cfunc); + } + res = sym_new_not_null(ctx); + } + op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { @@ -1420,6 +1453,13 @@ dummy_func(void) { } op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res, c, s, a)) { + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_O_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); c = callable; if (sym_is_not_null(self_or_null)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 8634189c707..52ca6b2531e 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -4107,6 +4107,13 @@ args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_O_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); c = callable; if (sym_is_not_null(self_or_null)) { @@ -4128,6 +4135,25 @@ break; } + case _CALL_METHOD_DESCRIPTOR_O_INLINE: { + JitOptRef res; + JitOptRef c; + JitOptRef s; + JitOptRef a; + res = sym_new_not_null(ctx); + c = sym_new_not_null(ctx); + s = sym_new_not_null(ctx); + a = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(3 - oparg); + stack_pointer[-1 - oparg] = res; + stack_pointer[-oparg] = c; + stack_pointer[1 - oparg] = s; + stack_pointer[2 - oparg] = a; + stack_pointer += 3 - oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { JitOptRef *args; JitOptRef self_or_null; @@ -4161,7 +4187,18 @@ } case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { + JitOptRef self_or_null; + JitOptRef callable; JitOptRef res; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; @@ -4170,6 +4207,16 @@ break; } + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE: { + JitOptRef res; + res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-oparg); + stack_pointer[-1 - oparg] = res; + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS: { JitOptRef *args; JitOptRef self_or_null; @@ -4203,7 +4250,18 @@ } case _CALL_METHOD_DESCRIPTOR_NOARGS: { + JitOptRef self_or_null; + JitOptRef callable; JitOptRef res; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; @@ -4212,6 +4270,16 @@ break; } + case _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE: { + JitOptRef res; + res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-oparg); + stack_pointer[-1 - oparg] = res; + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST: { JitOptRef *args; JitOptRef self_or_null; @@ -4245,7 +4313,18 @@ } case _CALL_METHOD_DESCRIPTOR_FAST: { + JitOptRef self_or_null; + JitOptRef callable; JitOptRef res; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + PyObject *callable_o = sym_get_const(ctx, callable); + if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) + && sym_is_not_null(self_or_null)) { + PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; + PyCFunction cfunc = method->d_method->ml_meth; + ADD_OP(_CALL_METHOD_DESCRIPTOR_FAST_INLINE, oparg + 1, (uintptr_t)cfunc); + } res = sym_new_not_null(ctx); CHECK_STACK_BOUNDS(-1 - oparg); stack_pointer[-2 - oparg] = res; @@ -4254,6 +4333,16 @@ break; } + case _CALL_METHOD_DESCRIPTOR_FAST_INLINE: { + JitOptRef res; + res = sym_new_not_null(ctx); + CHECK_STACK_BOUNDS(-oparg); + stack_pointer[-1 - oparg] = res; + stack_pointer += -oparg; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + /* _MONITOR_CALL_KW is not a viable micro-op for tier 2 */ case _MAYBE_EXPAND_METHOD_KW: { From 7bcc1c49205e14c81cdbfa452fcdc01c287c82d5 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 4 Apr 2026 12:49:23 +0530 Subject: [PATCH 396/775] gh-131798: relax GUARD_CALLABLE checks for self type checks (#148069) --- Python/optimizer_bytecodes.c | 60 +++++++++++++++++++----------------- Python/optimizer_cases.c.h | 60 +++++++++++++++++++----------------- 2 files changed, 64 insertions(+), 56 deletions(-) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 52a320fc70f..86efb74c6d9 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1323,19 +1323,20 @@ dummy_func(void) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args == 2 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_O && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } @@ -1348,19 +1349,20 @@ dummy_func(void) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args != 0 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == (METH_FASTCALL|METH_KEYWORDS) && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } @@ -1373,19 +1375,20 @@ dummy_func(void) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args == 1 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_NOARGS && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } @@ -1431,19 +1434,20 @@ dummy_func(void) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args != 0 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_FASTCALL && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 52ca6b2531e..a8be9bbd994 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -4074,19 +4074,20 @@ PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args == 2 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_O && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } @@ -4164,19 +4165,20 @@ PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args != 0 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == (METH_FASTCALL|METH_KEYWORDS) && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } @@ -4227,19 +4229,20 @@ PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args == 1 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_NOARGS && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } @@ -4290,19 +4293,20 @@ PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } - PyObject *self = NULL; - if (!sym_is_null(self_or_null)) { - self = sym_get_const(ctx, self_or_null); - } else { - self = sym_get_const(ctx, args[0]); + PyTypeObject *self_type = NULL; + if (sym_is_not_null(self_or_null)) { + self_type = sym_get_type(self_or_null); + } + else { + self_type = sym_get_type(args[0]); } PyTypeObject *d_type = ((PyMethodDescrObject *)callable_o)->d_common.d_type; if (total_args != 0 && ((PyMethodDescrObject *)callable_o)->d_method->ml_flags == METH_FASTCALL && - self && Py_IS_TYPE(self, d_type)) { + self_type == d_type) { ADD_OP(_NOP, 0, 0); } } From 985216ced3022cd461ba383df07884f8dcff89fa Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 4 Apr 2026 11:07:19 +0300 Subject: [PATCH 397/775] gh-148029: Fix error message for invalid number of Base32 characters (GH-148030) Do not count ignored non-alphabet characters. --- Lib/test/test_binascii.py | 40 ++++++++++++++++++++++++++++++--------- Modules/binascii.c | 4 ++-- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 959a61b530b..a3f7c7b832c 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -159,14 +159,14 @@ def addnoise(line): def test_base64_bad_padding(self): # Test malformed padding def _assertRegexTemplate(assert_regex, data, - non_strict_mode_expected_result): + non_strict_mode_expected_result, **kwargs): data = self.type2test(data) with self.assertRaisesRegex(binascii.Error, assert_regex): - binascii.a2b_base64(data, strict_mode=True) + binascii.a2b_base64(data, strict_mode=True, **kwargs) self.assertEqual(binascii.a2b_base64(data, strict_mode=False), non_strict_mode_expected_result) self.assertEqual(binascii.a2b_base64(data, strict_mode=True, - ignorechars=b'='), + ignorechars=b' ='), non_strict_mode_expected_result) self.assertEqual(binascii.a2b_base64(data), non_strict_mode_expected_result) @@ -180,8 +180,11 @@ def assertDiscontinuousPadding(*args): def assertExcessPadding(*args): _assertRegexTemplate(r'(?i)Excess padding', *args) - def assertInvalidLength(*args): - _assertRegexTemplate(r'(?i)Invalid.+number of data characters', *args) + def assertInvalidLength(data, *args, length=None, **kwargs): + if length is None: + length = len(data.split(b'=', 1)[0].replace(b' ', b'')) + assert_regex = fr"(?i)Invalid.+number of data characters \({length}\)" + _assertRegexTemplate(assert_regex, data, *args, **kwargs) assertExcessPadding(b'ab===', b'i') assertExcessPadding(b'ab====', b'i') @@ -206,6 +209,9 @@ def assertInvalidLength(*args): assertInvalidLength(b'a=bc==', b'i\xb7') assertInvalidLength(b'a=bcd', b'i\xb7\x1d') assertInvalidLength(b'a=bcd=', b'i\xb7\x1d') + assertInvalidLength(b' a=b==', b'i', ignorechars=b' ') + assertInvalidLength(b'abcde=f==', b'i\xb7\x1dy') + assertInvalidLength(b' abcde=f==', b'i\xb7\x1dy', ignorechars=b' ') assertDiscontinuousPadding(b'ab=c=', b'i\xb7') assertDiscontinuousPadding(b'ab=cd', b'i\xb7\x1d') @@ -763,9 +769,9 @@ def _fixPadding(data): p = 8 - len_8 if len_8 else 0 return fixed + b"=" * p - def _assertRegexTemplate(assert_regex, data, good_padding_result=None): + def _assertRegexTemplate(assert_regex, data, good_padding_result=None, **kwargs): with self.assertRaisesRegex(binascii.Error, assert_regex): - binascii.a2b_base32(self.type2test(data)) + binascii.a2b_base32(self.type2test(data), **kwargs) if good_padding_result: fixed = self.type2test(_fixPadding(data)) self.assertEqual(binascii.a2b_base32(fixed), good_padding_result) @@ -788,8 +794,11 @@ def assertIncorrectPadding(*args): def assertDiscontinuousPadding(*args): _assertRegexTemplate(r"(?i)Discontinuous padding", *args) - def assertInvalidLength(*args): - _assertRegexTemplate(r"(?i)Invalid.+number of data characters", *args) + def assertInvalidLength(data, *args, length=None, **kwargs): + if length is None: + length = len(data.split(b'=', 1)[0].replace(b' ', b'')) + assert_regex = fr"(?i)Invalid.+number of data characters \({length}\)" + _assertRegexTemplate(assert_regex, data, *args, **kwargs) assertNonBase32Data(b"a") assertNonBase32Data(b"AA-") @@ -869,6 +878,9 @@ def assertInvalidLength(*args): assertInvalidLength(b"A") assertInvalidLength(b"ABC") assertInvalidLength(b"ABCDEF") + assertInvalidLength(b"ABCDEFGHI") + assertInvalidLength(b"ABCDEFGHIJK") + assertInvalidLength(b"ABCDEFGHIJKLMN") assertInvalidLength(b"A=") assertInvalidLength(b"A==") @@ -889,6 +901,16 @@ def assertInvalidLength(*args): assertInvalidLength(b"BEEFCA=K", b"\t\x08Q\x01") assertInvalidLength(b"BEEFCA=====K", b"\t\x08Q\x01") + assertInvalidLength(b" A", ignorechars=b' ') + assertInvalidLength(b" ABC", ignorechars=b' ') + assertInvalidLength(b" ABCDEF", ignorechars=b' ') + assertInvalidLength(b" ABCDEFGHI", ignorechars=b' ') + assertInvalidLength(b" ABCDEFGHIJK", ignorechars=b' ') + assertInvalidLength(b" ABCDEFGHIJKLMN", ignorechars=b' ') + assertInvalidLength(b" A=======", ignorechars=b' ') + assertInvalidLength(b" ABC=====", ignorechars=b' ') + assertInvalidLength(b" ABCDEF==", ignorechars=b' ') + def test_base32_wrapcol(self): self._common_test_wrapcol(binascii.b2a_base32) b = self.type2test(b'www.python.org') diff --git a/Modules/binascii.c b/Modules/binascii.c index 098c85036c9..f28c0d472bb 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -1680,12 +1680,12 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, if (octa_pos == 1 || octa_pos == 3 || octa_pos == 6) { state = get_binascii_state(module); if (state) { - const unsigned char *ascii_data_start = data->buf; + unsigned char *bin_data_start = PyBytesWriter_GetData(writer); PyErr_Format(state->Error, "Invalid base32-encoded string: " "number of data characters (%zd) " "cannot be 1, 3, or 6 more than a multiple of 8", - ascii_data - ascii_data_start); + (bin_data - bin_data_start) / 5 * 8 + octa_pos); } goto error; } From 113038f94072b2f3c9c2648711b4dab74e232e3e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 4 Apr 2026 11:37:14 +0300 Subject: [PATCH 398/775] gh-148016: Improve "Leading padding not allowed" error in Base32 and Base64 decoders (GH-148017) It is now raised instead of "Excess padding not allowed" if all characters preceding "=" were ignored. --- Lib/test/test_binascii.py | 10 ++++++---- Modules/binascii.c | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index a3f7c7b832c..c8dbf3fec40 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -171,8 +171,8 @@ def _assertRegexTemplate(assert_regex, data, self.assertEqual(binascii.a2b_base64(data), non_strict_mode_expected_result) - def assertLeadingPadding(*args): - _assertRegexTemplate(r'(?i)Leading padding', *args) + def assertLeadingPadding(*args, **kwargs): + _assertRegexTemplate(r'(?i)Leading padding', *args, **kwargs) def assertDiscontinuousPadding(*args): _assertRegexTemplate(r'(?i)Discontinuous padding', *args) @@ -203,6 +203,7 @@ def assertInvalidLength(data, *args, length=None, **kwargs): assertLeadingPadding(b'===abcd', b'i\xb7\x1d') assertLeadingPadding(b'====abcd', b'i\xb7\x1d') assertLeadingPadding(b'=====abcd', b'i\xb7\x1d') + assertLeadingPadding(b' =abcd', b'i\xb7\x1d', ignorechars=b' ') assertInvalidLength(b'a=b==', b'i') assertInvalidLength(b'a=bc=', b'i\xb7') @@ -785,8 +786,8 @@ def assertExcessData(*args): def assertExcessPadding(*args): _assertRegexTemplate(r"(?i)Excess padding", *args) - def assertLeadingPadding(*args): - _assertRegexTemplate(r"(?i)Leading padding", *args) + def assertLeadingPadding(*args, **kwargs): + _assertRegexTemplate(r"(?i)Leading padding", *args, **kwargs) def assertIncorrectPadding(*args): _assertRegexTemplate(r"(?i)Incorrect padding", *args) @@ -853,6 +854,7 @@ def assertInvalidLength(data, *args, length=None, **kwargs): assertLeadingPadding(b"=======BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"========BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"=========BEEFCAKE", b"\t\x08Q\x01D") + assertLeadingPadding(b" =BEEFCAKE", ignorechars=b' ') assertIncorrectPadding(b"AB") assertIncorrectPadding(b"ABCD") diff --git a/Modules/binascii.c b/Modules/binascii.c index f28c0d472bb..d0ef2d2d2cc 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -816,8 +816,9 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, } state = get_binascii_state(module); if (state) { + unsigned char *bin_data_start = PyBytesWriter_GetData(writer); PyErr_SetString(state->Error, - (quad_pos == 0 && ascii_data == data->buf) + (quad_pos == 0 && bin_data == bin_data_start) ? "Leading padding not allowed" : "Excess padding not allowed"); } @@ -1601,8 +1602,9 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, } state = get_binascii_state(module); if (state) { + unsigned char *bin_data_start = PyBytesWriter_GetData(writer); PyErr_SetString(state->Error, - (octa_pos == 0 && ascii_data == data->buf) + (octa_pos == 0 && bin_data == bin_data_start) ? "Leading padding not allowed" : "Excess padding not allowed"); } From e7bf8eac0fef2e9aa954c9de36856954cb1b5f5b Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 4 Apr 2026 14:53:03 +0530 Subject: [PATCH 399/775] gh-131798: split recursion check to _CHECK_RECURSION_LIMIT and combine checks (GH-148070) --- Include/internal/pycore_opcode_metadata.h | 4 +- Include/internal/pycore_optimizer_types.h | 1 + Include/internal/pycore_uop_ids.h | 2443 +++++++++++---------- Include/internal/pycore_uop_metadata.h | 29 +- Lib/test/test_capi/test_opt.py | 17 + Modules/_testinternalcapi/test_cases.c.h | 26 +- Python/bytecodes.c | 12 +- Python/executor_cases.c.h | 90 +- Python/generated_cases.c.h | 26 +- Python/optimizer_bytecodes.c | 7 + Python/optimizer_cases.c.h | 8 + Python/optimizer_symbols.c | 1 + 12 files changed, 1393 insertions(+), 1271 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 15d5bd66845..916f3b8ee86 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1390,8 +1390,8 @@ _PyOpcode_macro_expansion[256] = { [CALL_LIST_APPEND] = { .nuops = 6, .uops = { { _GUARD_CALLABLE_LIST_APPEND, OPARG_SIMPLE, 3 }, { _GUARD_NOS_NOT_NULL, OPARG_SIMPLE, 3 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 3 }, { _CALL_LIST_APPEND, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } }, [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 3, .uops = { { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 4, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 4, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, - [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 5, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, + [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 8, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_LIMIT, OPARG_SIMPLE, 3 }, { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_NON_PY_GENERAL] = { .nuops = 4, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_IS_NOT_PY_CALLABLE, OPARG_SIMPLE, 3 }, { _CALL_NON_PY_GENERAL, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } }, [CALL_PY_EXACT_ARGS] = { .nuops = 9, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_PY_GENERAL] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, diff --git a/Include/internal/pycore_optimizer_types.h b/Include/internal/pycore_optimizer_types.h index fe45775201b..8ecfbea3874 100644 --- a/Include/internal/pycore_optimizer_types.h +++ b/Include/internal/pycore_optimizer_types.h @@ -147,6 +147,7 @@ typedef struct _Py_UOpsAbstractFrame { int stack_len; int locals_len; bool caller; // We have made a call from this frame during the trace + bool is_c_recursion_checked; JitOptRef callable; PyFunctionObject *func; PyCodeObject *code; diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index ae548eb3d68..dd319778b1f 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -95,141 +95,142 @@ extern "C" { #define _CHECK_PERIODIC 373 #define _CHECK_PERIODIC_AT_END 374 #define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 375 -#define _CHECK_RECURSION_REMAINING 376 -#define _CHECK_STACK_SPACE 377 -#define _CHECK_STACK_SPACE_OPERAND 378 -#define _CHECK_VALIDITY 379 -#define _COLD_DYNAMIC_EXIT 380 -#define _COLD_EXIT 381 -#define _COMPARE_OP 382 -#define _COMPARE_OP_FLOAT 383 -#define _COMPARE_OP_INT 384 -#define _COMPARE_OP_STR 385 -#define _CONTAINS_OP 386 -#define _CONTAINS_OP_DICT 387 -#define _CONTAINS_OP_SET 388 +#define _CHECK_RECURSION_LIMIT 376 +#define _CHECK_RECURSION_REMAINING 377 +#define _CHECK_STACK_SPACE 378 +#define _CHECK_STACK_SPACE_OPERAND 379 +#define _CHECK_VALIDITY 380 +#define _COLD_DYNAMIC_EXIT 381 +#define _COLD_EXIT 382 +#define _COMPARE_OP 383 +#define _COMPARE_OP_FLOAT 384 +#define _COMPARE_OP_INT 385 +#define _COMPARE_OP_STR 386 +#define _CONTAINS_OP 387 +#define _CONTAINS_OP_DICT 388 +#define _CONTAINS_OP_SET 389 #define _CONVERT_VALUE CONVERT_VALUE -#define _COPY 389 -#define _COPY_1 390 -#define _COPY_2 391 -#define _COPY_3 392 +#define _COPY 390 +#define _COPY_1 391 +#define _COPY_2 392 +#define _COPY_3 393 #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 393 +#define _CREATE_INIT_FRAME 394 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 394 -#define _DICT_MERGE 395 -#define _DICT_UPDATE 396 -#define _DO_CALL 397 -#define _DO_CALL_FUNCTION_EX 398 -#define _DO_CALL_KW 399 -#define _DYNAMIC_EXIT 400 +#define _DEOPT 395 +#define _DICT_MERGE 396 +#define _DICT_UPDATE 397 +#define _DO_CALL 398 +#define _DO_CALL_FUNCTION_EX 399 +#define _DO_CALL_KW 400 +#define _DYNAMIC_EXIT 401 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 401 +#define _ERROR_POP_N 402 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 402 -#define _EXPAND_METHOD_KW 403 -#define _FATAL_ERROR 404 +#define _EXPAND_METHOD 403 +#define _EXPAND_METHOD_KW 404 +#define _FATAL_ERROR 405 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 405 -#define _FOR_ITER_GEN_FRAME 406 -#define _FOR_ITER_TIER_TWO 407 +#define _FOR_ITER 406 +#define _FOR_ITER_GEN_FRAME 407 +#define _FOR_ITER_TIER_TWO 408 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN -#define _GUARD_BINARY_OP_EXTEND 408 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 409 -#define _GUARD_BIT_IS_SET_POP 410 -#define _GUARD_BIT_IS_SET_POP_4 411 -#define _GUARD_BIT_IS_SET_POP_5 412 -#define _GUARD_BIT_IS_SET_POP_6 413 -#define _GUARD_BIT_IS_SET_POP_7 414 -#define _GUARD_BIT_IS_UNSET_POP 415 -#define _GUARD_BIT_IS_UNSET_POP_4 416 -#define _GUARD_BIT_IS_UNSET_POP_5 417 -#define _GUARD_BIT_IS_UNSET_POP_6 418 -#define _GUARD_BIT_IS_UNSET_POP_7 419 -#define _GUARD_CALLABLE_BUILTIN_FAST 420 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 421 -#define _GUARD_CALLABLE_BUILTIN_O 422 -#define _GUARD_CALLABLE_ISINSTANCE 423 -#define _GUARD_CALLABLE_LEN 424 -#define _GUARD_CALLABLE_LIST_APPEND 425 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 426 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 427 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 428 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 429 -#define _GUARD_CALLABLE_STR_1 430 -#define _GUARD_CALLABLE_TUPLE_1 431 -#define _GUARD_CALLABLE_TYPE_1 432 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR 433 -#define _GUARD_CODE_VERSION_RETURN_VALUE 434 -#define _GUARD_CODE_VERSION_YIELD_VALUE 435 -#define _GUARD_CODE_VERSION__PUSH_FRAME 436 -#define _GUARD_DORV_NO_DICT 437 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 438 -#define _GUARD_GLOBALS_VERSION 439 -#define _GUARD_IP_RETURN_GENERATOR 440 -#define _GUARD_IP_RETURN_VALUE 441 -#define _GUARD_IP_YIELD_VALUE 442 -#define _GUARD_IP__PUSH_FRAME 443 -#define _GUARD_IS_FALSE_POP 444 -#define _GUARD_IS_NONE_POP 445 -#define _GUARD_IS_NOT_NONE_POP 446 -#define _GUARD_IS_TRUE_POP 447 -#define _GUARD_KEYS_VERSION 448 -#define _GUARD_NOS_ANY_DICT 449 -#define _GUARD_NOS_COMPACT_ASCII 450 -#define _GUARD_NOS_DICT 451 -#define _GUARD_NOS_FLOAT 452 -#define _GUARD_NOS_INT 453 -#define _GUARD_NOS_LIST 454 -#define _GUARD_NOS_NOT_NULL 455 -#define _GUARD_NOS_NULL 456 -#define _GUARD_NOS_OVERFLOWED 457 -#define _GUARD_NOS_TUPLE 458 -#define _GUARD_NOS_UNICODE 459 -#define _GUARD_NOT_EXHAUSTED_LIST 460 -#define _GUARD_NOT_EXHAUSTED_RANGE 461 -#define _GUARD_NOT_EXHAUSTED_TUPLE 462 -#define _GUARD_THIRD_NULL 463 -#define _GUARD_TOS_ANY_DICT 464 -#define _GUARD_TOS_ANY_SET 465 -#define _GUARD_TOS_DICT 466 -#define _GUARD_TOS_FLOAT 467 -#define _GUARD_TOS_FROZENDICT 468 -#define _GUARD_TOS_FROZENSET 469 -#define _GUARD_TOS_INT 470 -#define _GUARD_TOS_LIST 471 -#define _GUARD_TOS_OVERFLOWED 472 -#define _GUARD_TOS_SET 473 -#define _GUARD_TOS_SLICE 474 -#define _GUARD_TOS_TUPLE 475 -#define _GUARD_TOS_UNICODE 476 -#define _GUARD_TYPE_VERSION 477 -#define _GUARD_TYPE_VERSION_LOCKED 478 -#define _HANDLE_PENDING_AND_DEOPT 479 +#define _GUARD_BINARY_OP_EXTEND 409 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS 410 +#define _GUARD_BIT_IS_SET_POP 411 +#define _GUARD_BIT_IS_SET_POP_4 412 +#define _GUARD_BIT_IS_SET_POP_5 413 +#define _GUARD_BIT_IS_SET_POP_6 414 +#define _GUARD_BIT_IS_SET_POP_7 415 +#define _GUARD_BIT_IS_UNSET_POP 416 +#define _GUARD_BIT_IS_UNSET_POP_4 417 +#define _GUARD_BIT_IS_UNSET_POP_5 418 +#define _GUARD_BIT_IS_UNSET_POP_6 419 +#define _GUARD_BIT_IS_UNSET_POP_7 420 +#define _GUARD_CALLABLE_BUILTIN_FAST 421 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS 422 +#define _GUARD_CALLABLE_BUILTIN_O 423 +#define _GUARD_CALLABLE_ISINSTANCE 424 +#define _GUARD_CALLABLE_LEN 425 +#define _GUARD_CALLABLE_LIST_APPEND 426 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST 427 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 428 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS 429 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O 430 +#define _GUARD_CALLABLE_STR_1 431 +#define _GUARD_CALLABLE_TUPLE_1 432 +#define _GUARD_CALLABLE_TYPE_1 433 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR 434 +#define _GUARD_CODE_VERSION_RETURN_VALUE 435 +#define _GUARD_CODE_VERSION_YIELD_VALUE 436 +#define _GUARD_CODE_VERSION__PUSH_FRAME 437 +#define _GUARD_DORV_NO_DICT 438 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 439 +#define _GUARD_GLOBALS_VERSION 440 +#define _GUARD_IP_RETURN_GENERATOR 441 +#define _GUARD_IP_RETURN_VALUE 442 +#define _GUARD_IP_YIELD_VALUE 443 +#define _GUARD_IP__PUSH_FRAME 444 +#define _GUARD_IS_FALSE_POP 445 +#define _GUARD_IS_NONE_POP 446 +#define _GUARD_IS_NOT_NONE_POP 447 +#define _GUARD_IS_TRUE_POP 448 +#define _GUARD_KEYS_VERSION 449 +#define _GUARD_NOS_ANY_DICT 450 +#define _GUARD_NOS_COMPACT_ASCII 451 +#define _GUARD_NOS_DICT 452 +#define _GUARD_NOS_FLOAT 453 +#define _GUARD_NOS_INT 454 +#define _GUARD_NOS_LIST 455 +#define _GUARD_NOS_NOT_NULL 456 +#define _GUARD_NOS_NULL 457 +#define _GUARD_NOS_OVERFLOWED 458 +#define _GUARD_NOS_TUPLE 459 +#define _GUARD_NOS_UNICODE 460 +#define _GUARD_NOT_EXHAUSTED_LIST 461 +#define _GUARD_NOT_EXHAUSTED_RANGE 462 +#define _GUARD_NOT_EXHAUSTED_TUPLE 463 +#define _GUARD_THIRD_NULL 464 +#define _GUARD_TOS_ANY_DICT 465 +#define _GUARD_TOS_ANY_SET 466 +#define _GUARD_TOS_DICT 467 +#define _GUARD_TOS_FLOAT 468 +#define _GUARD_TOS_FROZENDICT 469 +#define _GUARD_TOS_FROZENSET 470 +#define _GUARD_TOS_INT 471 +#define _GUARD_TOS_LIST 472 +#define _GUARD_TOS_OVERFLOWED 473 +#define _GUARD_TOS_SET 474 +#define _GUARD_TOS_SLICE 475 +#define _GUARD_TOS_TUPLE 476 +#define _GUARD_TOS_UNICODE 477 +#define _GUARD_TYPE_VERSION 478 +#define _GUARD_TYPE_VERSION_LOCKED 479 +#define _HANDLE_PENDING_AND_DEOPT 480 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 480 -#define _INIT_CALL_PY_EXACT_ARGS 481 -#define _INIT_CALL_PY_EXACT_ARGS_0 482 -#define _INIT_CALL_PY_EXACT_ARGS_1 483 -#define _INIT_CALL_PY_EXACT_ARGS_2 484 -#define _INIT_CALL_PY_EXACT_ARGS_3 485 -#define _INIT_CALL_PY_EXACT_ARGS_4 486 -#define _INSERT_1_LOAD_CONST_INLINE 487 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 488 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 489 -#define _INSERT_NULL 490 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 481 +#define _INIT_CALL_PY_EXACT_ARGS 482 +#define _INIT_CALL_PY_EXACT_ARGS_0 483 +#define _INIT_CALL_PY_EXACT_ARGS_1 484 +#define _INIT_CALL_PY_EXACT_ARGS_2 485 +#define _INIT_CALL_PY_EXACT_ARGS_3 486 +#define _INIT_CALL_PY_EXACT_ARGS_4 487 +#define _INSERT_1_LOAD_CONST_INLINE 488 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW 489 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW 490 +#define _INSERT_NULL 491 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -239,1150 +240,1154 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 491 -#define _IS_OP 492 -#define _ITER_CHECK_LIST 493 -#define _ITER_CHECK_RANGE 494 -#define _ITER_CHECK_TUPLE 495 -#define _ITER_JUMP_LIST 496 -#define _ITER_JUMP_RANGE 497 -#define _ITER_JUMP_TUPLE 498 -#define _ITER_NEXT_LIST 499 -#define _ITER_NEXT_LIST_TIER_TWO 500 -#define _ITER_NEXT_RANGE 501 -#define _ITER_NEXT_TUPLE 502 +#define _IS_NONE 492 +#define _IS_OP 493 +#define _ITER_CHECK_LIST 494 +#define _ITER_CHECK_RANGE 495 +#define _ITER_CHECK_TUPLE 496 +#define _ITER_JUMP_LIST 497 +#define _ITER_JUMP_RANGE 498 +#define _ITER_JUMP_TUPLE 499 +#define _ITER_NEXT_LIST 500 +#define _ITER_NEXT_LIST_TIER_TWO 501 +#define _ITER_NEXT_RANGE 502 +#define _ITER_NEXT_TUPLE 503 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 503 +#define _JUMP_TO_TOP 504 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND 504 -#define _LOAD_ATTR 505 -#define _LOAD_ATTR_CLASS 506 +#define _LIST_EXTEND 505 +#define _LOAD_ATTR 506 +#define _LOAD_ATTR_CLASS 507 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 507 -#define _LOAD_ATTR_METHOD_LAZY_DICT 508 -#define _LOAD_ATTR_METHOD_NO_DICT 509 -#define _LOAD_ATTR_METHOD_WITH_VALUES 510 -#define _LOAD_ATTR_MODULE 511 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 512 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 513 -#define _LOAD_ATTR_PROPERTY_FRAME 514 -#define _LOAD_ATTR_SLOT 515 -#define _LOAD_ATTR_WITH_HINT 516 +#define _LOAD_ATTR_INSTANCE_VALUE 508 +#define _LOAD_ATTR_METHOD_LAZY_DICT 509 +#define _LOAD_ATTR_METHOD_NO_DICT 510 +#define _LOAD_ATTR_METHOD_WITH_VALUES 511 +#define _LOAD_ATTR_MODULE 512 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 513 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 514 +#define _LOAD_ATTR_PROPERTY_FRAME 515 +#define _LOAD_ATTR_SLOT 516 +#define _LOAD_ATTR_WITH_HINT 517 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 517 +#define _LOAD_BYTECODE 518 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 518 -#define _LOAD_CONST_INLINE_BORROW 519 -#define _LOAD_CONST_UNDER_INLINE 520 -#define _LOAD_CONST_UNDER_INLINE_BORROW 521 +#define _LOAD_CONST_INLINE 519 +#define _LOAD_CONST_INLINE_BORROW 520 +#define _LOAD_CONST_UNDER_INLINE 521 +#define _LOAD_CONST_UNDER_INLINE_BORROW 522 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 522 -#define _LOAD_FAST_0 523 -#define _LOAD_FAST_1 524 -#define _LOAD_FAST_2 525 -#define _LOAD_FAST_3 526 -#define _LOAD_FAST_4 527 -#define _LOAD_FAST_5 528 -#define _LOAD_FAST_6 529 -#define _LOAD_FAST_7 530 +#define _LOAD_FAST 523 +#define _LOAD_FAST_0 524 +#define _LOAD_FAST_1 525 +#define _LOAD_FAST_2 526 +#define _LOAD_FAST_3 527 +#define _LOAD_FAST_4 528 +#define _LOAD_FAST_5 529 +#define _LOAD_FAST_6 530 +#define _LOAD_FAST_7 531 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 531 -#define _LOAD_FAST_BORROW_0 532 -#define _LOAD_FAST_BORROW_1 533 -#define _LOAD_FAST_BORROW_2 534 -#define _LOAD_FAST_BORROW_3 535 -#define _LOAD_FAST_BORROW_4 536 -#define _LOAD_FAST_BORROW_5 537 -#define _LOAD_FAST_BORROW_6 538 -#define _LOAD_FAST_BORROW_7 539 +#define _LOAD_FAST_BORROW 532 +#define _LOAD_FAST_BORROW_0 533 +#define _LOAD_FAST_BORROW_1 534 +#define _LOAD_FAST_BORROW_2 535 +#define _LOAD_FAST_BORROW_3 536 +#define _LOAD_FAST_BORROW_4 537 +#define _LOAD_FAST_BORROW_5 538 +#define _LOAD_FAST_BORROW_6 539 +#define _LOAD_FAST_BORROW_7 540 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 540 -#define _LOAD_GLOBAL_BUILTINS 541 -#define _LOAD_GLOBAL_MODULE 542 +#define _LOAD_GLOBAL 541 +#define _LOAD_GLOBAL_BUILTINS 542 +#define _LOAD_GLOBAL_MODULE 543 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 543 -#define _LOAD_SMALL_INT_0 544 -#define _LOAD_SMALL_INT_1 545 -#define _LOAD_SMALL_INT_2 546 -#define _LOAD_SMALL_INT_3 547 -#define _LOAD_SPECIAL 548 +#define _LOAD_SMALL_INT 544 +#define _LOAD_SMALL_INT_0 545 +#define _LOAD_SMALL_INT_1 546 +#define _LOAD_SMALL_INT_2 547 +#define _LOAD_SMALL_INT_3 548 +#define _LOAD_SPECIAL 549 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _LOCK_OBJECT 549 -#define _MAKE_CALLARGS_A_TUPLE 550 +#define _LOCK_OBJECT 550 +#define _MAKE_CALLARGS_A_TUPLE 551 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_HEAP_SAFE 551 -#define _MAKE_WARM 552 +#define _MAKE_HEAP_SAFE 552 +#define _MAKE_WARM 553 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 553 +#define _MATCH_CLASS 554 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 554 -#define _MAYBE_EXPAND_METHOD_KW 555 -#define _MONITOR_CALL 556 -#define _MONITOR_CALL_KW 557 -#define _MONITOR_JUMP_BACKWARD 558 -#define _MONITOR_RESUME 559 +#define _MAYBE_EXPAND_METHOD 555 +#define _MAYBE_EXPAND_METHOD_KW 556 +#define _MONITOR_CALL 557 +#define _MONITOR_CALL_KW 558 +#define _MONITOR_JUMP_BACKWARD 559 +#define _MONITOR_RESUME 560 #define _NOP NOP -#define _POP_CALL 560 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 561 -#define _POP_CALL_ONE 562 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 563 -#define _POP_CALL_TWO 564 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 565 +#define _POP_CALL 561 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 562 +#define _POP_CALL_ONE 563 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 564 +#define _POP_CALL_TWO 565 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 566 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 566 -#define _POP_JUMP_IF_TRUE 567 +#define _POP_JUMP_IF_FALSE 567 +#define _POP_JUMP_IF_TRUE 568 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 568 -#define _POP_TOP_INT 569 -#define _POP_TOP_LOAD_CONST_INLINE 570 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 571 -#define _POP_TOP_NOP 572 -#define _POP_TOP_UNICODE 573 -#define _POP_TWO 574 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 575 +#define _POP_TOP_FLOAT 569 +#define _POP_TOP_INT 570 +#define _POP_TOP_LOAD_CONST_INLINE 571 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 572 +#define _POP_TOP_NOP 573 +#define _POP_TOP_UNICODE 574 +#define _POP_TWO 575 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 576 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 576 +#define _PUSH_FRAME 577 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 577 -#define _PY_FRAME_EX 578 -#define _PY_FRAME_GENERAL 579 -#define _PY_FRAME_KW 580 -#define _RECORD_3OS_GEN_FUNC 581 -#define _RECORD_4OS 582 -#define _RECORD_BOUND_METHOD 583 -#define _RECORD_CALLABLE 584 -#define _RECORD_CODE 585 -#define _RECORD_NOS 586 -#define _RECORD_NOS_GEN_FUNC 587 -#define _RECORD_TOS 588 -#define _RECORD_TOS_TYPE 589 -#define _REPLACE_WITH_TRUE 590 -#define _RESUME_CHECK 591 +#define _PUSH_NULL_CONDITIONAL 578 +#define _PY_FRAME_EX 579 +#define _PY_FRAME_GENERAL 580 +#define _PY_FRAME_KW 581 +#define _RECORD_3OS_GEN_FUNC 582 +#define _RECORD_4OS 583 +#define _RECORD_BOUND_METHOD 584 +#define _RECORD_CALLABLE 585 +#define _RECORD_CODE 586 +#define _RECORD_NOS 587 +#define _RECORD_NOS_GEN_FUNC 588 +#define _RECORD_TOS 589 +#define _RECORD_TOS_TYPE 590 +#define _REPLACE_WITH_TRUE 591 +#define _RESUME_CHECK 592 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 592 -#define _SAVE_RETURN_OFFSET 593 -#define _SEND 594 -#define _SEND_GEN_FRAME 595 +#define _RETURN_VALUE 593 +#define _SAVE_RETURN_OFFSET 594 +#define _SEND 595 +#define _SEND_GEN_FRAME 596 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 596 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 597 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 598 -#define _SPILL_OR_RELOAD 599 -#define _START_EXECUTOR 600 -#define _STORE_ATTR 601 -#define _STORE_ATTR_INSTANCE_VALUE 602 -#define _STORE_ATTR_SLOT 603 -#define _STORE_ATTR_WITH_HINT 604 +#define _SET_UPDATE 597 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW 598 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 599 +#define _SPILL_OR_RELOAD 600 +#define _START_EXECUTOR 601 +#define _STORE_ATTR 602 +#define _STORE_ATTR_INSTANCE_VALUE 603 +#define _STORE_ATTR_SLOT 604 +#define _STORE_ATTR_WITH_HINT 605 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 605 -#define _STORE_SUBSCR 606 -#define _STORE_SUBSCR_DICT 607 -#define _STORE_SUBSCR_DICT_KNOWN_HASH 608 -#define _STORE_SUBSCR_LIST_INT 609 -#define _SWAP 610 -#define _SWAP_2 611 -#define _SWAP_3 612 -#define _SWAP_FAST 613 -#define _SWAP_FAST_0 614 -#define _SWAP_FAST_1 615 -#define _SWAP_FAST_2 616 -#define _SWAP_FAST_3 617 -#define _SWAP_FAST_4 618 -#define _SWAP_FAST_5 619 -#define _SWAP_FAST_6 620 -#define _SWAP_FAST_7 621 -#define _TIER2_RESUME_CHECK 622 -#define _TO_BOOL 623 +#define _STORE_SLICE 606 +#define _STORE_SUBSCR 607 +#define _STORE_SUBSCR_DICT 608 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 609 +#define _STORE_SUBSCR_LIST_INT 610 +#define _SWAP 611 +#define _SWAP_2 612 +#define _SWAP_3 613 +#define _SWAP_FAST 614 +#define _SWAP_FAST_0 615 +#define _SWAP_FAST_1 616 +#define _SWAP_FAST_2 617 +#define _SWAP_FAST_3 618 +#define _SWAP_FAST_4 619 +#define _SWAP_FAST_5 620 +#define _SWAP_FAST_6 621 +#define _SWAP_FAST_7 622 +#define _TIER2_RESUME_CHECK 623 +#define _TO_BOOL 624 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 624 -#define _TO_BOOL_LIST 625 +#define _TO_BOOL_INT 625 +#define _TO_BOOL_LIST 626 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 626 +#define _TO_BOOL_STR 627 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 627 -#define _UNARY_NEGATIVE 628 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 629 +#define _UNARY_INVERT 628 +#define _UNARY_NEGATIVE 629 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 630 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 630 -#define _UNPACK_SEQUENCE_LIST 631 -#define _UNPACK_SEQUENCE_TUPLE 632 -#define _UNPACK_SEQUENCE_TWO_TUPLE 633 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 634 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 635 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 636 +#define _UNPACK_SEQUENCE 631 +#define _UNPACK_SEQUENCE_LIST 632 +#define _UNPACK_SEQUENCE_TUPLE 633 +#define _UNPACK_SEQUENCE_TWO_TUPLE 634 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 635 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 636 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 637 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 637 -#define MAX_UOP_ID 637 -#define _BINARY_OP_r23 638 -#define _BINARY_OP_ADD_FLOAT_r03 639 -#define _BINARY_OP_ADD_FLOAT_r13 640 -#define _BINARY_OP_ADD_FLOAT_r23 641 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 642 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 643 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 644 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 645 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 646 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 647 -#define _BINARY_OP_ADD_INT_r03 648 -#define _BINARY_OP_ADD_INT_r13 649 -#define _BINARY_OP_ADD_INT_r23 650 -#define _BINARY_OP_ADD_INT_INPLACE_r03 651 -#define _BINARY_OP_ADD_INT_INPLACE_r13 652 -#define _BINARY_OP_ADD_INT_INPLACE_r23 653 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 654 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 655 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 656 -#define _BINARY_OP_ADD_UNICODE_r03 657 -#define _BINARY_OP_ADD_UNICODE_r13 658 -#define _BINARY_OP_ADD_UNICODE_r23 659 -#define _BINARY_OP_EXTEND_r23 660 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 661 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 662 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 663 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 664 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 665 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 666 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 667 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 668 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 669 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 670 -#define _BINARY_OP_MULTIPLY_INT_r03 671 -#define _BINARY_OP_MULTIPLY_INT_r13 672 -#define _BINARY_OP_MULTIPLY_INT_r23 673 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 674 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 675 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 676 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 677 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 678 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 679 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 680 -#define _BINARY_OP_SUBSCR_DICT_r23 681 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 682 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 683 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 684 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 685 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 686 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 687 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 688 -#define _BINARY_OP_SUBSCR_STR_INT_r23 689 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 690 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 691 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 692 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 693 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 694 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 695 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 696 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 697 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 698 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 699 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 700 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 701 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 702 -#define _BINARY_OP_SUBTRACT_INT_r03 703 -#define _BINARY_OP_SUBTRACT_INT_r13 704 -#define _BINARY_OP_SUBTRACT_INT_r23 705 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 706 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 707 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 708 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 709 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 710 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 711 -#define _BINARY_SLICE_r31 712 -#define _BUILD_INTERPOLATION_r01 713 -#define _BUILD_LIST_r01 714 -#define _BUILD_MAP_r01 715 -#define _BUILD_SET_r01 716 -#define _BUILD_SLICE_r01 717 -#define _BUILD_STRING_r01 718 -#define _BUILD_TEMPLATE_r21 719 -#define _BUILD_TUPLE_r01 720 -#define _CALL_BUILTIN_CLASS_r01 721 -#define _CALL_BUILTIN_FAST_r01 722 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 723 -#define _CALL_BUILTIN_O_r03 724 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 725 -#define _CALL_INTRINSIC_1_r12 726 -#define _CALL_INTRINSIC_2_r23 727 -#define _CALL_ISINSTANCE_r31 728 -#define _CALL_KW_NON_PY_r11 729 -#define _CALL_LEN_r33 730 -#define _CALL_LIST_APPEND_r03 731 -#define _CALL_LIST_APPEND_r13 732 -#define _CALL_LIST_APPEND_r23 733 -#define _CALL_LIST_APPEND_r33 734 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 735 -#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01 736 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 737 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01 738 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 739 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01 740 -#define _CALL_METHOD_DESCRIPTOR_O_r03 741 -#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 742 -#define _CALL_NON_PY_GENERAL_r01 743 -#define _CALL_STR_1_r32 744 -#define _CALL_TUPLE_1_r32 745 -#define _CALL_TYPE_1_r02 746 -#define _CALL_TYPE_1_r12 747 -#define _CALL_TYPE_1_r22 748 -#define _CALL_TYPE_1_r32 749 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 750 -#define _CHECK_ATTR_CLASS_r01 751 -#define _CHECK_ATTR_CLASS_r11 752 -#define _CHECK_ATTR_CLASS_r22 753 -#define _CHECK_ATTR_CLASS_r33 754 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 755 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 756 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 757 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 758 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 759 -#define _CHECK_EG_MATCH_r22 760 -#define _CHECK_EXC_MATCH_r22 761 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 762 -#define _CHECK_FUNCTION_VERSION_r00 763 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 764 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 765 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 766 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 767 -#define _CHECK_FUNCTION_VERSION_KW_r11 768 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 769 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 770 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 771 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 772 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 773 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 774 -#define _CHECK_IS_PY_CALLABLE_EX_r03 775 -#define _CHECK_IS_PY_CALLABLE_EX_r13 776 -#define _CHECK_IS_PY_CALLABLE_EX_r23 777 -#define _CHECK_IS_PY_CALLABLE_EX_r33 778 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 779 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 780 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 781 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 782 -#define _CHECK_METHOD_VERSION_r00 783 -#define _CHECK_METHOD_VERSION_KW_r11 784 -#define _CHECK_PEP_523_r00 785 -#define _CHECK_PEP_523_r11 786 -#define _CHECK_PEP_523_r22 787 -#define _CHECK_PEP_523_r33 788 -#define _CHECK_PERIODIC_r00 789 -#define _CHECK_PERIODIC_AT_END_r00 790 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 791 -#define _CHECK_RECURSION_REMAINING_r00 792 -#define _CHECK_RECURSION_REMAINING_r11 793 -#define _CHECK_RECURSION_REMAINING_r22 794 -#define _CHECK_RECURSION_REMAINING_r33 795 -#define _CHECK_STACK_SPACE_r00 796 -#define _CHECK_STACK_SPACE_OPERAND_r00 797 -#define _CHECK_STACK_SPACE_OPERAND_r11 798 -#define _CHECK_STACK_SPACE_OPERAND_r22 799 -#define _CHECK_STACK_SPACE_OPERAND_r33 800 -#define _CHECK_VALIDITY_r00 801 -#define _CHECK_VALIDITY_r11 802 -#define _CHECK_VALIDITY_r22 803 -#define _CHECK_VALIDITY_r33 804 -#define _COLD_DYNAMIC_EXIT_r00 805 -#define _COLD_EXIT_r00 806 -#define _COMPARE_OP_r21 807 -#define _COMPARE_OP_FLOAT_r03 808 -#define _COMPARE_OP_FLOAT_r13 809 -#define _COMPARE_OP_FLOAT_r23 810 -#define _COMPARE_OP_INT_r23 811 -#define _COMPARE_OP_STR_r23 812 -#define _CONTAINS_OP_r23 813 -#define _CONTAINS_OP_DICT_r23 814 -#define _CONTAINS_OP_SET_r23 815 -#define _CONVERT_VALUE_r11 816 -#define _COPY_r01 817 -#define _COPY_1_r02 818 -#define _COPY_1_r12 819 -#define _COPY_1_r23 820 -#define _COPY_2_r03 821 -#define _COPY_2_r13 822 -#define _COPY_2_r23 823 -#define _COPY_3_r03 824 -#define _COPY_3_r13 825 -#define _COPY_3_r23 826 -#define _COPY_3_r33 827 -#define _COPY_FREE_VARS_r00 828 -#define _COPY_FREE_VARS_r11 829 -#define _COPY_FREE_VARS_r22 830 -#define _COPY_FREE_VARS_r33 831 -#define _CREATE_INIT_FRAME_r01 832 -#define _DELETE_ATTR_r10 833 -#define _DELETE_DEREF_r00 834 -#define _DELETE_FAST_r00 835 -#define _DELETE_GLOBAL_r00 836 -#define _DELETE_NAME_r00 837 -#define _DELETE_SUBSCR_r20 838 -#define _DEOPT_r00 839 -#define _DEOPT_r10 840 -#define _DEOPT_r20 841 -#define _DEOPT_r30 842 -#define _DICT_MERGE_r11 843 -#define _DICT_UPDATE_r11 844 -#define _DO_CALL_r01 845 -#define _DO_CALL_FUNCTION_EX_r31 846 -#define _DO_CALL_KW_r11 847 -#define _DYNAMIC_EXIT_r00 848 -#define _DYNAMIC_EXIT_r10 849 -#define _DYNAMIC_EXIT_r20 850 -#define _DYNAMIC_EXIT_r30 851 -#define _END_FOR_r10 852 -#define _END_SEND_r31 853 -#define _ERROR_POP_N_r00 854 -#define _EXIT_INIT_CHECK_r10 855 -#define _EXIT_TRACE_r00 856 -#define _EXIT_TRACE_r10 857 -#define _EXIT_TRACE_r20 858 -#define _EXIT_TRACE_r30 859 -#define _EXPAND_METHOD_r00 860 -#define _EXPAND_METHOD_KW_r11 861 -#define _FATAL_ERROR_r00 862 -#define _FATAL_ERROR_r11 863 -#define _FATAL_ERROR_r22 864 -#define _FATAL_ERROR_r33 865 -#define _FORMAT_SIMPLE_r11 866 -#define _FORMAT_WITH_SPEC_r21 867 -#define _FOR_ITER_r23 868 -#define _FOR_ITER_GEN_FRAME_r03 869 -#define _FOR_ITER_GEN_FRAME_r13 870 -#define _FOR_ITER_GEN_FRAME_r23 871 -#define _FOR_ITER_TIER_TWO_r23 872 -#define _GET_AITER_r11 873 -#define _GET_ANEXT_r12 874 -#define _GET_AWAITABLE_r11 875 -#define _GET_ITER_r12 876 -#define _GET_LEN_r12 877 -#define _GUARD_BINARY_OP_EXTEND_r22 878 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 879 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 880 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 881 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 882 -#define _GUARD_BIT_IS_SET_POP_r00 883 -#define _GUARD_BIT_IS_SET_POP_r10 884 -#define _GUARD_BIT_IS_SET_POP_r21 885 -#define _GUARD_BIT_IS_SET_POP_r32 886 -#define _GUARD_BIT_IS_SET_POP_4_r00 887 -#define _GUARD_BIT_IS_SET_POP_4_r10 888 -#define _GUARD_BIT_IS_SET_POP_4_r21 889 -#define _GUARD_BIT_IS_SET_POP_4_r32 890 -#define _GUARD_BIT_IS_SET_POP_5_r00 891 -#define _GUARD_BIT_IS_SET_POP_5_r10 892 -#define _GUARD_BIT_IS_SET_POP_5_r21 893 -#define _GUARD_BIT_IS_SET_POP_5_r32 894 -#define _GUARD_BIT_IS_SET_POP_6_r00 895 -#define _GUARD_BIT_IS_SET_POP_6_r10 896 -#define _GUARD_BIT_IS_SET_POP_6_r21 897 -#define _GUARD_BIT_IS_SET_POP_6_r32 898 -#define _GUARD_BIT_IS_SET_POP_7_r00 899 -#define _GUARD_BIT_IS_SET_POP_7_r10 900 -#define _GUARD_BIT_IS_SET_POP_7_r21 901 -#define _GUARD_BIT_IS_SET_POP_7_r32 902 -#define _GUARD_BIT_IS_UNSET_POP_r00 903 -#define _GUARD_BIT_IS_UNSET_POP_r10 904 -#define _GUARD_BIT_IS_UNSET_POP_r21 905 -#define _GUARD_BIT_IS_UNSET_POP_r32 906 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 907 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 908 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 909 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 910 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 911 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 912 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 913 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 914 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 915 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 916 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 917 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 918 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 919 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 920 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 921 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 922 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 923 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 924 -#define _GUARD_CALLABLE_BUILTIN_O_r00 925 -#define _GUARD_CALLABLE_ISINSTANCE_r03 926 -#define _GUARD_CALLABLE_ISINSTANCE_r13 927 -#define _GUARD_CALLABLE_ISINSTANCE_r23 928 -#define _GUARD_CALLABLE_ISINSTANCE_r33 929 -#define _GUARD_CALLABLE_LEN_r03 930 -#define _GUARD_CALLABLE_LEN_r13 931 -#define _GUARD_CALLABLE_LEN_r23 932 -#define _GUARD_CALLABLE_LEN_r33 933 -#define _GUARD_CALLABLE_LIST_APPEND_r03 934 -#define _GUARD_CALLABLE_LIST_APPEND_r13 935 -#define _GUARD_CALLABLE_LIST_APPEND_r23 936 -#define _GUARD_CALLABLE_LIST_APPEND_r33 937 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 938 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 939 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 940 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 941 -#define _GUARD_CALLABLE_STR_1_r03 942 -#define _GUARD_CALLABLE_STR_1_r13 943 -#define _GUARD_CALLABLE_STR_1_r23 944 -#define _GUARD_CALLABLE_STR_1_r33 945 -#define _GUARD_CALLABLE_TUPLE_1_r03 946 -#define _GUARD_CALLABLE_TUPLE_1_r13 947 -#define _GUARD_CALLABLE_TUPLE_1_r23 948 -#define _GUARD_CALLABLE_TUPLE_1_r33 949 -#define _GUARD_CALLABLE_TYPE_1_r03 950 -#define _GUARD_CALLABLE_TYPE_1_r13 951 -#define _GUARD_CALLABLE_TYPE_1_r23 952 -#define _GUARD_CALLABLE_TYPE_1_r33 953 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 954 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 955 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 956 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 957 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 958 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 959 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 960 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 961 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 962 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 963 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 964 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 965 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 966 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 967 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 968 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 969 -#define _GUARD_DORV_NO_DICT_r01 970 -#define _GUARD_DORV_NO_DICT_r11 971 -#define _GUARD_DORV_NO_DICT_r22 972 -#define _GUARD_DORV_NO_DICT_r33 973 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 974 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 975 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 976 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 977 -#define _GUARD_GLOBALS_VERSION_r00 978 -#define _GUARD_GLOBALS_VERSION_r11 979 -#define _GUARD_GLOBALS_VERSION_r22 980 -#define _GUARD_GLOBALS_VERSION_r33 981 -#define _GUARD_IP_RETURN_GENERATOR_r00 982 -#define _GUARD_IP_RETURN_GENERATOR_r11 983 -#define _GUARD_IP_RETURN_GENERATOR_r22 984 -#define _GUARD_IP_RETURN_GENERATOR_r33 985 -#define _GUARD_IP_RETURN_VALUE_r00 986 -#define _GUARD_IP_RETURN_VALUE_r11 987 -#define _GUARD_IP_RETURN_VALUE_r22 988 -#define _GUARD_IP_RETURN_VALUE_r33 989 -#define _GUARD_IP_YIELD_VALUE_r00 990 -#define _GUARD_IP_YIELD_VALUE_r11 991 -#define _GUARD_IP_YIELD_VALUE_r22 992 -#define _GUARD_IP_YIELD_VALUE_r33 993 -#define _GUARD_IP__PUSH_FRAME_r00 994 -#define _GUARD_IP__PUSH_FRAME_r11 995 -#define _GUARD_IP__PUSH_FRAME_r22 996 -#define _GUARD_IP__PUSH_FRAME_r33 997 -#define _GUARD_IS_FALSE_POP_r00 998 -#define _GUARD_IS_FALSE_POP_r10 999 -#define _GUARD_IS_FALSE_POP_r21 1000 -#define _GUARD_IS_FALSE_POP_r32 1001 -#define _GUARD_IS_NONE_POP_r00 1002 -#define _GUARD_IS_NONE_POP_r10 1003 -#define _GUARD_IS_NONE_POP_r21 1004 -#define _GUARD_IS_NONE_POP_r32 1005 -#define _GUARD_IS_NOT_NONE_POP_r10 1006 -#define _GUARD_IS_TRUE_POP_r00 1007 -#define _GUARD_IS_TRUE_POP_r10 1008 -#define _GUARD_IS_TRUE_POP_r21 1009 -#define _GUARD_IS_TRUE_POP_r32 1010 -#define _GUARD_KEYS_VERSION_r01 1011 -#define _GUARD_KEYS_VERSION_r11 1012 -#define _GUARD_KEYS_VERSION_r22 1013 -#define _GUARD_KEYS_VERSION_r33 1014 -#define _GUARD_NOS_ANY_DICT_r02 1015 -#define _GUARD_NOS_ANY_DICT_r12 1016 -#define _GUARD_NOS_ANY_DICT_r22 1017 -#define _GUARD_NOS_ANY_DICT_r33 1018 -#define _GUARD_NOS_COMPACT_ASCII_r02 1019 -#define _GUARD_NOS_COMPACT_ASCII_r12 1020 -#define _GUARD_NOS_COMPACT_ASCII_r22 1021 -#define _GUARD_NOS_COMPACT_ASCII_r33 1022 -#define _GUARD_NOS_DICT_r02 1023 -#define _GUARD_NOS_DICT_r12 1024 -#define _GUARD_NOS_DICT_r22 1025 -#define _GUARD_NOS_DICT_r33 1026 -#define _GUARD_NOS_FLOAT_r02 1027 -#define _GUARD_NOS_FLOAT_r12 1028 -#define _GUARD_NOS_FLOAT_r22 1029 -#define _GUARD_NOS_FLOAT_r33 1030 -#define _GUARD_NOS_INT_r02 1031 -#define _GUARD_NOS_INT_r12 1032 -#define _GUARD_NOS_INT_r22 1033 -#define _GUARD_NOS_INT_r33 1034 -#define _GUARD_NOS_LIST_r02 1035 -#define _GUARD_NOS_LIST_r12 1036 -#define _GUARD_NOS_LIST_r22 1037 -#define _GUARD_NOS_LIST_r33 1038 -#define _GUARD_NOS_NOT_NULL_r02 1039 -#define _GUARD_NOS_NOT_NULL_r12 1040 -#define _GUARD_NOS_NOT_NULL_r22 1041 -#define _GUARD_NOS_NOT_NULL_r33 1042 -#define _GUARD_NOS_NULL_r02 1043 -#define _GUARD_NOS_NULL_r12 1044 -#define _GUARD_NOS_NULL_r22 1045 -#define _GUARD_NOS_NULL_r33 1046 -#define _GUARD_NOS_OVERFLOWED_r02 1047 -#define _GUARD_NOS_OVERFLOWED_r12 1048 -#define _GUARD_NOS_OVERFLOWED_r22 1049 -#define _GUARD_NOS_OVERFLOWED_r33 1050 -#define _GUARD_NOS_TUPLE_r02 1051 -#define _GUARD_NOS_TUPLE_r12 1052 -#define _GUARD_NOS_TUPLE_r22 1053 -#define _GUARD_NOS_TUPLE_r33 1054 -#define _GUARD_NOS_UNICODE_r02 1055 -#define _GUARD_NOS_UNICODE_r12 1056 -#define _GUARD_NOS_UNICODE_r22 1057 -#define _GUARD_NOS_UNICODE_r33 1058 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1059 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1060 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1061 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1062 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1063 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1064 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1065 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1066 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1067 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1068 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1069 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1070 -#define _GUARD_THIRD_NULL_r03 1071 -#define _GUARD_THIRD_NULL_r13 1072 -#define _GUARD_THIRD_NULL_r23 1073 -#define _GUARD_THIRD_NULL_r33 1074 -#define _GUARD_TOS_ANY_DICT_r01 1075 -#define _GUARD_TOS_ANY_DICT_r11 1076 -#define _GUARD_TOS_ANY_DICT_r22 1077 -#define _GUARD_TOS_ANY_DICT_r33 1078 -#define _GUARD_TOS_ANY_SET_r01 1079 -#define _GUARD_TOS_ANY_SET_r11 1080 -#define _GUARD_TOS_ANY_SET_r22 1081 -#define _GUARD_TOS_ANY_SET_r33 1082 -#define _GUARD_TOS_DICT_r01 1083 -#define _GUARD_TOS_DICT_r11 1084 -#define _GUARD_TOS_DICT_r22 1085 -#define _GUARD_TOS_DICT_r33 1086 -#define _GUARD_TOS_FLOAT_r01 1087 -#define _GUARD_TOS_FLOAT_r11 1088 -#define _GUARD_TOS_FLOAT_r22 1089 -#define _GUARD_TOS_FLOAT_r33 1090 -#define _GUARD_TOS_FROZENDICT_r01 1091 -#define _GUARD_TOS_FROZENDICT_r11 1092 -#define _GUARD_TOS_FROZENDICT_r22 1093 -#define _GUARD_TOS_FROZENDICT_r33 1094 -#define _GUARD_TOS_FROZENSET_r01 1095 -#define _GUARD_TOS_FROZENSET_r11 1096 -#define _GUARD_TOS_FROZENSET_r22 1097 -#define _GUARD_TOS_FROZENSET_r33 1098 -#define _GUARD_TOS_INT_r01 1099 -#define _GUARD_TOS_INT_r11 1100 -#define _GUARD_TOS_INT_r22 1101 -#define _GUARD_TOS_INT_r33 1102 -#define _GUARD_TOS_LIST_r01 1103 -#define _GUARD_TOS_LIST_r11 1104 -#define _GUARD_TOS_LIST_r22 1105 -#define _GUARD_TOS_LIST_r33 1106 -#define _GUARD_TOS_OVERFLOWED_r01 1107 -#define _GUARD_TOS_OVERFLOWED_r11 1108 -#define _GUARD_TOS_OVERFLOWED_r22 1109 -#define _GUARD_TOS_OVERFLOWED_r33 1110 -#define _GUARD_TOS_SET_r01 1111 -#define _GUARD_TOS_SET_r11 1112 -#define _GUARD_TOS_SET_r22 1113 -#define _GUARD_TOS_SET_r33 1114 -#define _GUARD_TOS_SLICE_r01 1115 -#define _GUARD_TOS_SLICE_r11 1116 -#define _GUARD_TOS_SLICE_r22 1117 -#define _GUARD_TOS_SLICE_r33 1118 -#define _GUARD_TOS_TUPLE_r01 1119 -#define _GUARD_TOS_TUPLE_r11 1120 -#define _GUARD_TOS_TUPLE_r22 1121 -#define _GUARD_TOS_TUPLE_r33 1122 -#define _GUARD_TOS_UNICODE_r01 1123 -#define _GUARD_TOS_UNICODE_r11 1124 -#define _GUARD_TOS_UNICODE_r22 1125 -#define _GUARD_TOS_UNICODE_r33 1126 -#define _GUARD_TYPE_VERSION_r01 1127 -#define _GUARD_TYPE_VERSION_r11 1128 -#define _GUARD_TYPE_VERSION_r22 1129 -#define _GUARD_TYPE_VERSION_r33 1130 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1131 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1132 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1133 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1134 -#define _HANDLE_PENDING_AND_DEOPT_r00 1135 -#define _HANDLE_PENDING_AND_DEOPT_r10 1136 -#define _HANDLE_PENDING_AND_DEOPT_r20 1137 -#define _HANDLE_PENDING_AND_DEOPT_r30 1138 -#define _IMPORT_FROM_r12 1139 -#define _IMPORT_NAME_r21 1140 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1141 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1142 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1143 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1144 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1145 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1146 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1147 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1148 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1149 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1150 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1151 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1152 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1153 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1154 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1155 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1156 -#define _INSERT_NULL_r10 1157 -#define _INSTRUMENTED_FOR_ITER_r23 1158 -#define _INSTRUMENTED_INSTRUCTION_r00 1159 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1160 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1161 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1162 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1163 -#define _INSTRUMENTED_LINE_r00 1164 -#define _INSTRUMENTED_NOT_TAKEN_r00 1165 -#define _INSTRUMENTED_NOT_TAKEN_r11 1166 -#define _INSTRUMENTED_NOT_TAKEN_r22 1167 -#define _INSTRUMENTED_NOT_TAKEN_r33 1168 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1169 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1170 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1171 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1172 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1173 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1174 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1175 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1176 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1177 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1178 -#define _IS_NONE_r11 1179 -#define _IS_OP_r03 1180 -#define _IS_OP_r13 1181 -#define _IS_OP_r23 1182 -#define _ITER_CHECK_LIST_r02 1183 -#define _ITER_CHECK_LIST_r12 1184 -#define _ITER_CHECK_LIST_r22 1185 -#define _ITER_CHECK_LIST_r33 1186 -#define _ITER_CHECK_RANGE_r02 1187 -#define _ITER_CHECK_RANGE_r12 1188 -#define _ITER_CHECK_RANGE_r22 1189 -#define _ITER_CHECK_RANGE_r33 1190 -#define _ITER_CHECK_TUPLE_r02 1191 -#define _ITER_CHECK_TUPLE_r12 1192 -#define _ITER_CHECK_TUPLE_r22 1193 -#define _ITER_CHECK_TUPLE_r33 1194 -#define _ITER_JUMP_LIST_r02 1195 -#define _ITER_JUMP_LIST_r12 1196 -#define _ITER_JUMP_LIST_r22 1197 -#define _ITER_JUMP_LIST_r33 1198 -#define _ITER_JUMP_RANGE_r02 1199 -#define _ITER_JUMP_RANGE_r12 1200 -#define _ITER_JUMP_RANGE_r22 1201 -#define _ITER_JUMP_RANGE_r33 1202 -#define _ITER_JUMP_TUPLE_r02 1203 -#define _ITER_JUMP_TUPLE_r12 1204 -#define _ITER_JUMP_TUPLE_r22 1205 -#define _ITER_JUMP_TUPLE_r33 1206 -#define _ITER_NEXT_LIST_r23 1207 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1208 -#define _ITER_NEXT_RANGE_r03 1209 -#define _ITER_NEXT_RANGE_r13 1210 -#define _ITER_NEXT_RANGE_r23 1211 -#define _ITER_NEXT_TUPLE_r03 1212 -#define _ITER_NEXT_TUPLE_r13 1213 -#define _ITER_NEXT_TUPLE_r23 1214 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1215 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1216 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1217 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1218 -#define _JUMP_TO_TOP_r00 1219 -#define _LIST_APPEND_r10 1220 -#define _LIST_EXTEND_r11 1221 -#define _LOAD_ATTR_r10 1222 -#define _LOAD_ATTR_CLASS_r11 1223 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1224 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1225 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1226 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1227 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1228 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1229 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1230 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1231 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1232 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1233 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1234 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1235 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1236 -#define _LOAD_ATTR_MODULE_r12 1237 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1238 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1239 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1240 -#define _LOAD_ATTR_SLOT_r02 1241 -#define _LOAD_ATTR_SLOT_r12 1242 -#define _LOAD_ATTR_SLOT_r23 1243 -#define _LOAD_ATTR_WITH_HINT_r12 1244 -#define _LOAD_BUILD_CLASS_r01 1245 -#define _LOAD_BYTECODE_r00 1246 -#define _LOAD_COMMON_CONSTANT_r01 1247 -#define _LOAD_COMMON_CONSTANT_r12 1248 -#define _LOAD_COMMON_CONSTANT_r23 1249 -#define _LOAD_CONST_r01 1250 -#define _LOAD_CONST_r12 1251 -#define _LOAD_CONST_r23 1252 -#define _LOAD_CONST_INLINE_r01 1253 -#define _LOAD_CONST_INLINE_r12 1254 -#define _LOAD_CONST_INLINE_r23 1255 -#define _LOAD_CONST_INLINE_BORROW_r01 1256 -#define _LOAD_CONST_INLINE_BORROW_r12 1257 -#define _LOAD_CONST_INLINE_BORROW_r23 1258 -#define _LOAD_CONST_UNDER_INLINE_r02 1259 -#define _LOAD_CONST_UNDER_INLINE_r12 1260 -#define _LOAD_CONST_UNDER_INLINE_r23 1261 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1262 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1263 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1264 -#define _LOAD_DEREF_r01 1265 -#define _LOAD_FAST_r01 1266 -#define _LOAD_FAST_r12 1267 -#define _LOAD_FAST_r23 1268 -#define _LOAD_FAST_0_r01 1269 -#define _LOAD_FAST_0_r12 1270 -#define _LOAD_FAST_0_r23 1271 -#define _LOAD_FAST_1_r01 1272 -#define _LOAD_FAST_1_r12 1273 -#define _LOAD_FAST_1_r23 1274 -#define _LOAD_FAST_2_r01 1275 -#define _LOAD_FAST_2_r12 1276 -#define _LOAD_FAST_2_r23 1277 -#define _LOAD_FAST_3_r01 1278 -#define _LOAD_FAST_3_r12 1279 -#define _LOAD_FAST_3_r23 1280 -#define _LOAD_FAST_4_r01 1281 -#define _LOAD_FAST_4_r12 1282 -#define _LOAD_FAST_4_r23 1283 -#define _LOAD_FAST_5_r01 1284 -#define _LOAD_FAST_5_r12 1285 -#define _LOAD_FAST_5_r23 1286 -#define _LOAD_FAST_6_r01 1287 -#define _LOAD_FAST_6_r12 1288 -#define _LOAD_FAST_6_r23 1289 -#define _LOAD_FAST_7_r01 1290 -#define _LOAD_FAST_7_r12 1291 -#define _LOAD_FAST_7_r23 1292 -#define _LOAD_FAST_AND_CLEAR_r01 1293 -#define _LOAD_FAST_AND_CLEAR_r12 1294 -#define _LOAD_FAST_AND_CLEAR_r23 1295 -#define _LOAD_FAST_BORROW_r01 1296 -#define _LOAD_FAST_BORROW_r12 1297 -#define _LOAD_FAST_BORROW_r23 1298 -#define _LOAD_FAST_BORROW_0_r01 1299 -#define _LOAD_FAST_BORROW_0_r12 1300 -#define _LOAD_FAST_BORROW_0_r23 1301 -#define _LOAD_FAST_BORROW_1_r01 1302 -#define _LOAD_FAST_BORROW_1_r12 1303 -#define _LOAD_FAST_BORROW_1_r23 1304 -#define _LOAD_FAST_BORROW_2_r01 1305 -#define _LOAD_FAST_BORROW_2_r12 1306 -#define _LOAD_FAST_BORROW_2_r23 1307 -#define _LOAD_FAST_BORROW_3_r01 1308 -#define _LOAD_FAST_BORROW_3_r12 1309 -#define _LOAD_FAST_BORROW_3_r23 1310 -#define _LOAD_FAST_BORROW_4_r01 1311 -#define _LOAD_FAST_BORROW_4_r12 1312 -#define _LOAD_FAST_BORROW_4_r23 1313 -#define _LOAD_FAST_BORROW_5_r01 1314 -#define _LOAD_FAST_BORROW_5_r12 1315 -#define _LOAD_FAST_BORROW_5_r23 1316 -#define _LOAD_FAST_BORROW_6_r01 1317 -#define _LOAD_FAST_BORROW_6_r12 1318 -#define _LOAD_FAST_BORROW_6_r23 1319 -#define _LOAD_FAST_BORROW_7_r01 1320 -#define _LOAD_FAST_BORROW_7_r12 1321 -#define _LOAD_FAST_BORROW_7_r23 1322 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1323 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1324 -#define _LOAD_FAST_CHECK_r01 1325 -#define _LOAD_FAST_CHECK_r12 1326 -#define _LOAD_FAST_CHECK_r23 1327 -#define _LOAD_FAST_LOAD_FAST_r02 1328 -#define _LOAD_FAST_LOAD_FAST_r13 1329 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1330 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1331 -#define _LOAD_GLOBAL_r00 1332 -#define _LOAD_GLOBAL_BUILTINS_r01 1333 -#define _LOAD_GLOBAL_MODULE_r01 1334 -#define _LOAD_LOCALS_r01 1335 -#define _LOAD_LOCALS_r12 1336 -#define _LOAD_LOCALS_r23 1337 -#define _LOAD_NAME_r01 1338 -#define _LOAD_SMALL_INT_r01 1339 -#define _LOAD_SMALL_INT_r12 1340 -#define _LOAD_SMALL_INT_r23 1341 -#define _LOAD_SMALL_INT_0_r01 1342 -#define _LOAD_SMALL_INT_0_r12 1343 -#define _LOAD_SMALL_INT_0_r23 1344 -#define _LOAD_SMALL_INT_1_r01 1345 -#define _LOAD_SMALL_INT_1_r12 1346 -#define _LOAD_SMALL_INT_1_r23 1347 -#define _LOAD_SMALL_INT_2_r01 1348 -#define _LOAD_SMALL_INT_2_r12 1349 -#define _LOAD_SMALL_INT_2_r23 1350 -#define _LOAD_SMALL_INT_3_r01 1351 -#define _LOAD_SMALL_INT_3_r12 1352 -#define _LOAD_SMALL_INT_3_r23 1353 -#define _LOAD_SPECIAL_r00 1354 -#define _LOAD_SUPER_ATTR_ATTR_r31 1355 -#define _LOAD_SUPER_ATTR_METHOD_r32 1356 -#define _LOCK_OBJECT_r01 1357 -#define _LOCK_OBJECT_r11 1358 -#define _LOCK_OBJECT_r22 1359 -#define _LOCK_OBJECT_r33 1360 -#define _MAKE_CALLARGS_A_TUPLE_r33 1361 -#define _MAKE_CELL_r00 1362 -#define _MAKE_FUNCTION_r11 1363 -#define _MAKE_HEAP_SAFE_r01 1364 -#define _MAKE_HEAP_SAFE_r11 1365 -#define _MAKE_HEAP_SAFE_r22 1366 -#define _MAKE_HEAP_SAFE_r33 1367 -#define _MAKE_WARM_r00 1368 -#define _MAKE_WARM_r11 1369 -#define _MAKE_WARM_r22 1370 -#define _MAKE_WARM_r33 1371 -#define _MAP_ADD_r20 1372 -#define _MATCH_CLASS_r33 1373 -#define _MATCH_KEYS_r23 1374 -#define _MATCH_MAPPING_r02 1375 -#define _MATCH_MAPPING_r12 1376 -#define _MATCH_MAPPING_r23 1377 -#define _MATCH_SEQUENCE_r02 1378 -#define _MATCH_SEQUENCE_r12 1379 -#define _MATCH_SEQUENCE_r23 1380 -#define _MAYBE_EXPAND_METHOD_r00 1381 -#define _MAYBE_EXPAND_METHOD_KW_r11 1382 -#define _MONITOR_CALL_r00 1383 -#define _MONITOR_CALL_KW_r11 1384 -#define _MONITOR_JUMP_BACKWARD_r00 1385 -#define _MONITOR_JUMP_BACKWARD_r11 1386 -#define _MONITOR_JUMP_BACKWARD_r22 1387 -#define _MONITOR_JUMP_BACKWARD_r33 1388 -#define _MONITOR_RESUME_r00 1389 -#define _NOP_r00 1390 -#define _NOP_r11 1391 -#define _NOP_r22 1392 -#define _NOP_r33 1393 -#define _POP_CALL_r20 1394 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1395 -#define _POP_CALL_ONE_r30 1396 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1397 -#define _POP_CALL_TWO_r30 1398 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1399 -#define _POP_EXCEPT_r10 1400 -#define _POP_ITER_r20 1401 -#define _POP_JUMP_IF_FALSE_r00 1402 -#define _POP_JUMP_IF_FALSE_r10 1403 -#define _POP_JUMP_IF_FALSE_r21 1404 -#define _POP_JUMP_IF_FALSE_r32 1405 -#define _POP_JUMP_IF_TRUE_r00 1406 -#define _POP_JUMP_IF_TRUE_r10 1407 -#define _POP_JUMP_IF_TRUE_r21 1408 -#define _POP_JUMP_IF_TRUE_r32 1409 -#define _POP_TOP_r10 1410 -#define _POP_TOP_FLOAT_r00 1411 -#define _POP_TOP_FLOAT_r10 1412 -#define _POP_TOP_FLOAT_r21 1413 -#define _POP_TOP_FLOAT_r32 1414 -#define _POP_TOP_INT_r00 1415 -#define _POP_TOP_INT_r10 1416 -#define _POP_TOP_INT_r21 1417 -#define _POP_TOP_INT_r32 1418 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1419 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1420 -#define _POP_TOP_NOP_r00 1421 -#define _POP_TOP_NOP_r10 1422 -#define _POP_TOP_NOP_r21 1423 -#define _POP_TOP_NOP_r32 1424 -#define _POP_TOP_UNICODE_r00 1425 -#define _POP_TOP_UNICODE_r10 1426 -#define _POP_TOP_UNICODE_r21 1427 -#define _POP_TOP_UNICODE_r32 1428 -#define _POP_TWO_r20 1429 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1430 -#define _PUSH_EXC_INFO_r02 1431 -#define _PUSH_EXC_INFO_r12 1432 -#define _PUSH_EXC_INFO_r23 1433 -#define _PUSH_FRAME_r10 1434 -#define _PUSH_NULL_r01 1435 -#define _PUSH_NULL_r12 1436 -#define _PUSH_NULL_r23 1437 -#define _PUSH_NULL_CONDITIONAL_r00 1438 -#define _PY_FRAME_EX_r31 1439 -#define _PY_FRAME_GENERAL_r01 1440 -#define _PY_FRAME_KW_r11 1441 -#define _REPLACE_WITH_TRUE_r02 1442 -#define _REPLACE_WITH_TRUE_r12 1443 -#define _REPLACE_WITH_TRUE_r23 1444 -#define _RESUME_CHECK_r00 1445 -#define _RESUME_CHECK_r11 1446 -#define _RESUME_CHECK_r22 1447 -#define _RESUME_CHECK_r33 1448 -#define _RETURN_GENERATOR_r01 1449 -#define _RETURN_VALUE_r11 1450 -#define _SAVE_RETURN_OFFSET_r00 1451 -#define _SAVE_RETURN_OFFSET_r11 1452 -#define _SAVE_RETURN_OFFSET_r22 1453 -#define _SAVE_RETURN_OFFSET_r33 1454 -#define _SEND_r33 1455 -#define _SEND_GEN_FRAME_r33 1456 -#define _SETUP_ANNOTATIONS_r00 1457 -#define _SET_ADD_r10 1458 -#define _SET_FUNCTION_ATTRIBUTE_r01 1459 -#define _SET_FUNCTION_ATTRIBUTE_r11 1460 -#define _SET_FUNCTION_ATTRIBUTE_r21 1461 -#define _SET_FUNCTION_ATTRIBUTE_r32 1462 -#define _SET_IP_r00 1463 -#define _SET_IP_r11 1464 -#define _SET_IP_r22 1465 -#define _SET_IP_r33 1466 -#define _SET_UPDATE_r11 1467 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1468 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1469 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1470 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1471 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1472 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1473 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1474 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1475 -#define _SPILL_OR_RELOAD_r01 1476 -#define _SPILL_OR_RELOAD_r02 1477 -#define _SPILL_OR_RELOAD_r03 1478 -#define _SPILL_OR_RELOAD_r10 1479 -#define _SPILL_OR_RELOAD_r12 1480 -#define _SPILL_OR_RELOAD_r13 1481 -#define _SPILL_OR_RELOAD_r20 1482 -#define _SPILL_OR_RELOAD_r21 1483 -#define _SPILL_OR_RELOAD_r23 1484 -#define _SPILL_OR_RELOAD_r30 1485 -#define _SPILL_OR_RELOAD_r31 1486 -#define _SPILL_OR_RELOAD_r32 1487 -#define _START_EXECUTOR_r00 1488 -#define _STORE_ATTR_r20 1489 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1490 -#define _STORE_ATTR_SLOT_r21 1491 -#define _STORE_ATTR_WITH_HINT_r21 1492 -#define _STORE_DEREF_r10 1493 -#define _STORE_FAST_LOAD_FAST_r11 1494 -#define _STORE_FAST_STORE_FAST_r20 1495 -#define _STORE_GLOBAL_r10 1496 -#define _STORE_NAME_r10 1497 -#define _STORE_SLICE_r30 1498 -#define _STORE_SUBSCR_r30 1499 -#define _STORE_SUBSCR_DICT_r31 1500 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1501 -#define _STORE_SUBSCR_LIST_INT_r32 1502 -#define _SWAP_r11 1503 -#define _SWAP_2_r02 1504 -#define _SWAP_2_r12 1505 -#define _SWAP_2_r22 1506 -#define _SWAP_2_r33 1507 -#define _SWAP_3_r03 1508 -#define _SWAP_3_r13 1509 -#define _SWAP_3_r23 1510 -#define _SWAP_3_r33 1511 -#define _SWAP_FAST_r01 1512 -#define _SWAP_FAST_r11 1513 -#define _SWAP_FAST_r22 1514 -#define _SWAP_FAST_r33 1515 -#define _SWAP_FAST_0_r01 1516 -#define _SWAP_FAST_0_r11 1517 -#define _SWAP_FAST_0_r22 1518 -#define _SWAP_FAST_0_r33 1519 -#define _SWAP_FAST_1_r01 1520 -#define _SWAP_FAST_1_r11 1521 -#define _SWAP_FAST_1_r22 1522 -#define _SWAP_FAST_1_r33 1523 -#define _SWAP_FAST_2_r01 1524 -#define _SWAP_FAST_2_r11 1525 -#define _SWAP_FAST_2_r22 1526 -#define _SWAP_FAST_2_r33 1527 -#define _SWAP_FAST_3_r01 1528 -#define _SWAP_FAST_3_r11 1529 -#define _SWAP_FAST_3_r22 1530 -#define _SWAP_FAST_3_r33 1531 -#define _SWAP_FAST_4_r01 1532 -#define _SWAP_FAST_4_r11 1533 -#define _SWAP_FAST_4_r22 1534 -#define _SWAP_FAST_4_r33 1535 -#define _SWAP_FAST_5_r01 1536 -#define _SWAP_FAST_5_r11 1537 -#define _SWAP_FAST_5_r22 1538 -#define _SWAP_FAST_5_r33 1539 -#define _SWAP_FAST_6_r01 1540 -#define _SWAP_FAST_6_r11 1541 -#define _SWAP_FAST_6_r22 1542 -#define _SWAP_FAST_6_r33 1543 -#define _SWAP_FAST_7_r01 1544 -#define _SWAP_FAST_7_r11 1545 -#define _SWAP_FAST_7_r22 1546 -#define _SWAP_FAST_7_r33 1547 -#define _TIER2_RESUME_CHECK_r00 1548 -#define _TIER2_RESUME_CHECK_r11 1549 -#define _TIER2_RESUME_CHECK_r22 1550 -#define _TIER2_RESUME_CHECK_r33 1551 -#define _TO_BOOL_r11 1552 -#define _TO_BOOL_BOOL_r01 1553 -#define _TO_BOOL_BOOL_r11 1554 -#define _TO_BOOL_BOOL_r22 1555 -#define _TO_BOOL_BOOL_r33 1556 -#define _TO_BOOL_INT_r02 1557 -#define _TO_BOOL_INT_r12 1558 -#define _TO_BOOL_INT_r23 1559 -#define _TO_BOOL_LIST_r02 1560 -#define _TO_BOOL_LIST_r12 1561 -#define _TO_BOOL_LIST_r23 1562 -#define _TO_BOOL_NONE_r01 1563 -#define _TO_BOOL_NONE_r11 1564 -#define _TO_BOOL_NONE_r22 1565 -#define _TO_BOOL_NONE_r33 1566 -#define _TO_BOOL_STR_r02 1567 -#define _TO_BOOL_STR_r12 1568 -#define _TO_BOOL_STR_r23 1569 -#define _TRACE_RECORD_r00 1570 -#define _UNARY_INVERT_r12 1571 -#define _UNARY_NEGATIVE_r12 1572 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1573 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1574 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1575 -#define _UNARY_NOT_r01 1576 -#define _UNARY_NOT_r11 1577 -#define _UNARY_NOT_r22 1578 -#define _UNARY_NOT_r33 1579 -#define _UNPACK_EX_r10 1580 -#define _UNPACK_SEQUENCE_r10 1581 -#define _UNPACK_SEQUENCE_LIST_r10 1582 -#define _UNPACK_SEQUENCE_TUPLE_r10 1583 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1584 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1585 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1586 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1587 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1588 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1589 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1590 -#define _WITH_EXCEPT_START_r33 1591 -#define _YIELD_VALUE_r11 1592 -#define MAX_UOP_REGS_ID 1592 +#define _YIELD_VALUE 638 +#define MAX_UOP_ID 638 +#define _BINARY_OP_r23 639 +#define _BINARY_OP_ADD_FLOAT_r03 640 +#define _BINARY_OP_ADD_FLOAT_r13 641 +#define _BINARY_OP_ADD_FLOAT_r23 642 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 643 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 644 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 645 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 646 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 647 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 648 +#define _BINARY_OP_ADD_INT_r03 649 +#define _BINARY_OP_ADD_INT_r13 650 +#define _BINARY_OP_ADD_INT_r23 651 +#define _BINARY_OP_ADD_INT_INPLACE_r03 652 +#define _BINARY_OP_ADD_INT_INPLACE_r13 653 +#define _BINARY_OP_ADD_INT_INPLACE_r23 654 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 655 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 656 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 657 +#define _BINARY_OP_ADD_UNICODE_r03 658 +#define _BINARY_OP_ADD_UNICODE_r13 659 +#define _BINARY_OP_ADD_UNICODE_r23 660 +#define _BINARY_OP_EXTEND_r23 661 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 662 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 663 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 664 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 665 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 666 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 667 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 668 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 669 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 670 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 671 +#define _BINARY_OP_MULTIPLY_INT_r03 672 +#define _BINARY_OP_MULTIPLY_INT_r13 673 +#define _BINARY_OP_MULTIPLY_INT_r23 674 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 675 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 676 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 677 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 678 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 679 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 680 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 681 +#define _BINARY_OP_SUBSCR_DICT_r23 682 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 683 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 684 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 685 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 686 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 687 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 688 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 689 +#define _BINARY_OP_SUBSCR_STR_INT_r23 690 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 691 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 692 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 693 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 694 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 695 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 696 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 697 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 698 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 699 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 700 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 701 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 702 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 703 +#define _BINARY_OP_SUBTRACT_INT_r03 704 +#define _BINARY_OP_SUBTRACT_INT_r13 705 +#define _BINARY_OP_SUBTRACT_INT_r23 706 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 707 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 708 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 709 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 710 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 711 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 712 +#define _BINARY_SLICE_r31 713 +#define _BUILD_INTERPOLATION_r01 714 +#define _BUILD_LIST_r01 715 +#define _BUILD_MAP_r01 716 +#define _BUILD_SET_r01 717 +#define _BUILD_SLICE_r01 718 +#define _BUILD_STRING_r01 719 +#define _BUILD_TEMPLATE_r21 720 +#define _BUILD_TUPLE_r01 721 +#define _CALL_BUILTIN_CLASS_r01 722 +#define _CALL_BUILTIN_FAST_r01 723 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 724 +#define _CALL_BUILTIN_O_r03 725 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 726 +#define _CALL_INTRINSIC_1_r12 727 +#define _CALL_INTRINSIC_2_r23 728 +#define _CALL_ISINSTANCE_r31 729 +#define _CALL_KW_NON_PY_r11 730 +#define _CALL_LEN_r33 731 +#define _CALL_LIST_APPEND_r03 732 +#define _CALL_LIST_APPEND_r13 733 +#define _CALL_LIST_APPEND_r23 734 +#define _CALL_LIST_APPEND_r33 735 +#define _CALL_METHOD_DESCRIPTOR_FAST_r01 736 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r01 737 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 738 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r01 739 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 740 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r01 741 +#define _CALL_METHOD_DESCRIPTOR_O_r03 742 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 743 +#define _CALL_NON_PY_GENERAL_r01 744 +#define _CALL_STR_1_r32 745 +#define _CALL_TUPLE_1_r32 746 +#define _CALL_TYPE_1_r02 747 +#define _CALL_TYPE_1_r12 748 +#define _CALL_TYPE_1_r22 749 +#define _CALL_TYPE_1_r32 750 +#define _CHECK_AND_ALLOCATE_OBJECT_r00 751 +#define _CHECK_ATTR_CLASS_r01 752 +#define _CHECK_ATTR_CLASS_r11 753 +#define _CHECK_ATTR_CLASS_r22 754 +#define _CHECK_ATTR_CLASS_r33 755 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 756 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 757 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 758 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 759 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 760 +#define _CHECK_EG_MATCH_r22 761 +#define _CHECK_EXC_MATCH_r22 762 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 763 +#define _CHECK_FUNCTION_VERSION_r00 764 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 765 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 766 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 767 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 768 +#define _CHECK_FUNCTION_VERSION_KW_r11 769 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 770 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 771 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 772 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 773 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 774 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 775 +#define _CHECK_IS_PY_CALLABLE_EX_r03 776 +#define _CHECK_IS_PY_CALLABLE_EX_r13 777 +#define _CHECK_IS_PY_CALLABLE_EX_r23 778 +#define _CHECK_IS_PY_CALLABLE_EX_r33 779 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 780 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 781 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 782 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 783 +#define _CHECK_METHOD_VERSION_r00 784 +#define _CHECK_METHOD_VERSION_KW_r11 785 +#define _CHECK_PEP_523_r00 786 +#define _CHECK_PEP_523_r11 787 +#define _CHECK_PEP_523_r22 788 +#define _CHECK_PEP_523_r33 789 +#define _CHECK_PERIODIC_r00 790 +#define _CHECK_PERIODIC_AT_END_r00 791 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 792 +#define _CHECK_RECURSION_LIMIT_r00 793 +#define _CHECK_RECURSION_LIMIT_r11 794 +#define _CHECK_RECURSION_LIMIT_r22 795 +#define _CHECK_RECURSION_LIMIT_r33 796 +#define _CHECK_RECURSION_REMAINING_r00 797 +#define _CHECK_RECURSION_REMAINING_r11 798 +#define _CHECK_RECURSION_REMAINING_r22 799 +#define _CHECK_RECURSION_REMAINING_r33 800 +#define _CHECK_STACK_SPACE_r00 801 +#define _CHECK_STACK_SPACE_OPERAND_r00 802 +#define _CHECK_STACK_SPACE_OPERAND_r11 803 +#define _CHECK_STACK_SPACE_OPERAND_r22 804 +#define _CHECK_STACK_SPACE_OPERAND_r33 805 +#define _CHECK_VALIDITY_r00 806 +#define _CHECK_VALIDITY_r11 807 +#define _CHECK_VALIDITY_r22 808 +#define _CHECK_VALIDITY_r33 809 +#define _COLD_DYNAMIC_EXIT_r00 810 +#define _COLD_EXIT_r00 811 +#define _COMPARE_OP_r21 812 +#define _COMPARE_OP_FLOAT_r03 813 +#define _COMPARE_OP_FLOAT_r13 814 +#define _COMPARE_OP_FLOAT_r23 815 +#define _COMPARE_OP_INT_r23 816 +#define _COMPARE_OP_STR_r23 817 +#define _CONTAINS_OP_r23 818 +#define _CONTAINS_OP_DICT_r23 819 +#define _CONTAINS_OP_SET_r23 820 +#define _CONVERT_VALUE_r11 821 +#define _COPY_r01 822 +#define _COPY_1_r02 823 +#define _COPY_1_r12 824 +#define _COPY_1_r23 825 +#define _COPY_2_r03 826 +#define _COPY_2_r13 827 +#define _COPY_2_r23 828 +#define _COPY_3_r03 829 +#define _COPY_3_r13 830 +#define _COPY_3_r23 831 +#define _COPY_3_r33 832 +#define _COPY_FREE_VARS_r00 833 +#define _COPY_FREE_VARS_r11 834 +#define _COPY_FREE_VARS_r22 835 +#define _COPY_FREE_VARS_r33 836 +#define _CREATE_INIT_FRAME_r01 837 +#define _DELETE_ATTR_r10 838 +#define _DELETE_DEREF_r00 839 +#define _DELETE_FAST_r00 840 +#define _DELETE_GLOBAL_r00 841 +#define _DELETE_NAME_r00 842 +#define _DELETE_SUBSCR_r20 843 +#define _DEOPT_r00 844 +#define _DEOPT_r10 845 +#define _DEOPT_r20 846 +#define _DEOPT_r30 847 +#define _DICT_MERGE_r11 848 +#define _DICT_UPDATE_r11 849 +#define _DO_CALL_r01 850 +#define _DO_CALL_FUNCTION_EX_r31 851 +#define _DO_CALL_KW_r11 852 +#define _DYNAMIC_EXIT_r00 853 +#define _DYNAMIC_EXIT_r10 854 +#define _DYNAMIC_EXIT_r20 855 +#define _DYNAMIC_EXIT_r30 856 +#define _END_FOR_r10 857 +#define _END_SEND_r31 858 +#define _ERROR_POP_N_r00 859 +#define _EXIT_INIT_CHECK_r10 860 +#define _EXIT_TRACE_r00 861 +#define _EXIT_TRACE_r10 862 +#define _EXIT_TRACE_r20 863 +#define _EXIT_TRACE_r30 864 +#define _EXPAND_METHOD_r00 865 +#define _EXPAND_METHOD_KW_r11 866 +#define _FATAL_ERROR_r00 867 +#define _FATAL_ERROR_r11 868 +#define _FATAL_ERROR_r22 869 +#define _FATAL_ERROR_r33 870 +#define _FORMAT_SIMPLE_r11 871 +#define _FORMAT_WITH_SPEC_r21 872 +#define _FOR_ITER_r23 873 +#define _FOR_ITER_GEN_FRAME_r03 874 +#define _FOR_ITER_GEN_FRAME_r13 875 +#define _FOR_ITER_GEN_FRAME_r23 876 +#define _FOR_ITER_TIER_TWO_r23 877 +#define _GET_AITER_r11 878 +#define _GET_ANEXT_r12 879 +#define _GET_AWAITABLE_r11 880 +#define _GET_ITER_r12 881 +#define _GET_LEN_r12 882 +#define _GUARD_BINARY_OP_EXTEND_r22 883 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 884 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 885 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 886 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 887 +#define _GUARD_BIT_IS_SET_POP_r00 888 +#define _GUARD_BIT_IS_SET_POP_r10 889 +#define _GUARD_BIT_IS_SET_POP_r21 890 +#define _GUARD_BIT_IS_SET_POP_r32 891 +#define _GUARD_BIT_IS_SET_POP_4_r00 892 +#define _GUARD_BIT_IS_SET_POP_4_r10 893 +#define _GUARD_BIT_IS_SET_POP_4_r21 894 +#define _GUARD_BIT_IS_SET_POP_4_r32 895 +#define _GUARD_BIT_IS_SET_POP_5_r00 896 +#define _GUARD_BIT_IS_SET_POP_5_r10 897 +#define _GUARD_BIT_IS_SET_POP_5_r21 898 +#define _GUARD_BIT_IS_SET_POP_5_r32 899 +#define _GUARD_BIT_IS_SET_POP_6_r00 900 +#define _GUARD_BIT_IS_SET_POP_6_r10 901 +#define _GUARD_BIT_IS_SET_POP_6_r21 902 +#define _GUARD_BIT_IS_SET_POP_6_r32 903 +#define _GUARD_BIT_IS_SET_POP_7_r00 904 +#define _GUARD_BIT_IS_SET_POP_7_r10 905 +#define _GUARD_BIT_IS_SET_POP_7_r21 906 +#define _GUARD_BIT_IS_SET_POP_7_r32 907 +#define _GUARD_BIT_IS_UNSET_POP_r00 908 +#define _GUARD_BIT_IS_UNSET_POP_r10 909 +#define _GUARD_BIT_IS_UNSET_POP_r21 910 +#define _GUARD_BIT_IS_UNSET_POP_r32 911 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 912 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 913 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 914 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 915 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 916 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 917 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 918 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 919 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 920 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 921 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 922 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 923 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 924 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 925 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 926 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 927 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 928 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 929 +#define _GUARD_CALLABLE_BUILTIN_O_r00 930 +#define _GUARD_CALLABLE_ISINSTANCE_r03 931 +#define _GUARD_CALLABLE_ISINSTANCE_r13 932 +#define _GUARD_CALLABLE_ISINSTANCE_r23 933 +#define _GUARD_CALLABLE_ISINSTANCE_r33 934 +#define _GUARD_CALLABLE_LEN_r03 935 +#define _GUARD_CALLABLE_LEN_r13 936 +#define _GUARD_CALLABLE_LEN_r23 937 +#define _GUARD_CALLABLE_LEN_r33 938 +#define _GUARD_CALLABLE_LIST_APPEND_r03 939 +#define _GUARD_CALLABLE_LIST_APPEND_r13 940 +#define _GUARD_CALLABLE_LIST_APPEND_r23 941 +#define _GUARD_CALLABLE_LIST_APPEND_r33 942 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 943 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 944 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 945 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 946 +#define _GUARD_CALLABLE_STR_1_r03 947 +#define _GUARD_CALLABLE_STR_1_r13 948 +#define _GUARD_CALLABLE_STR_1_r23 949 +#define _GUARD_CALLABLE_STR_1_r33 950 +#define _GUARD_CALLABLE_TUPLE_1_r03 951 +#define _GUARD_CALLABLE_TUPLE_1_r13 952 +#define _GUARD_CALLABLE_TUPLE_1_r23 953 +#define _GUARD_CALLABLE_TUPLE_1_r33 954 +#define _GUARD_CALLABLE_TYPE_1_r03 955 +#define _GUARD_CALLABLE_TYPE_1_r13 956 +#define _GUARD_CALLABLE_TYPE_1_r23 957 +#define _GUARD_CALLABLE_TYPE_1_r33 958 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 959 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 960 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 961 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 962 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 963 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 964 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 965 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 966 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 967 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 968 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 969 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 970 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 971 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 972 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 973 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 974 +#define _GUARD_DORV_NO_DICT_r01 975 +#define _GUARD_DORV_NO_DICT_r11 976 +#define _GUARD_DORV_NO_DICT_r22 977 +#define _GUARD_DORV_NO_DICT_r33 978 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 979 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 980 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 981 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 982 +#define _GUARD_GLOBALS_VERSION_r00 983 +#define _GUARD_GLOBALS_VERSION_r11 984 +#define _GUARD_GLOBALS_VERSION_r22 985 +#define _GUARD_GLOBALS_VERSION_r33 986 +#define _GUARD_IP_RETURN_GENERATOR_r00 987 +#define _GUARD_IP_RETURN_GENERATOR_r11 988 +#define _GUARD_IP_RETURN_GENERATOR_r22 989 +#define _GUARD_IP_RETURN_GENERATOR_r33 990 +#define _GUARD_IP_RETURN_VALUE_r00 991 +#define _GUARD_IP_RETURN_VALUE_r11 992 +#define _GUARD_IP_RETURN_VALUE_r22 993 +#define _GUARD_IP_RETURN_VALUE_r33 994 +#define _GUARD_IP_YIELD_VALUE_r00 995 +#define _GUARD_IP_YIELD_VALUE_r11 996 +#define _GUARD_IP_YIELD_VALUE_r22 997 +#define _GUARD_IP_YIELD_VALUE_r33 998 +#define _GUARD_IP__PUSH_FRAME_r00 999 +#define _GUARD_IP__PUSH_FRAME_r11 1000 +#define _GUARD_IP__PUSH_FRAME_r22 1001 +#define _GUARD_IP__PUSH_FRAME_r33 1002 +#define _GUARD_IS_FALSE_POP_r00 1003 +#define _GUARD_IS_FALSE_POP_r10 1004 +#define _GUARD_IS_FALSE_POP_r21 1005 +#define _GUARD_IS_FALSE_POP_r32 1006 +#define _GUARD_IS_NONE_POP_r00 1007 +#define _GUARD_IS_NONE_POP_r10 1008 +#define _GUARD_IS_NONE_POP_r21 1009 +#define _GUARD_IS_NONE_POP_r32 1010 +#define _GUARD_IS_NOT_NONE_POP_r10 1011 +#define _GUARD_IS_TRUE_POP_r00 1012 +#define _GUARD_IS_TRUE_POP_r10 1013 +#define _GUARD_IS_TRUE_POP_r21 1014 +#define _GUARD_IS_TRUE_POP_r32 1015 +#define _GUARD_KEYS_VERSION_r01 1016 +#define _GUARD_KEYS_VERSION_r11 1017 +#define _GUARD_KEYS_VERSION_r22 1018 +#define _GUARD_KEYS_VERSION_r33 1019 +#define _GUARD_NOS_ANY_DICT_r02 1020 +#define _GUARD_NOS_ANY_DICT_r12 1021 +#define _GUARD_NOS_ANY_DICT_r22 1022 +#define _GUARD_NOS_ANY_DICT_r33 1023 +#define _GUARD_NOS_COMPACT_ASCII_r02 1024 +#define _GUARD_NOS_COMPACT_ASCII_r12 1025 +#define _GUARD_NOS_COMPACT_ASCII_r22 1026 +#define _GUARD_NOS_COMPACT_ASCII_r33 1027 +#define _GUARD_NOS_DICT_r02 1028 +#define _GUARD_NOS_DICT_r12 1029 +#define _GUARD_NOS_DICT_r22 1030 +#define _GUARD_NOS_DICT_r33 1031 +#define _GUARD_NOS_FLOAT_r02 1032 +#define _GUARD_NOS_FLOAT_r12 1033 +#define _GUARD_NOS_FLOAT_r22 1034 +#define _GUARD_NOS_FLOAT_r33 1035 +#define _GUARD_NOS_INT_r02 1036 +#define _GUARD_NOS_INT_r12 1037 +#define _GUARD_NOS_INT_r22 1038 +#define _GUARD_NOS_INT_r33 1039 +#define _GUARD_NOS_LIST_r02 1040 +#define _GUARD_NOS_LIST_r12 1041 +#define _GUARD_NOS_LIST_r22 1042 +#define _GUARD_NOS_LIST_r33 1043 +#define _GUARD_NOS_NOT_NULL_r02 1044 +#define _GUARD_NOS_NOT_NULL_r12 1045 +#define _GUARD_NOS_NOT_NULL_r22 1046 +#define _GUARD_NOS_NOT_NULL_r33 1047 +#define _GUARD_NOS_NULL_r02 1048 +#define _GUARD_NOS_NULL_r12 1049 +#define _GUARD_NOS_NULL_r22 1050 +#define _GUARD_NOS_NULL_r33 1051 +#define _GUARD_NOS_OVERFLOWED_r02 1052 +#define _GUARD_NOS_OVERFLOWED_r12 1053 +#define _GUARD_NOS_OVERFLOWED_r22 1054 +#define _GUARD_NOS_OVERFLOWED_r33 1055 +#define _GUARD_NOS_TUPLE_r02 1056 +#define _GUARD_NOS_TUPLE_r12 1057 +#define _GUARD_NOS_TUPLE_r22 1058 +#define _GUARD_NOS_TUPLE_r33 1059 +#define _GUARD_NOS_UNICODE_r02 1060 +#define _GUARD_NOS_UNICODE_r12 1061 +#define _GUARD_NOS_UNICODE_r22 1062 +#define _GUARD_NOS_UNICODE_r33 1063 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1064 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1065 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1066 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1067 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1068 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1069 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1070 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1071 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1072 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1073 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1074 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1075 +#define _GUARD_THIRD_NULL_r03 1076 +#define _GUARD_THIRD_NULL_r13 1077 +#define _GUARD_THIRD_NULL_r23 1078 +#define _GUARD_THIRD_NULL_r33 1079 +#define _GUARD_TOS_ANY_DICT_r01 1080 +#define _GUARD_TOS_ANY_DICT_r11 1081 +#define _GUARD_TOS_ANY_DICT_r22 1082 +#define _GUARD_TOS_ANY_DICT_r33 1083 +#define _GUARD_TOS_ANY_SET_r01 1084 +#define _GUARD_TOS_ANY_SET_r11 1085 +#define _GUARD_TOS_ANY_SET_r22 1086 +#define _GUARD_TOS_ANY_SET_r33 1087 +#define _GUARD_TOS_DICT_r01 1088 +#define _GUARD_TOS_DICT_r11 1089 +#define _GUARD_TOS_DICT_r22 1090 +#define _GUARD_TOS_DICT_r33 1091 +#define _GUARD_TOS_FLOAT_r01 1092 +#define _GUARD_TOS_FLOAT_r11 1093 +#define _GUARD_TOS_FLOAT_r22 1094 +#define _GUARD_TOS_FLOAT_r33 1095 +#define _GUARD_TOS_FROZENDICT_r01 1096 +#define _GUARD_TOS_FROZENDICT_r11 1097 +#define _GUARD_TOS_FROZENDICT_r22 1098 +#define _GUARD_TOS_FROZENDICT_r33 1099 +#define _GUARD_TOS_FROZENSET_r01 1100 +#define _GUARD_TOS_FROZENSET_r11 1101 +#define _GUARD_TOS_FROZENSET_r22 1102 +#define _GUARD_TOS_FROZENSET_r33 1103 +#define _GUARD_TOS_INT_r01 1104 +#define _GUARD_TOS_INT_r11 1105 +#define _GUARD_TOS_INT_r22 1106 +#define _GUARD_TOS_INT_r33 1107 +#define _GUARD_TOS_LIST_r01 1108 +#define _GUARD_TOS_LIST_r11 1109 +#define _GUARD_TOS_LIST_r22 1110 +#define _GUARD_TOS_LIST_r33 1111 +#define _GUARD_TOS_OVERFLOWED_r01 1112 +#define _GUARD_TOS_OVERFLOWED_r11 1113 +#define _GUARD_TOS_OVERFLOWED_r22 1114 +#define _GUARD_TOS_OVERFLOWED_r33 1115 +#define _GUARD_TOS_SET_r01 1116 +#define _GUARD_TOS_SET_r11 1117 +#define _GUARD_TOS_SET_r22 1118 +#define _GUARD_TOS_SET_r33 1119 +#define _GUARD_TOS_SLICE_r01 1120 +#define _GUARD_TOS_SLICE_r11 1121 +#define _GUARD_TOS_SLICE_r22 1122 +#define _GUARD_TOS_SLICE_r33 1123 +#define _GUARD_TOS_TUPLE_r01 1124 +#define _GUARD_TOS_TUPLE_r11 1125 +#define _GUARD_TOS_TUPLE_r22 1126 +#define _GUARD_TOS_TUPLE_r33 1127 +#define _GUARD_TOS_UNICODE_r01 1128 +#define _GUARD_TOS_UNICODE_r11 1129 +#define _GUARD_TOS_UNICODE_r22 1130 +#define _GUARD_TOS_UNICODE_r33 1131 +#define _GUARD_TYPE_VERSION_r01 1132 +#define _GUARD_TYPE_VERSION_r11 1133 +#define _GUARD_TYPE_VERSION_r22 1134 +#define _GUARD_TYPE_VERSION_r33 1135 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1136 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1137 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1138 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1139 +#define _HANDLE_PENDING_AND_DEOPT_r00 1140 +#define _HANDLE_PENDING_AND_DEOPT_r10 1141 +#define _HANDLE_PENDING_AND_DEOPT_r20 1142 +#define _HANDLE_PENDING_AND_DEOPT_r30 1143 +#define _IMPORT_FROM_r12 1144 +#define _IMPORT_NAME_r21 1145 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1146 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1147 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1148 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1149 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1150 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1151 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1152 +#define _INSERT_1_LOAD_CONST_INLINE_r02 1153 +#define _INSERT_1_LOAD_CONST_INLINE_r12 1154 +#define _INSERT_1_LOAD_CONST_INLINE_r23 1155 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1156 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1157 +#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1158 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1159 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1160 +#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1161 +#define _INSERT_NULL_r10 1162 +#define _INSTRUMENTED_FOR_ITER_r23 1163 +#define _INSTRUMENTED_INSTRUCTION_r00 1164 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1165 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1166 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1167 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1168 +#define _INSTRUMENTED_LINE_r00 1169 +#define _INSTRUMENTED_NOT_TAKEN_r00 1170 +#define _INSTRUMENTED_NOT_TAKEN_r11 1171 +#define _INSTRUMENTED_NOT_TAKEN_r22 1172 +#define _INSTRUMENTED_NOT_TAKEN_r33 1173 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1174 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1175 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1176 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1177 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1178 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1179 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1180 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1181 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1182 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1183 +#define _IS_NONE_r11 1184 +#define _IS_OP_r03 1185 +#define _IS_OP_r13 1186 +#define _IS_OP_r23 1187 +#define _ITER_CHECK_LIST_r02 1188 +#define _ITER_CHECK_LIST_r12 1189 +#define _ITER_CHECK_LIST_r22 1190 +#define _ITER_CHECK_LIST_r33 1191 +#define _ITER_CHECK_RANGE_r02 1192 +#define _ITER_CHECK_RANGE_r12 1193 +#define _ITER_CHECK_RANGE_r22 1194 +#define _ITER_CHECK_RANGE_r33 1195 +#define _ITER_CHECK_TUPLE_r02 1196 +#define _ITER_CHECK_TUPLE_r12 1197 +#define _ITER_CHECK_TUPLE_r22 1198 +#define _ITER_CHECK_TUPLE_r33 1199 +#define _ITER_JUMP_LIST_r02 1200 +#define _ITER_JUMP_LIST_r12 1201 +#define _ITER_JUMP_LIST_r22 1202 +#define _ITER_JUMP_LIST_r33 1203 +#define _ITER_JUMP_RANGE_r02 1204 +#define _ITER_JUMP_RANGE_r12 1205 +#define _ITER_JUMP_RANGE_r22 1206 +#define _ITER_JUMP_RANGE_r33 1207 +#define _ITER_JUMP_TUPLE_r02 1208 +#define _ITER_JUMP_TUPLE_r12 1209 +#define _ITER_JUMP_TUPLE_r22 1210 +#define _ITER_JUMP_TUPLE_r33 1211 +#define _ITER_NEXT_LIST_r23 1212 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1213 +#define _ITER_NEXT_RANGE_r03 1214 +#define _ITER_NEXT_RANGE_r13 1215 +#define _ITER_NEXT_RANGE_r23 1216 +#define _ITER_NEXT_TUPLE_r03 1217 +#define _ITER_NEXT_TUPLE_r13 1218 +#define _ITER_NEXT_TUPLE_r23 1219 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1220 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1221 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1222 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1223 +#define _JUMP_TO_TOP_r00 1224 +#define _LIST_APPEND_r10 1225 +#define _LIST_EXTEND_r11 1226 +#define _LOAD_ATTR_r10 1227 +#define _LOAD_ATTR_CLASS_r11 1228 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1229 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1230 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1231 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1232 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1233 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1234 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1235 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1236 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1237 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1238 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1239 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1240 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1241 +#define _LOAD_ATTR_MODULE_r12 1242 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1243 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1244 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1245 +#define _LOAD_ATTR_SLOT_r02 1246 +#define _LOAD_ATTR_SLOT_r12 1247 +#define _LOAD_ATTR_SLOT_r23 1248 +#define _LOAD_ATTR_WITH_HINT_r12 1249 +#define _LOAD_BUILD_CLASS_r01 1250 +#define _LOAD_BYTECODE_r00 1251 +#define _LOAD_COMMON_CONSTANT_r01 1252 +#define _LOAD_COMMON_CONSTANT_r12 1253 +#define _LOAD_COMMON_CONSTANT_r23 1254 +#define _LOAD_CONST_r01 1255 +#define _LOAD_CONST_r12 1256 +#define _LOAD_CONST_r23 1257 +#define _LOAD_CONST_INLINE_r01 1258 +#define _LOAD_CONST_INLINE_r12 1259 +#define _LOAD_CONST_INLINE_r23 1260 +#define _LOAD_CONST_INLINE_BORROW_r01 1261 +#define _LOAD_CONST_INLINE_BORROW_r12 1262 +#define _LOAD_CONST_INLINE_BORROW_r23 1263 +#define _LOAD_CONST_UNDER_INLINE_r02 1264 +#define _LOAD_CONST_UNDER_INLINE_r12 1265 +#define _LOAD_CONST_UNDER_INLINE_r23 1266 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1267 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1268 +#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1269 +#define _LOAD_DEREF_r01 1270 +#define _LOAD_FAST_r01 1271 +#define _LOAD_FAST_r12 1272 +#define _LOAD_FAST_r23 1273 +#define _LOAD_FAST_0_r01 1274 +#define _LOAD_FAST_0_r12 1275 +#define _LOAD_FAST_0_r23 1276 +#define _LOAD_FAST_1_r01 1277 +#define _LOAD_FAST_1_r12 1278 +#define _LOAD_FAST_1_r23 1279 +#define _LOAD_FAST_2_r01 1280 +#define _LOAD_FAST_2_r12 1281 +#define _LOAD_FAST_2_r23 1282 +#define _LOAD_FAST_3_r01 1283 +#define _LOAD_FAST_3_r12 1284 +#define _LOAD_FAST_3_r23 1285 +#define _LOAD_FAST_4_r01 1286 +#define _LOAD_FAST_4_r12 1287 +#define _LOAD_FAST_4_r23 1288 +#define _LOAD_FAST_5_r01 1289 +#define _LOAD_FAST_5_r12 1290 +#define _LOAD_FAST_5_r23 1291 +#define _LOAD_FAST_6_r01 1292 +#define _LOAD_FAST_6_r12 1293 +#define _LOAD_FAST_6_r23 1294 +#define _LOAD_FAST_7_r01 1295 +#define _LOAD_FAST_7_r12 1296 +#define _LOAD_FAST_7_r23 1297 +#define _LOAD_FAST_AND_CLEAR_r01 1298 +#define _LOAD_FAST_AND_CLEAR_r12 1299 +#define _LOAD_FAST_AND_CLEAR_r23 1300 +#define _LOAD_FAST_BORROW_r01 1301 +#define _LOAD_FAST_BORROW_r12 1302 +#define _LOAD_FAST_BORROW_r23 1303 +#define _LOAD_FAST_BORROW_0_r01 1304 +#define _LOAD_FAST_BORROW_0_r12 1305 +#define _LOAD_FAST_BORROW_0_r23 1306 +#define _LOAD_FAST_BORROW_1_r01 1307 +#define _LOAD_FAST_BORROW_1_r12 1308 +#define _LOAD_FAST_BORROW_1_r23 1309 +#define _LOAD_FAST_BORROW_2_r01 1310 +#define _LOAD_FAST_BORROW_2_r12 1311 +#define _LOAD_FAST_BORROW_2_r23 1312 +#define _LOAD_FAST_BORROW_3_r01 1313 +#define _LOAD_FAST_BORROW_3_r12 1314 +#define _LOAD_FAST_BORROW_3_r23 1315 +#define _LOAD_FAST_BORROW_4_r01 1316 +#define _LOAD_FAST_BORROW_4_r12 1317 +#define _LOAD_FAST_BORROW_4_r23 1318 +#define _LOAD_FAST_BORROW_5_r01 1319 +#define _LOAD_FAST_BORROW_5_r12 1320 +#define _LOAD_FAST_BORROW_5_r23 1321 +#define _LOAD_FAST_BORROW_6_r01 1322 +#define _LOAD_FAST_BORROW_6_r12 1323 +#define _LOAD_FAST_BORROW_6_r23 1324 +#define _LOAD_FAST_BORROW_7_r01 1325 +#define _LOAD_FAST_BORROW_7_r12 1326 +#define _LOAD_FAST_BORROW_7_r23 1327 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1328 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1329 +#define _LOAD_FAST_CHECK_r01 1330 +#define _LOAD_FAST_CHECK_r12 1331 +#define _LOAD_FAST_CHECK_r23 1332 +#define _LOAD_FAST_LOAD_FAST_r02 1333 +#define _LOAD_FAST_LOAD_FAST_r13 1334 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1335 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1336 +#define _LOAD_GLOBAL_r00 1337 +#define _LOAD_GLOBAL_BUILTINS_r01 1338 +#define _LOAD_GLOBAL_MODULE_r01 1339 +#define _LOAD_LOCALS_r01 1340 +#define _LOAD_LOCALS_r12 1341 +#define _LOAD_LOCALS_r23 1342 +#define _LOAD_NAME_r01 1343 +#define _LOAD_SMALL_INT_r01 1344 +#define _LOAD_SMALL_INT_r12 1345 +#define _LOAD_SMALL_INT_r23 1346 +#define _LOAD_SMALL_INT_0_r01 1347 +#define _LOAD_SMALL_INT_0_r12 1348 +#define _LOAD_SMALL_INT_0_r23 1349 +#define _LOAD_SMALL_INT_1_r01 1350 +#define _LOAD_SMALL_INT_1_r12 1351 +#define _LOAD_SMALL_INT_1_r23 1352 +#define _LOAD_SMALL_INT_2_r01 1353 +#define _LOAD_SMALL_INT_2_r12 1354 +#define _LOAD_SMALL_INT_2_r23 1355 +#define _LOAD_SMALL_INT_3_r01 1356 +#define _LOAD_SMALL_INT_3_r12 1357 +#define _LOAD_SMALL_INT_3_r23 1358 +#define _LOAD_SPECIAL_r00 1359 +#define _LOAD_SUPER_ATTR_ATTR_r31 1360 +#define _LOAD_SUPER_ATTR_METHOD_r32 1361 +#define _LOCK_OBJECT_r01 1362 +#define _LOCK_OBJECT_r11 1363 +#define _LOCK_OBJECT_r22 1364 +#define _LOCK_OBJECT_r33 1365 +#define _MAKE_CALLARGS_A_TUPLE_r33 1366 +#define _MAKE_CELL_r00 1367 +#define _MAKE_FUNCTION_r11 1368 +#define _MAKE_HEAP_SAFE_r01 1369 +#define _MAKE_HEAP_SAFE_r11 1370 +#define _MAKE_HEAP_SAFE_r22 1371 +#define _MAKE_HEAP_SAFE_r33 1372 +#define _MAKE_WARM_r00 1373 +#define _MAKE_WARM_r11 1374 +#define _MAKE_WARM_r22 1375 +#define _MAKE_WARM_r33 1376 +#define _MAP_ADD_r20 1377 +#define _MATCH_CLASS_r33 1378 +#define _MATCH_KEYS_r23 1379 +#define _MATCH_MAPPING_r02 1380 +#define _MATCH_MAPPING_r12 1381 +#define _MATCH_MAPPING_r23 1382 +#define _MATCH_SEQUENCE_r02 1383 +#define _MATCH_SEQUENCE_r12 1384 +#define _MATCH_SEQUENCE_r23 1385 +#define _MAYBE_EXPAND_METHOD_r00 1386 +#define _MAYBE_EXPAND_METHOD_KW_r11 1387 +#define _MONITOR_CALL_r00 1388 +#define _MONITOR_CALL_KW_r11 1389 +#define _MONITOR_JUMP_BACKWARD_r00 1390 +#define _MONITOR_JUMP_BACKWARD_r11 1391 +#define _MONITOR_JUMP_BACKWARD_r22 1392 +#define _MONITOR_JUMP_BACKWARD_r33 1393 +#define _MONITOR_RESUME_r00 1394 +#define _NOP_r00 1395 +#define _NOP_r11 1396 +#define _NOP_r22 1397 +#define _NOP_r33 1398 +#define _POP_CALL_r20 1399 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1400 +#define _POP_CALL_ONE_r30 1401 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1402 +#define _POP_CALL_TWO_r30 1403 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1404 +#define _POP_EXCEPT_r10 1405 +#define _POP_ITER_r20 1406 +#define _POP_JUMP_IF_FALSE_r00 1407 +#define _POP_JUMP_IF_FALSE_r10 1408 +#define _POP_JUMP_IF_FALSE_r21 1409 +#define _POP_JUMP_IF_FALSE_r32 1410 +#define _POP_JUMP_IF_TRUE_r00 1411 +#define _POP_JUMP_IF_TRUE_r10 1412 +#define _POP_JUMP_IF_TRUE_r21 1413 +#define _POP_JUMP_IF_TRUE_r32 1414 +#define _POP_TOP_r10 1415 +#define _POP_TOP_FLOAT_r00 1416 +#define _POP_TOP_FLOAT_r10 1417 +#define _POP_TOP_FLOAT_r21 1418 +#define _POP_TOP_FLOAT_r32 1419 +#define _POP_TOP_INT_r00 1420 +#define _POP_TOP_INT_r10 1421 +#define _POP_TOP_INT_r21 1422 +#define _POP_TOP_INT_r32 1423 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1424 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1425 +#define _POP_TOP_NOP_r00 1426 +#define _POP_TOP_NOP_r10 1427 +#define _POP_TOP_NOP_r21 1428 +#define _POP_TOP_NOP_r32 1429 +#define _POP_TOP_UNICODE_r00 1430 +#define _POP_TOP_UNICODE_r10 1431 +#define _POP_TOP_UNICODE_r21 1432 +#define _POP_TOP_UNICODE_r32 1433 +#define _POP_TWO_r20 1434 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1435 +#define _PUSH_EXC_INFO_r02 1436 +#define _PUSH_EXC_INFO_r12 1437 +#define _PUSH_EXC_INFO_r23 1438 +#define _PUSH_FRAME_r10 1439 +#define _PUSH_NULL_r01 1440 +#define _PUSH_NULL_r12 1441 +#define _PUSH_NULL_r23 1442 +#define _PUSH_NULL_CONDITIONAL_r00 1443 +#define _PY_FRAME_EX_r31 1444 +#define _PY_FRAME_GENERAL_r01 1445 +#define _PY_FRAME_KW_r11 1446 +#define _REPLACE_WITH_TRUE_r02 1447 +#define _REPLACE_WITH_TRUE_r12 1448 +#define _REPLACE_WITH_TRUE_r23 1449 +#define _RESUME_CHECK_r00 1450 +#define _RESUME_CHECK_r11 1451 +#define _RESUME_CHECK_r22 1452 +#define _RESUME_CHECK_r33 1453 +#define _RETURN_GENERATOR_r01 1454 +#define _RETURN_VALUE_r11 1455 +#define _SAVE_RETURN_OFFSET_r00 1456 +#define _SAVE_RETURN_OFFSET_r11 1457 +#define _SAVE_RETURN_OFFSET_r22 1458 +#define _SAVE_RETURN_OFFSET_r33 1459 +#define _SEND_r33 1460 +#define _SEND_GEN_FRAME_r33 1461 +#define _SETUP_ANNOTATIONS_r00 1462 +#define _SET_ADD_r10 1463 +#define _SET_FUNCTION_ATTRIBUTE_r01 1464 +#define _SET_FUNCTION_ATTRIBUTE_r11 1465 +#define _SET_FUNCTION_ATTRIBUTE_r21 1466 +#define _SET_FUNCTION_ATTRIBUTE_r32 1467 +#define _SET_IP_r00 1468 +#define _SET_IP_r11 1469 +#define _SET_IP_r22 1470 +#define _SET_IP_r33 1471 +#define _SET_UPDATE_r11 1472 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1473 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1474 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1475 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1476 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1477 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1478 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1479 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1480 +#define _SPILL_OR_RELOAD_r01 1481 +#define _SPILL_OR_RELOAD_r02 1482 +#define _SPILL_OR_RELOAD_r03 1483 +#define _SPILL_OR_RELOAD_r10 1484 +#define _SPILL_OR_RELOAD_r12 1485 +#define _SPILL_OR_RELOAD_r13 1486 +#define _SPILL_OR_RELOAD_r20 1487 +#define _SPILL_OR_RELOAD_r21 1488 +#define _SPILL_OR_RELOAD_r23 1489 +#define _SPILL_OR_RELOAD_r30 1490 +#define _SPILL_OR_RELOAD_r31 1491 +#define _SPILL_OR_RELOAD_r32 1492 +#define _START_EXECUTOR_r00 1493 +#define _STORE_ATTR_r20 1494 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1495 +#define _STORE_ATTR_SLOT_r21 1496 +#define _STORE_ATTR_WITH_HINT_r21 1497 +#define _STORE_DEREF_r10 1498 +#define _STORE_FAST_LOAD_FAST_r11 1499 +#define _STORE_FAST_STORE_FAST_r20 1500 +#define _STORE_GLOBAL_r10 1501 +#define _STORE_NAME_r10 1502 +#define _STORE_SLICE_r30 1503 +#define _STORE_SUBSCR_r30 1504 +#define _STORE_SUBSCR_DICT_r31 1505 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1506 +#define _STORE_SUBSCR_LIST_INT_r32 1507 +#define _SWAP_r11 1508 +#define _SWAP_2_r02 1509 +#define _SWAP_2_r12 1510 +#define _SWAP_2_r22 1511 +#define _SWAP_2_r33 1512 +#define _SWAP_3_r03 1513 +#define _SWAP_3_r13 1514 +#define _SWAP_3_r23 1515 +#define _SWAP_3_r33 1516 +#define _SWAP_FAST_r01 1517 +#define _SWAP_FAST_r11 1518 +#define _SWAP_FAST_r22 1519 +#define _SWAP_FAST_r33 1520 +#define _SWAP_FAST_0_r01 1521 +#define _SWAP_FAST_0_r11 1522 +#define _SWAP_FAST_0_r22 1523 +#define _SWAP_FAST_0_r33 1524 +#define _SWAP_FAST_1_r01 1525 +#define _SWAP_FAST_1_r11 1526 +#define _SWAP_FAST_1_r22 1527 +#define _SWAP_FAST_1_r33 1528 +#define _SWAP_FAST_2_r01 1529 +#define _SWAP_FAST_2_r11 1530 +#define _SWAP_FAST_2_r22 1531 +#define _SWAP_FAST_2_r33 1532 +#define _SWAP_FAST_3_r01 1533 +#define _SWAP_FAST_3_r11 1534 +#define _SWAP_FAST_3_r22 1535 +#define _SWAP_FAST_3_r33 1536 +#define _SWAP_FAST_4_r01 1537 +#define _SWAP_FAST_4_r11 1538 +#define _SWAP_FAST_4_r22 1539 +#define _SWAP_FAST_4_r33 1540 +#define _SWAP_FAST_5_r01 1541 +#define _SWAP_FAST_5_r11 1542 +#define _SWAP_FAST_5_r22 1543 +#define _SWAP_FAST_5_r33 1544 +#define _SWAP_FAST_6_r01 1545 +#define _SWAP_FAST_6_r11 1546 +#define _SWAP_FAST_6_r22 1547 +#define _SWAP_FAST_6_r33 1548 +#define _SWAP_FAST_7_r01 1549 +#define _SWAP_FAST_7_r11 1550 +#define _SWAP_FAST_7_r22 1551 +#define _SWAP_FAST_7_r33 1552 +#define _TIER2_RESUME_CHECK_r00 1553 +#define _TIER2_RESUME_CHECK_r11 1554 +#define _TIER2_RESUME_CHECK_r22 1555 +#define _TIER2_RESUME_CHECK_r33 1556 +#define _TO_BOOL_r11 1557 +#define _TO_BOOL_BOOL_r01 1558 +#define _TO_BOOL_BOOL_r11 1559 +#define _TO_BOOL_BOOL_r22 1560 +#define _TO_BOOL_BOOL_r33 1561 +#define _TO_BOOL_INT_r02 1562 +#define _TO_BOOL_INT_r12 1563 +#define _TO_BOOL_INT_r23 1564 +#define _TO_BOOL_LIST_r02 1565 +#define _TO_BOOL_LIST_r12 1566 +#define _TO_BOOL_LIST_r23 1567 +#define _TO_BOOL_NONE_r01 1568 +#define _TO_BOOL_NONE_r11 1569 +#define _TO_BOOL_NONE_r22 1570 +#define _TO_BOOL_NONE_r33 1571 +#define _TO_BOOL_STR_r02 1572 +#define _TO_BOOL_STR_r12 1573 +#define _TO_BOOL_STR_r23 1574 +#define _TRACE_RECORD_r00 1575 +#define _UNARY_INVERT_r12 1576 +#define _UNARY_NEGATIVE_r12 1577 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1578 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1579 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1580 +#define _UNARY_NOT_r01 1581 +#define _UNARY_NOT_r11 1582 +#define _UNARY_NOT_r22 1583 +#define _UNARY_NOT_r33 1584 +#define _UNPACK_EX_r10 1585 +#define _UNPACK_SEQUENCE_r10 1586 +#define _UNPACK_SEQUENCE_LIST_r10 1587 +#define _UNPACK_SEQUENCE_TUPLE_r10 1588 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1589 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1590 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1591 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1592 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1593 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1594 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1595 +#define _WITH_EXCEPT_START_r33 1596 +#define _YIELD_VALUE_r11 1597 +#define MAX_UOP_REGS_ID 1597 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 19d19e5aee8..016bed17bf1 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -318,14 +318,15 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GUARD_CALLABLE_LIST_APPEND] = HAS_EXIT_FLAG, [_CALL_LIST_APPEND] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG, - [_CALL_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CALL_METHOD_DESCRIPTOR_O_INLINE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_O] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_RECURSION_LIMIT] = HAS_EXIT_FLAG, + [_CALL_METHOD_DESCRIPTOR_O_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, - [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST_INLINE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -2993,6 +2994,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_CHECK_RECURSION_LIMIT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 0, 0, _CHECK_RECURSION_LIMIT_r00 }, + { 1, 1, _CHECK_RECURSION_LIMIT_r11 }, + { 2, 2, _CHECK_RECURSION_LIMIT_r22 }, + { 3, 3, _CHECK_RECURSION_LIMIT_r33 }, + }, + }, [_CALL_METHOD_DESCRIPTOR_O_INLINE] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -4476,6 +4486,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CALL_LIST_APPEND_r33] = _CALL_LIST_APPEND, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_O, [_CALL_METHOD_DESCRIPTOR_O_r03] = _CALL_METHOD_DESCRIPTOR_O, + [_CHECK_RECURSION_LIMIT_r00] = _CHECK_RECURSION_LIMIT, + [_CHECK_RECURSION_LIMIT_r11] = _CHECK_RECURSION_LIMIT, + [_CHECK_RECURSION_LIMIT_r22] = _CHECK_RECURSION_LIMIT, + [_CHECK_RECURSION_LIMIT_r33] = _CHECK_RECURSION_LIMIT, [_CALL_METHOD_DESCRIPTOR_O_INLINE_r03] = _CALL_METHOD_DESCRIPTOR_O_INLINE, [_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00] = _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, @@ -4973,6 +4987,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_CHECK_PERIODIC_r00] = "_CHECK_PERIODIC_r00", [_CHECK_PERIODIC_IF_NOT_YIELD_FROM] = "_CHECK_PERIODIC_IF_NOT_YIELD_FROM", [_CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00] = "_CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00", + [_CHECK_RECURSION_LIMIT] = "_CHECK_RECURSION_LIMIT", + [_CHECK_RECURSION_LIMIT_r00] = "_CHECK_RECURSION_LIMIT_r00", + [_CHECK_RECURSION_LIMIT_r11] = "_CHECK_RECURSION_LIMIT_r11", + [_CHECK_RECURSION_LIMIT_r22] = "_CHECK_RECURSION_LIMIT_r22", + [_CHECK_RECURSION_LIMIT_r33] = "_CHECK_RECURSION_LIMIT_r33", [_CHECK_RECURSION_REMAINING] = "_CHECK_RECURSION_REMAINING", [_CHECK_RECURSION_REMAINING_r00] = "_CHECK_RECURSION_REMAINING_r00", [_CHECK_RECURSION_REMAINING_r11] = "_CHECK_RECURSION_REMAINING_r11", @@ -6582,6 +6601,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _CALL_METHOD_DESCRIPTOR_O: return 2 + oparg; + case _CHECK_RECURSION_LIMIT: + return 0; case _CALL_METHOD_DESCRIPTOR_O_INLINE: return 1 + oparg; case _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 1d92c476f93..022f05bbe37 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2813,6 +2813,23 @@ def testfunc(n): self.assertNotIn("_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops) self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops) + def test_check_recursion_limit_deduplicated(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = "hello" + a = y.upper() + b = y.lower() + x += len(a) + x += len(b) + return x + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD * 10) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", uops) + self.assertEqual(count_ops(ex, "_CHECK_RECURSION_LIMIT"), 1) + def test_call_intrinsic_1(self): def testfunc(n): x = 0 diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 7e3668622d9..45cbc58b085 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -4006,6 +4006,14 @@ JUMP_TO_PREDICTED(CALL); } } + // _CHECK_RECURSION_LIMIT + { + if (_Py_ReachedRecursionLimit(tstate)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } // _CALL_METHOD_DESCRIPTOR_NOARGS { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4016,11 +4024,6 @@ } _PyStackRef self_stackref = args[0]; PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); - if (_Py_ReachedRecursionLimit(tstate)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4111,6 +4114,14 @@ JUMP_TO_PREDICTED(CALL); } } + // _CHECK_RECURSION_LIMIT + { + if (_Py_ReachedRecursionLimit(tstate)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } // _CALL_METHOD_DESCRIPTOR_O { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4119,11 +4130,6 @@ if (!PyStackRef_IsNull(self_or_null)) { arguments--; } - if (_Py_ReachedRecursionLimit(tstate)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 4b58efaf921..edba5a89cc0 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4811,8 +4811,6 @@ dummy_func( if (!PyStackRef_IsNull(self_or_null)) { arguments--; } - // CPython promises to check all non-vectorcall function calls. - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); @@ -4830,9 +4828,12 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } + op(_CHECK_RECURSION_LIMIT, ( -- )) { + EXIT_IF(_Py_ReachedRecursionLimit(tstate)); + } + tier2 op(_CALL_METHOD_DESCRIPTOR_O_INLINE, (callable, args[oparg], cfunc/4 -- res, c, s, a)) { assert(oparg == 2); - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); STAT_INC(CALL, hit); volatile PyCFunction cfunc_v = (PyCFunction)cfunc; PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); @@ -4855,6 +4856,7 @@ dummy_func( unused/1 + unused/2 + _GUARD_CALLABLE_METHOD_DESCRIPTOR_O + + _CHECK_RECURSION_LIMIT + _CALL_METHOD_DESCRIPTOR_O + POP_TOP + POP_TOP + @@ -4956,8 +4958,6 @@ dummy_func( } _PyStackRef self_stackref = args[0]; PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); - // CPython promises to check all non-vectorcall function calls. - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); @@ -4975,7 +4975,6 @@ dummy_func( assert(oparg == 1); _PyStackRef self_stackref = args[0]; PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); - EXIT_IF(_Py_ReachedRecursionLimit(tstate)); STAT_INC(CALL, hit); volatile PyCFunction cfunc_v = (PyCFunction)cfunc; PyObject *res_o = _PyCFunction_TrampolineCall(cfunc_v, self, NULL); @@ -4993,6 +4992,7 @@ dummy_func( unused/1 + unused/2 + _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS + + _CHECK_RECURSION_LIMIT + _CALL_METHOD_DESCRIPTOR_NOARGS + _CHECK_PERIODIC_AT_END; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 0b68274a378..6600accb37e 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -17086,11 +17086,6 @@ if (!PyStackRef_IsNull(self_or_null)) { arguments--; } - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); @@ -17119,6 +17114,76 @@ break; } + case _CHECK_RECURSION_LIMIT_r00: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + SET_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CHECK_RECURSION_LIMIT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CHECK_RECURSION_LIMIT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _CHECK_RECURSION_LIMIT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + if (_Py_ReachedRecursionLimit(tstate)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = _stack_item_2; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _CALL_METHOD_DESCRIPTOR_O_INLINE_r03: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -17133,11 +17198,6 @@ callable = stack_pointer[-1 - oparg]; PyObject *cfunc = (PyObject *)CURRENT_OPERAND0_64(); assert(oparg == 2); - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); volatile PyCFunction cfunc_v = (PyCFunction)cfunc; PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); @@ -17361,11 +17421,6 @@ } _PyStackRef self_stackref = args[0]; PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -17407,11 +17462,6 @@ assert(oparg == 1); _PyStackRef self_stackref = args[0]; PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); - if (_Py_ReachedRecursionLimit(tstate)) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } STAT_INC(CALL, hit); volatile PyCFunction cfunc_v = (PyCFunction)cfunc; _PyFrame_SetStackPointer(frame, stack_pointer); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 7573bf5510b..127a45ef591 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -4006,6 +4006,14 @@ JUMP_TO_PREDICTED(CALL); } } + // _CHECK_RECURSION_LIMIT + { + if (_Py_ReachedRecursionLimit(tstate)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } // _CALL_METHOD_DESCRIPTOR_NOARGS { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4016,11 +4024,6 @@ } _PyStackRef self_stackref = args[0]; PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref); - if (_Py_ReachedRecursionLimit(tstate)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4111,6 +4114,14 @@ JUMP_TO_PREDICTED(CALL); } } + // _CHECK_RECURSION_LIMIT + { + if (_Py_ReachedRecursionLimit(tstate)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } + } // _CALL_METHOD_DESCRIPTOR_O { PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4119,11 +4130,6 @@ if (!PyStackRef_IsNull(self_or_null)) { arguments--; } - if (_Py_ReachedRecursionLimit(tstate)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } STAT_INC(CALL, hit); PyCFunction cfunc = method->d_method->ml_meth; PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 86efb74c6d9..4f16fa7a5ff 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1397,6 +1397,13 @@ dummy_func(void) { } } + op(_CHECK_RECURSION_LIMIT, ( -- )) { + if (ctx->frame->is_c_recursion_checked) { + ADD_OP(_NOP, 0, 0); + } + ctx->frame->is_c_recursion_checked = true; + } + op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res)) { PyObject *callable_o = sym_get_const(ctx, callable); if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type) diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index a8be9bbd994..2b0efd9db25 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -4136,6 +4136,14 @@ break; } + case _CHECK_RECURSION_LIMIT: { + if (ctx->frame->is_c_recursion_checked) { + ADD_OP(_NOP, 0, 0); + } + ctx->frame->is_c_recursion_checked = true; + break; + } + case _CALL_METHOD_DESCRIPTOR_O_INLINE: { JitOptRef res; JitOptRef c; diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index d6f1c09490a..a0ee175fd10 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -1514,6 +1514,7 @@ _Py_uop_frame_new( frame->globals_watched = false; frame->func = NULL; frame->caller = false; + frame->is_c_recursion_checked = false; if (ctx->locals.used > ctx->locals.end || ctx->stack.used > ctx->stack.end) { ctx->done = true; ctx->out_of_space = true; From c50d6cd01215b72282221845ea4831a104f12c4c Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Sat, 4 Apr 2026 18:16:23 +0800 Subject: [PATCH 400/775] gh-148078: Fix uses of sym_is_not_null in JIT optimizer (GH-148079) --- Python/optimizer_bytecodes.c | 19 ++++++++++++------- Python/optimizer_cases.c.h | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 4f16fa7a5ff..dfb97625bf9 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -979,7 +979,7 @@ dummy_func(void) { if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, callable); PyCodeObject *co = (PyCodeObject *)func->func_code; - if (co->co_argcount == oparg + !sym_is_null(self_or_null)) { + if (co->co_argcount == oparg + sym_is_not_null(self_or_null)) { ADD_OP(_NOP, 0 ,0); } } @@ -1266,9 +1266,10 @@ dummy_func(void) { op(_GUARD_CALLABLE_BUILTIN_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyCFunction_Type)) { + if (callable_o && sym_matches_type(callable, &PyCFunction_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } if (total_args == 1 && PyCFunction_GET_FLAGS(callable_o) == METH_O) { @@ -1321,7 +1322,8 @@ dummy_func(void) { op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; @@ -1347,7 +1349,8 @@ dummy_func(void) { op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; @@ -1373,7 +1376,8 @@ dummy_func(void) { op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; @@ -1439,7 +1443,8 @@ dummy_func(void) { op(_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) { PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 2b0efd9db25..4643a0ed0c5 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3565,7 +3565,7 @@ if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, callable); PyCodeObject *co = (PyCodeObject *)func->func_code; - if (co->co_argcount == oparg + !sym_is_null(self_or_null)) { + if (co->co_argcount == oparg + sym_is_not_null(self_or_null)) { ADD_OP(_NOP, 0 ,0); } } @@ -3835,9 +3835,10 @@ self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyCFunction_Type)) { + if (callable_o && sym_matches_type(callable, &PyCFunction_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; - if (!sym_is_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { total_args++; } if (total_args == 1 && PyCFunction_GET_FLAGS(callable_o) == METH_O) { @@ -4072,7 +4073,8 @@ self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; @@ -4171,7 +4173,8 @@ self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; @@ -4235,7 +4238,8 @@ self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; @@ -4299,7 +4303,8 @@ self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; PyObject *callable_o = sym_get_const(ctx, callable); - if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type)) { + if (callable_o && sym_matches_type(callable, &PyMethodDescr_Type) && + (sym_is_not_null(self_or_null) || sym_is_null(self_or_null))) { int total_args = oparg; if (sym_is_not_null(self_or_null)) { total_args++; From 611d606a1890be275c70efee37a298a3acc60585 Mon Sep 17 00:00:00 2001 From: TT <70463940+Herrtian@users.noreply.github.com> Date: Sat, 4 Apr 2026 12:32:58 +0200 Subject: [PATCH 401/775] gh-148067: Fix typo in asyncio event loop docs: 'signals' -> 'signal' (#148073) --- Doc/library/asyncio-eventloop.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index d1a5b4e7b46..79c9516cda2 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -2055,7 +2055,7 @@ Wait until a file descriptor received some data using the Set signal handlers for SIGINT and SIGTERM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -(This ``signals`` example only works on Unix.) +(This ``signal`` example only works on Unix.) Register handlers for signals :const:`~signal.SIGINT` and :const:`~signal.SIGTERM` using the :meth:`loop.add_signal_handler` method:: From 328da67b2c71a52b0cdf61c4e52b697e7e921c22 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Sat, 4 Apr 2026 19:56:40 +0800 Subject: [PATCH 402/775] gh-146073: Revert "gh-146073: Add fitness/exit quality mechanism for JIT trace frontend (GH-147966)" (#148082) This reverts commit 198b04b75f7425c401ffe40a748688a89d28dd59. --- Include/cpython/pystats.h | 1 - Include/internal/pycore_interp_structs.h | 4 - Include/internal/pycore_optimizer.h | 20 +--- Python/optimizer.c | 130 ++--------------------- Python/pystate.c | 16 --- Python/pystats.c | 1 - 6 files changed, 7 insertions(+), 165 deletions(-) diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h index 5d1f44988a6..e473110eca7 100644 --- a/Include/cpython/pystats.h +++ b/Include/cpython/pystats.h @@ -144,7 +144,6 @@ typedef struct _optimization_stats { uint64_t unknown_callee; uint64_t trace_immediately_deopts; uint64_t executors_invalidated; - uint64_t fitness_terminated_traces; UOpStats opcode[PYSTATS_MAX_UOP_ID + 1]; uint64_t unsupported_opcode[256]; uint64_t trace_length_hist[_Py_UOP_HIST_SIZE]; diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 0cebe1b4b9e..f76d4f41c55 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -449,10 +449,6 @@ typedef struct _PyOptimizationConfig { uint16_t side_exit_initial_value; uint16_t side_exit_initial_backoff; - // Trace fitness thresholds - uint16_t fitness_initial; - uint16_t fitness_initial_side; - // Optimization flags bool specialization_enabled; bool uops_optimize_enabled; diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 820ee32201c..2986afb142b 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -15,23 +15,6 @@ extern "C" { #include "pycore_optimizer_types.h" #include -/* Default fitness configuration values for trace quality control. - * FITNESS_INITIAL and FITNESS_INITIAL_SIDE can be overridden via - * PYTHON_JIT_FITNESS_INITIAL and PYTHON_JIT_FITNESS_INITIAL_SIDE */ -#define FITNESS_PER_INSTRUCTION 2 -#define FITNESS_BRANCH_BASE 5 -#define FITNESS_INITIAL (FITNESS_PER_INSTRUCTION * 1000) -#define FITNESS_INITIAL_SIDE (FITNESS_INITIAL / 2) -#define FITNESS_BACKWARD_EDGE (FITNESS_INITIAL / 10) - -/* Exit quality constants for fitness-based trace termination. - * Higher values mean better places to stop the trace. */ - -#define EXIT_QUALITY_DEFAULT 200 -#define EXIT_QUALITY_CLOSE_LOOP (4 * EXIT_QUALITY_DEFAULT) -#define EXIT_QUALITY_ENTER_EXECUTOR (2 * EXIT_QUALITY_DEFAULT + 100) -#define EXIT_QUALITY_SPECIALIZABLE (EXIT_QUALITY_DEFAULT / 4) - typedef struct _PyJitUopBuffer { _PyUOpInstruction *start; @@ -118,8 +101,7 @@ typedef struct _PyJitTracerPreviousState { } _PyJitTracerPreviousState; typedef struct _PyJitTracerTranslatorState { - int32_t fitness; // Current trace fitness, starts high, decrements - int frame_depth; // Current inline depth (0 = root frame) + int jump_backward_seen; } _PyJitTracerTranslatorState; typedef struct _PyJitTracerState { diff --git a/Python/optimizer.c b/Python/optimizer.c index c7a6b7e7465..f09bf778587 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -549,6 +549,8 @@ dynamic_exit_uop[MAX_UOP_ID + 1] = { }; +#define CONFIDENCE_RANGE 1000 +#define CONFIDENCE_CUTOFF 333 #ifdef Py_DEBUG #define DPRINTF(level, ...) \ @@ -596,46 +598,6 @@ add_to_trace( ((uint32_t)((INSTR) - ((_Py_CODEUNIT *)(CODE)->co_code_adaptive))) -/* Compute branch fitness penalty based on how likely the traced path is. - * The penalty is small when the traced path is common, large when rare. - * A branch that historically goes the other way gets a heavy penalty. */ -static inline int -compute_branch_penalty(uint16_t history, bool branch_taken) -{ - int taken_count = _Py_popcount32((uint32_t)history); - int on_trace_count = branch_taken ? taken_count : 16 - taken_count; - int off_trace = 16 - on_trace_count; - /* Linear scaling: off_trace ranges from 0 (fully biased our way) - * to 16 (fully biased against us), so the penalty ranges from - * FITNESS_BRANCH_BASE to FITNESS_BRANCH_BASE + 32. */ - return FITNESS_BRANCH_BASE + off_trace * 2; -} - -/* Compute exit quality for the current trace position. - * Higher values mean better places to stop the trace. */ -static inline int32_t -compute_exit_quality(_Py_CODEUNIT *target_instr, int opcode, - const _PyJitTracerState *tracer) -{ - if (target_instr == tracer->initial_state.start_instr || - target_instr == tracer->initial_state.close_loop_instr) { - return EXIT_QUALITY_CLOSE_LOOP; - } - if (target_instr->op.code == ENTER_EXECUTOR) { - return EXIT_QUALITY_ENTER_EXECUTOR; - } - if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] > 0) { - return EXIT_QUALITY_SPECIALIZABLE; - } - return EXIT_QUALITY_DEFAULT; -} - -static inline int32_t -compute_frame_penalty(const _PyOptimizationConfig *cfg) -{ - return (int32_t)cfg->fitness_initial / 10 + 1; -} - static int is_terminator(const _PyUOpInstruction *uop) { @@ -675,7 +637,6 @@ _PyJit_translate_single_bytecode_to_trace( _Py_CODEUNIT *this_instr = tracer->prev_state.instr; _Py_CODEUNIT *target_instr = this_instr; uint32_t target = 0; - int end_trace_opcode = _DEOPT; target = Py_IsNone((PyObject *)old_code) ? (uint32_t)(target_instr - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR) @@ -773,14 +734,16 @@ _PyJit_translate_single_bytecode_to_trace( DPRINTF(2, "Unsupported: oparg too large\n"); unsupported: { + // Rewind to previous instruction and replace with _EXIT_TRACE. _PyUOpInstruction *curr = uop_buffer_last(trace); while (curr->opcode != _SET_IP && uop_buffer_length(trace) > 2) { trace->next--; curr = uop_buffer_last(trace); } + assert(curr->opcode == _SET_IP || uop_buffer_length(trace) == 2); if (curr->opcode == _SET_IP) { int32_t old_target = (int32_t)uop_get_target(curr); - curr->opcode = end_trace_opcode; + curr->opcode = _DEOPT; curr->format = UOP_FORMAT_TARGET; curr->target = old_target; } @@ -800,23 +763,6 @@ _PyJit_translate_single_bytecode_to_trace( return 1; } - // Fitness-based trace quality check (before reserving space for this instruction) - _PyJitTracerTranslatorState *ts = &tracer->translator_state; - int32_t eq = compute_exit_quality(target_instr, opcode, tracer); - DPRINTF(3, "Fitness check: %s(%d) fitness=%d, exit_quality=%d, depth=%d\n", - _PyOpcode_OpName[opcode], oparg, ts->fitness, eq, ts->frame_depth); - - // Check if fitness is depleted — should we stop the trace? - if (ts->fitness < eq) { - // This is a tracer heuristic rather than normal program control flow, - // so leave operand1 clear and let the resulting side exit increase chain_depth. - ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); - OPT_STAT_INC(fitness_terminated_traces); - DPRINTF(2, "Fitness terminated: %s(%d) fitness=%d < exit_quality=%d\n", - _PyOpcode_OpName[opcode], oparg, ts->fitness, eq); - goto done; - } - // One for possible _DEOPT, one because _CHECK_VALIDITY itself might _DEOPT trace->end -= 2; @@ -870,12 +816,6 @@ _PyJit_translate_single_bytecode_to_trace( assert(jump_happened ? (next_instr == computed_jump_instr) : (next_instr == computed_next_instr)); uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_happened]; ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(jump_happened ? computed_next_instr : computed_jump_instr, old_code)); - int bp = compute_branch_penalty(target_instr[1].cache, jump_happened); - tracer->translator_state.fitness -= bp; - DPRINTF(3, " branch penalty: -%d (history=0x%04x, taken=%d) -> fitness=%d\n", - bp, target_instr[1].cache, jump_happened, - tracer->translator_state.fitness); - break; } case JUMP_BACKWARD_JIT: @@ -883,9 +823,6 @@ _PyJit_translate_single_bytecode_to_trace( case JUMP_BACKWARD_NO_JIT: case JUMP_BACKWARD: ADD_TO_TRACE(_CHECK_PERIODIC, 0, 0, target); - tracer->translator_state.fitness -= FITNESS_BACKWARD_EDGE; - DPRINTF(3, " backward edge penalty: -%d -> fitness=%d\n", - FITNESS_BACKWARD_EDGE, tracer->translator_state.fitness); _Py_FALLTHROUGH; case JUMP_BACKWARD_NO_INTERRUPT: { @@ -1008,44 +945,6 @@ _PyJit_translate_single_bytecode_to_trace( assert(next->op.code == STORE_FAST); operand = next->op.arg; } - else if (uop == _PUSH_FRAME) { - _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; - ts_depth->frame_depth++; - if (ts_depth->frame_depth >= MAX_ABSTRACT_FRAME_DEPTH) { - // The optimizer can't handle frames this deep, - // so there's no point continuing the trace. - DPRINTF(2, "Unsupported: frame depth %d >= MAX_ABSTRACT_FRAME_DEPTH\n", - ts_depth->frame_depth); - end_trace_opcode = _EXIT_TRACE; - goto unsupported; - } - int32_t frame_penalty = compute_frame_penalty(&tstate->interp->opt_config); - int32_t cost = frame_penalty * ts_depth->frame_depth; - ts_depth->fitness -= cost; - DPRINTF(3, " _PUSH_FRAME: depth=%d, penalty=-%d (per_frame=%d) -> fitness=%d\n", - ts_depth->frame_depth, cost, frame_penalty, - ts_depth->fitness); - } - else if (uop == _RETURN_VALUE || uop == _RETURN_GENERATOR || uop == _YIELD_VALUE) { - _PyJitTracerTranslatorState *ts_depth = &tracer->translator_state; - int32_t frame_penalty = compute_frame_penalty(&tstate->interp->opt_config); - if (ts_depth->frame_depth <= 0) { - // Underflow: returning from a frame we didn't enter - ts_depth->fitness -= frame_penalty * 2; - DPRINTF(3, " %s: underflow penalty=-%d -> fitness=%d\n", - _PyOpcode_uop_name[uop], frame_penalty * 2, - ts_depth->fitness); - } - else { - // Reward returning: small inlined calls should be encouraged - ts_depth->fitness += frame_penalty; - DPRINTF(3, " %s: return reward=+%d, depth=%d -> fitness=%d\n", - _PyOpcode_uop_name[uop], frame_penalty, - ts_depth->frame_depth - 1, - ts_depth->fitness); - } - ts_depth->frame_depth = ts_depth->frame_depth <= 0 ? 0 : ts_depth->frame_depth - 1; - } else if (_PyUop_Flags[uop] & HAS_RECORDS_VALUE_FLAG) { PyObject *recorded_value = tracer->prev_state.recorded_value; tracer->prev_state.recorded_value = NULL; @@ -1087,13 +986,7 @@ _PyJit_translate_single_bytecode_to_trace( ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); goto done; } - // Update fitness AFTER translation, BEFORE returning to continue tracing. - // This ensures the next iteration's fitness check reflects the cost of - // all instructions translated so far. - tracer->translator_state.fitness -= FITNESS_PER_INSTRUCTION; - DPRINTF(3, " per-insn cost: -%d -> fitness=%d\n", - FITNESS_PER_INSTRUCTION, tracer->translator_state.fitness); - DPRINTF(2, "Trace continuing (fitness=%d)\n", tracer->translator_state.fitness); + DPRINTF(2, "Trace continuing\n"); return 1; done: DPRINTF(2, "Trace done\n"); @@ -1176,17 +1069,6 @@ _PyJit_TryInitializeTracing( assert(curr_instr->op.code == JUMP_BACKWARD_JIT || curr_instr->op.code == RESUME_CHECK_JIT || (exit != NULL)); tracer->initial_state.jump_backward_instr = curr_instr; - // Initialize fitness tracking state - const _PyOptimizationConfig *cfg = &tstate->interp->opt_config; - _PyJitTracerTranslatorState *ts = &tracer->translator_state; - bool is_side_trace = (exit != NULL); - ts->fitness = is_side_trace - ? (int32_t)cfg->fitness_initial_side - : (int32_t)cfg->fitness_initial; - ts->frame_depth = 0; - DPRINTF(3, "Fitness init: %s trace, fitness=%d\n", - is_side_trace ? "side" : "root", ts->fitness); - tracer->is_tracing = true; return 1; } diff --git a/Python/pystate.c b/Python/pystate.c index 78eab7cc7d2..143175da0f4 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -635,22 +635,6 @@ init_interpreter(PyInterpreterState *interp, "PYTHON_JIT_SIDE_EXIT_INITIAL_BACKOFF", SIDE_EXIT_INITIAL_BACKOFF, 0, MAX_BACKOFF); - // Trace fitness configuration - init_policy(&interp->opt_config.fitness_initial, - "PYTHON_JIT_FITNESS_INITIAL", - FITNESS_INITIAL, 100, 10000); - init_policy(&interp->opt_config.fitness_initial_side, - "PYTHON_JIT_FITNESS_INITIAL_SIDE", - FITNESS_INITIAL_SIDE, 50, 5000); - /* The tracer starts at start_instr, so initial fitness must not be below - * the close-loop exit quality or tracing will terminate immediately. */ - if (interp->opt_config.fitness_initial < EXIT_QUALITY_CLOSE_LOOP) { - interp->opt_config.fitness_initial = EXIT_QUALITY_CLOSE_LOOP; - } - if (interp->opt_config.fitness_initial_side < EXIT_QUALITY_CLOSE_LOOP) { - interp->opt_config.fitness_initial_side = EXIT_QUALITY_CLOSE_LOOP; - } - interp->opt_config.specialization_enabled = !is_env_enabled("PYTHON_SPECIALIZATION_OFF"); interp->opt_config.uops_optimize_enabled = !is_env_disabled("PYTHON_UOPS_OPTIMIZE"); if (interp != &runtime->_main_interpreter) { diff --git a/Python/pystats.c b/Python/pystats.c index 2fac2db1b73..a057ad88456 100644 --- a/Python/pystats.c +++ b/Python/pystats.c @@ -274,7 +274,6 @@ print_optimization_stats(FILE *out, OptimizationStats *stats) fprintf(out, "Optimization low confidence: %" PRIu64 "\n", stats->low_confidence); fprintf(out, "Optimization unknown callee: %" PRIu64 "\n", stats->unknown_callee); fprintf(out, "Executors invalidated: %" PRIu64 "\n", stats->executors_invalidated); - fprintf(out, "Optimization fitness terminated: %" PRIu64 "\n", stats->fitness_terminated_traces); print_histogram(out, "Trace length", stats->trace_length_hist); print_histogram(out, "Trace run length", stats->trace_run_length_hist); From fe9befc1ca7eac36749ec358969464334381b9f9 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Sat, 4 Apr 2026 13:29:17 +0100 Subject: [PATCH 403/775] gh-145883: Fix two heap-buffer-overflows in `_zoneinfo` (#145885) --- Lib/test/test_zoneinfo/test_zoneinfo.py | 32 +++++++++++++++++++ Lib/zoneinfo/_common.py | 4 +++ Lib/zoneinfo/_zoneinfo.py | 2 +- ...-03-12-21-01-48.gh-issue-145883.lUvXcc.rst | 2 ++ Modules/_zoneinfo.c | 4 +-- Tools/build/compute-changes.py | 3 ++ 6 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py b/Lib/test/test_zoneinfo/test_zoneinfo.py index aaab4709464..7502b120825 100644 --- a/Lib/test/test_zoneinfo/test_zoneinfo.py +++ b/Lib/test/test_zoneinfo/test_zoneinfo.py @@ -741,6 +741,38 @@ def test_empty_zone(self): with self.assertRaises(ValueError): self.klass.from_file(zf) + def test_invalid_transition_index(self): + STD = ZoneOffset("STD", ZERO) + DST = ZoneOffset("DST", ONE_H, ONE_H) + + zf = self.construct_zone([ + ZoneTransition(datetime(2026, 3, 1, 2), STD, DST), + ZoneTransition(datetime(2026, 11, 1, 2), DST, STD), + ], after="", version=1) + + data = bytearray(zf.read()) + timecnt = struct.unpack_from(">l", data, 32)[0] + idx_offset = 44 + timecnt * 4 + data[idx_offset + 1] = 2 # typecnt is 2, so index 2 is OOB + f = io.BytesIO(bytes(data)) + + with self.assertRaises(ValueError): + self.klass.from_file(f) + + def test_transition_lookahead_out_of_bounds(self): + STD = ZoneOffset("STD", ZERO) + DST = ZoneOffset("DST", ONE_H, ONE_H) + EXT = ZoneOffset("EXT", ONE_H) + + zf = self.construct_zone([ + ZoneTransition(datetime(2026, 3, 1), STD, DST), + ZoneTransition(datetime(2026, 6, 1), DST, EXT), + ZoneTransition(datetime(2026, 9, 1), EXT, DST), + ], after="") + + zi = self.klass.from_file(zf) + self.assertIsNotNone(zi) + def test_zone_very_large_timestamp(self): """Test when a transition is in the far past or future. diff --git a/Lib/zoneinfo/_common.py b/Lib/zoneinfo/_common.py index 59f3f0ce853..98668c15d8b 100644 --- a/Lib/zoneinfo/_common.py +++ b/Lib/zoneinfo/_common.py @@ -67,6 +67,10 @@ def load_data(fobj): f">{timecnt}{time_type}", fobj.read(timecnt * time_size) ) trans_idx = struct.unpack(f">{timecnt}B", fobj.read(timecnt)) + + if max(trans_idx) >= typecnt: + raise ValueError("Invalid transition index found while reading TZif: " + f"{max(trans_idx)}") else: trans_list_utc = () trans_idx = () diff --git a/Lib/zoneinfo/_zoneinfo.py b/Lib/zoneinfo/_zoneinfo.py index bd3fefc6c9d..7063eb6a902 100644 --- a/Lib/zoneinfo/_zoneinfo.py +++ b/Lib/zoneinfo/_zoneinfo.py @@ -338,7 +338,7 @@ def _utcoff_to_dstoff(trans_idx, utcoffsets, isdsts): if not isdsts[comp_idx]: dstoff = utcoff - utcoffsets[comp_idx] - if not dstoff and idx < (typecnt - 1): + if not dstoff and idx < (typecnt - 1) and i + 1 < len(trans_idx): comp_idx = trans_idx[i + 1] # If the following transition is also DST and we couldn't diff --git a/Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst b/Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst new file mode 100644 index 00000000000..2c17768c518 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst @@ -0,0 +1,2 @@ +:mod:`zoneinfo`: Fix heap buffer overflow reads from malformed TZif data. +Found by OSS Fuzz, issues :oss-fuzz:`492245058` and :oss-fuzz:`492230068`. diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index aa0b1302cb2..eaffd020ed9 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -1075,7 +1075,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) } trans_idx[i] = (size_t)cur_trans_idx; - if (trans_idx[i] > self->num_ttinfos) { + if (trans_idx[i] >= self->num_ttinfos) { PyErr_Format( PyExc_ValueError, "Invalid transition index found while reading TZif: %zd", @@ -2081,7 +2081,7 @@ utcoff_to_dstoff(size_t *trans_idx, long *utcoffs, long *dstoffs, dstoff = utcoff - utcoffs[comp_idx]; } - if (!dstoff && idx < (num_ttinfos - 1)) { + if (!dstoff && idx < (num_ttinfos - 1) && i + 1 < num_transitions) { comp_idx = trans_idx[i + 1]; // If the following transition is also DST and we couldn't find diff --git a/Tools/build/compute-changes.py b/Tools/build/compute-changes.py index c15dc599f99..4870388da0d 100644 --- a/Tools/build/compute-changes.py +++ b/Tools/build/compute-changes.py @@ -99,6 +99,9 @@ Path("Modules/pyexpat.c"), # zipfile Path("Lib/zipfile/"), + # zoneinfo + Path("Lib/zoneinfo/"), + Path("Modules/_zoneinfo.c"), }) From 289f19adb0abaaab0e914f52dceca831905a1967 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Sat, 4 Apr 2026 21:32:12 +0900 Subject: [PATCH 404/775] gh-148083: Constant-fold _CONTAINS_OP_SET for frozenset (gh-148084) --- Lib/test/test_capi/test_opt.py | 20 ++++++++- ...-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst | 1 + Python/optimizer_analysis.c | 1 + Python/optimizer_bytecodes.c | 3 ++ Python/optimizer_cases.c.h | 44 +++++++++++++++++++ Python/optimizer_symbols.c | 3 +- 6 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 022f05bbe37..56f90194b48 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -23,6 +23,9 @@ # For frozendict JIT tests FROZEN_DICT_CONST = frozendict(x=1, y=2) +# For frozenset JIT tests +FROZEN_SET_CONST = frozenset({1, 2, 3}) + class _GenericKey: pass @@ -2169,7 +2172,8 @@ def f(n): self.assertIsNotNone(ex) uops = get_opnames(ex) self.assertNotIn("_GUARD_TOS_ANY_SET", uops) - self.assertIn("_CONTAINS_OP_SET", uops) + # _CONTAINS_OP_SET is constant-folded away for frozenset literals + self.assertIn("_INSERT_2_LOAD_CONST_INLINE_BORROW", uops) def test_remove_guard_for_known_type_tuple(self): def f(n): @@ -4399,6 +4403,20 @@ def testfunc(n): # lookup result is folded to constant 1, so comparison is optimized away self.assertNotIn("_COMPARE_OP_INT", uops) + def test_contains_op_frozenset_const_fold(self): + def testfunc(n): + x = 0 + for _ in range(n): + if 1 in FROZEN_SET_CONST: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CONTAINS_OP_SET", uops) + def test_binary_subscr_list_slice(self): def testfunc(n): x = 0 diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst new file mode 100644 index 00000000000..fea4659d0b9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst @@ -0,0 +1 @@ +Constant-fold ``_CONTAINS_OP_SET`` for :class:`frozenset`. Patch by Donghee Na. diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 4672a272fc9..2953311b392 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -30,6 +30,7 @@ #include "pycore_unicodeobject.h" #include "pycore_ceval.h" #include "pycore_floatobject.h" +#include "pycore_setobject.h" #include #include diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index dfb97625bf9..6e9a34384ba 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -706,6 +706,9 @@ dummy_func(void) { b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_matches_type(right, &PyFrozenSet_Type)) { + REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, b); + } } op(_CONTAINS_OP_DICT, (left, right -- b, l, r)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 4643a0ed0c5..dc00b6bc139 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2993,6 +2993,50 @@ b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; + if (sym_matches_type(right, &PyFrozenSet_Type)) { + if ( + sym_is_safe_const(ctx, left) && + sym_is_safe_const(ctx, right) + ) { + JitOptRef left_sym = left; + JitOptRef right_sym = right; + _PyStackRef left = sym_get_const_as_stackref(ctx, left_sym); + _PyStackRef right = sym_get_const_as_stackref(ctx, right_sym); + _PyStackRef b_stackref; + _PyStackRef l_stackref; + _PyStackRef r_stackref; + /* Start of uop copied from bytecodes for constant evaluation */ + PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); + PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + assert(PyAnySet_CheckExact(right_o)); + STAT_INC(CONTAINS_OP, hit); + int res = _PySet_Contains((PySetObject *)right_o, left_o); + if (res < 0) { + JUMP_TO_LABEL(error); + } + b_stackref = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; + l_stackref = left; + r_stackref = right; + /* End of uop copied from bytecodes for constant evaluation */ + (void)l_stackref; + (void)r_stackref; + b = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(b_stackref)); + if (sym_is_const(ctx, b)) { + PyObject *result = sym_get_const(ctx, b); + if (_Py_IsImmortal(result)) { + // Replace with _INSERT_2_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result + ADD_OP(_INSERT_2_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); + } + } + CHECK_STACK_BOUNDS(1); + stack_pointer[-2] = b; + stack_pointer[-1] = l; + stack_pointer[0] = r; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + break; + } + } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = b; stack_pointer[-1] = l; diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index a0ee175fd10..2614bcd430a 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -283,7 +283,8 @@ _Py_uop_sym_is_safe_const(JitOptContext *ctx, JitOptRef sym) (typ == &PyFloat_Type) || (typ == &_PyNone_Type) || (typ == &PyBool_Type) || - (typ == &PyFrozenDict_Type); + (typ == &PyFrozenDict_Type) || + (typ == &PyFrozenSet_Type); } void From c398490fbf15ede5de3389b4ca4e32fb9a7c5d67 Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Sat, 4 Apr 2026 23:34:55 +0800 Subject: [PATCH 405/775] gh-148074: Fix `typeobject.c` missing error return (#148075) --- Objects/typeobject.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index b19aee6338d..0ac5377d168 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9345,6 +9345,7 @@ type_ready_post_checks(PyTypeObject *type) PyErr_Format(PyExc_SystemError, "type %s has a tp_dictoffset that is too small", type->tp_name); + return -1; } } return 0; From 853dafe23a138459be544065251d0150df680a2c Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Sun, 5 Apr 2026 00:40:12 +0900 Subject: [PATCH 406/775] gh-148083: Prevent constant folding when lhs is container types (gh-148090) --- Include/internal/pycore_optimizer.h | 1 + Python/optimizer_analysis.c | 1 + Python/optimizer_bytecodes.c | 6 ++++-- Python/optimizer_cases.c.h | 6 ++++-- Python/optimizer_symbols.c | 14 ++++++++++++++ 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 2986afb142b..cf01c620476 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -394,6 +394,7 @@ extern JitOptRef _Py_uop_sym_new_type( extern JitOptRef _Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val); extern JitOptRef _Py_uop_sym_new_const_steal(JitOptContext *ctx, PyObject *const_val); bool _Py_uop_sym_is_safe_const(JitOptContext *ctx, JitOptRef sym); +bool _Py_uop_sym_is_not_container(JitOptRef sym); _PyStackRef _Py_uop_sym_get_const_as_stackref(JitOptContext *ctx, JitOptRef sym); extern JitOptRef _Py_uop_sym_new_null(JitOptContext *ctx); extern bool _Py_uop_sym_has_type(JitOptRef sym); diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 2953311b392..92e1c081d52 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -252,6 +252,7 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_is_not_null _Py_uop_sym_is_not_null #define sym_is_const _Py_uop_sym_is_const #define sym_is_safe_const _Py_uop_sym_is_safe_const +#define sym_is_not_container _Py_uop_sym_is_not_container #define sym_get_const _Py_uop_sym_get_const #define sym_new_const_steal _Py_uop_sym_new_const_steal #define sym_get_const_as_stackref _Py_uop_sym_get_const_as_stackref diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 6e9a34384ba..f2645553513 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -515,7 +515,8 @@ dummy_func(void) { res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; - if (sym_matches_type(dict_st, &PyFrozenDict_Type)) { + if (sym_is_not_container(sub_st) && + sym_matches_type(dict_st, &PyFrozenDict_Type)) { REPLACE_OPCODE_IF_EVALUATES_PURE(dict_st, sub_st, res); } } @@ -706,7 +707,8 @@ dummy_func(void) { b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; - if (sym_matches_type(right, &PyFrozenSet_Type)) { + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenSet_Type)) { REPLACE_OPCODE_IF_EVALUATES_PURE(left, right, b); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index dc00b6bc139..fb3ec39a42e 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1462,7 +1462,8 @@ res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; - if (sym_matches_type(dict_st, &PyFrozenDict_Type)) { + if (sym_is_not_container(sub_st) && + sym_matches_type(dict_st, &PyFrozenDict_Type)) { if ( sym_is_safe_const(ctx, dict_st) && sym_is_safe_const(ctx, sub_st) @@ -2993,7 +2994,8 @@ b = sym_new_type(ctx, &PyBool_Type); l = left; r = right; - if (sym_matches_type(right, &PyFrozenSet_Type)) { + if (sym_is_not_container(left) && + sym_matches_type(right, &PyFrozenSet_Type)) { if ( sym_is_safe_const(ctx, left) && sym_is_safe_const(ctx, right) diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index 2614bcd430a..6230b894869 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -287,6 +287,20 @@ _Py_uop_sym_is_safe_const(JitOptContext *ctx, JitOptRef sym) (typ == &PyFrozenSet_Type); } +bool +_Py_uop_sym_is_not_container(JitOptRef sym) +{ + PyTypeObject *typ = _Py_uop_sym_get_type(sym); + if (typ == NULL) { + return false; + } + return (typ == &PyLong_Type) || + (typ == &PyFloat_Type) || + (typ == &PyUnicode_Type) || + (typ == &_PyNone_Type) || + (typ == &PyBool_Type); +} + void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *typ) { From fbdbea949f0d3e33c5566edd4da102d3db0674d5 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:13:17 +0300 Subject: [PATCH 407/775] Regex HOWTO: invalid string literals result in `SyntaxWarning` (#148092) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Doc/howto/regex.rst | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index 7486a378dbb..84ec535ca98 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -1,7 +1,7 @@ .. _regex-howto: **************************** - Regular Expression HOWTO + Regular expression HOWTO **************************** :Author: A.M. Kuchling @@ -47,7 +47,7 @@ Python code to do the processing; while Python code will be slower than an elaborate regular expression, it will also probably be more understandable. -Simple Patterns +Simple patterns =============== We'll start by learning about the simplest possible regular expressions. Since @@ -59,7 +59,7 @@ expressions (deterministic and non-deterministic finite automata), you can refer to almost any textbook on writing compilers. -Matching Characters +Matching characters ------------------- Most letters and characters will simply match themselves. For example, the @@ -159,7 +159,7 @@ match even a newline. ``.`` is often used where you want to match "any character". -Repeating Things +Repeating things ---------------- Being able to match varying sets of characters is the first thing regular @@ -210,7 +210,7 @@ this RE against the string ``'abcbd'``. | | | ``[bcd]*`` is only matching | | | | ``bc``. | +------+-----------+---------------------------------+ -| 6 | ``abcb`` | Try ``b`` again. This time | +| 7 | ``abcb`` | Try ``b`` again. This time | | | | the character at the | | | | current position is ``'b'``, so | | | | it succeeds. | @@ -255,7 +255,7 @@ is equivalent to ``+``, and ``{0,1}`` is the same as ``?``. It's better to use to read. -Using Regular Expressions +Using regular expressions ========================= Now that we've looked at some simple regular expressions, how do we actually use @@ -264,7 +264,7 @@ expression engine, allowing you to compile REs into objects and then perform matches with them. -Compiling Regular Expressions +Compiling regular expressions ----------------------------- Regular expressions are compiled into pattern objects, which have @@ -295,7 +295,7 @@ disadvantage which is the topic of the next section. .. _the-backslash-plague: -The Backslash Plague +The backslash plague -------------------- As stated earlier, regular expressions use the backslash character (``'\'``) to @@ -335,7 +335,7 @@ expressions will often be written in Python code using this raw string notation. In addition, special escape sequences that are valid in regular expressions, but not valid as Python string literals, now result in a -:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`, +:exc:`SyntaxWarning` and will eventually become a :exc:`SyntaxError`, which means the sequences will be invalid if raw string notation or escaping the backslashes isn't used. @@ -351,7 +351,7 @@ the backslashes isn't used. +-------------------+------------------+ -Performing Matches +Performing matches ------------------ Once you have an object representing a compiled regular expression, what do you @@ -369,10 +369,10 @@ for a complete listing. | | location where this RE matches. | +------------------+-----------------------------------------------+ | ``findall()`` | Find all substrings where the RE matches, and | -| | returns them as a list. | +| | return them as a list. | +------------------+-----------------------------------------------+ | ``finditer()`` | Find all substrings where the RE matches, and | -| | returns them as an :term:`iterator`. | +| | return them as an :term:`iterator`. | +------------------+-----------------------------------------------+ :meth:`~re.Pattern.match` and :meth:`~re.Pattern.search` return ``None`` if no match can be found. If @@ -473,7 +473,7 @@ Two pattern methods return all of the matches for a pattern. The ``r`` prefix, making the literal a raw string literal, is needed in this example because escape sequences in a normal "cooked" string literal that are not recognized by Python, as opposed to regular expressions, now result in a -:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`. See +:exc:`SyntaxWarning` and will eventually become a :exc:`SyntaxError`. See :ref:`the-backslash-plague`. :meth:`~re.Pattern.findall` has to create the entire list before it can be returned as the @@ -491,7 +491,7 @@ result. The :meth:`~re.Pattern.finditer` method returns a sequence of (29, 31) -Module-Level Functions +Module-level functions ---------------------- You don't have to create a pattern object and call its methods; the @@ -518,7 +518,7 @@ Outside of loops, there's not much difference thanks to the internal cache. -Compilation Flags +Compilation flags ----------------- .. currentmodule:: re @@ -642,7 +642,7 @@ of each one. whitespace is in a character class or preceded by an unescaped backslash; this lets you organize and indent the RE more clearly. This flag also lets you put comments within a RE that will be ignored by the engine; comments are marked by - a ``'#'`` that's neither in a character class or preceded by an unescaped + a ``'#'`` that's neither in a character class nor preceded by an unescaped backslash. For example, here's a RE that uses :const:`re.VERBOSE`; see how much easier it @@ -669,7 +669,7 @@ of each one. to understand than the version using :const:`re.VERBOSE`. -More Pattern Power +More pattern power ================== So far we've only covered a part of the features of regular expressions. In @@ -679,7 +679,7 @@ retrieve portions of the text that was matched. .. _more-metacharacters: -More Metacharacters +More metacharacters ------------------- There are some metacharacters that we haven't covered yet. Most of them will be @@ -875,7 +875,7 @@ Backreferences like this aren't often useful for just searching through a string find out that they're *very* useful when performing string substitutions. -Non-capturing and Named Groups +Non-capturing and named groups ------------------------------ Elaborate REs may use many groups, both to capture substrings of interest, and @@ -979,7 +979,7 @@ current point. The regular expression for finding doubled words, 'the the' -Lookahead Assertions +Lookahead assertions -------------------- Another zero-width assertion is the lookahead assertion. Lookahead assertions @@ -1061,7 +1061,7 @@ end in either ``bat`` or ``exe``: ``.*[.](?!bat$|exe$)[^.]*$`` -Modifying Strings +Modifying strings ================= Up to this point, we've simply performed searches against a static string. @@ -1083,7 +1083,7 @@ using the following pattern methods: +------------------+-----------------------------------------------+ -Splitting Strings +Splitting strings ----------------- The :meth:`~re.Pattern.split` method of a pattern splits a string apart @@ -1137,7 +1137,7 @@ argument, but is otherwise the same. :: ['Words', 'words, words.'] -Search and Replace +Search and replace ------------------ Another common task is to find all the matches for a pattern, and replace them @@ -1236,7 +1236,7 @@ pattern object as the first parameter, or use embedded modifiers in the pattern string, e.g. ``sub("(?i)b+", "x", "bbbb BBBB")`` returns ``'x x'``. -Common Problems +Common problems =============== Regular expressions are a powerful tool for some applications, but in some ways @@ -1244,7 +1244,7 @@ their behaviour isn't intuitive and at times they don't behave the way you may expect them to. This section will point out some of the most common pitfalls. -Use String Methods +Use string methods ------------------ Sometimes using the :mod:`re` module is a mistake. If you're matching a fixed @@ -1310,7 +1310,7 @@ string and then backtracking to find a match for the rest of the RE. Use :func:`re.search` instead. -Greedy versus Non-Greedy +Greedy versus non-greedy ------------------------ When repeating a regular expression, as in ``a*``, the resulting action is to @@ -1388,9 +1388,9 @@ Feedback ======== Regular expressions are a complicated topic. Did this document help you -understand them? Were there parts that were unclear, or Problems you +understand them? Were there parts that were unclear, or problems you encountered that weren't covered here? If so, please send suggestions for -improvements to the author. +improvements to the :ref:`issue tracker `. The most complete book on regular expressions is almost certainly Jeffrey Friedl's Mastering Regular Expressions, published by O'Reilly. Unfortunately, From b1d2d9829cfb33f0487ce00c19fa57ddefeb1b50 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Sat, 4 Apr 2026 17:45:52 +0100 Subject: [PATCH 408/775] Docs: Fix a typo in the 'Non-ASCII characters in names' section (#148043) --- Doc/reference/lexical_analysis.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index ae541680c53..f3ed1539493 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -560,7 +560,7 @@ start with a character in the "letter-like" set ``xid_start``, and the remaining characters must be in the "letter- and digit-like" set ``xid_continue``. -These sets based on the *XID_Start* and *XID_Continue* sets as defined by the +These sets are based on the *XID_Start* and *XID_Continue* sets as defined by the Unicode standard annex `UAX-31`_. Python's ``xid_start`` additionally includes the underscore (``_``). Note that Python does not necessarily conform to `UAX-31`_. From 21fb9dc71d2dd4ea9faf966385c102be20ce99e8 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Sat, 4 Apr 2026 18:42:30 +0100 Subject: [PATCH 409/775] gh-146527: Heap-allocate gc_stats to avoid bloating PyInterpreterState (#148057) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gc_stats struct contains ring buffers of gc_generation_stats entries (11 young + 3×2 old on default builds). Embedding it inline in _gc_runtime_state, which is itself inline in PyInterpreterState, pushed fields like _gil.locked and threads.head to offsets beyond what out-of-process profilers and debuggers can reasonably read in a single buffer (e.g. offset 9384 for _gil.locked vs an 8 KiB read buffer). Heap-allocate generation_stats via PyMem_RawCalloc in _PyGC_Init and free it in _PyGC_Fini. This shrinks PyInterpreterState by ~1.6 KiB and keeps the GIL, thread-list, and other frequently-inspected fields at stable, low offsets. --- Include/internal/pycore_interp_structs.h | 2 +- Modules/gcmodule.c | 6 +++--- Python/gc.c | 15 +++++++++++---- Python/gc_free_threading.c | 11 +++++++++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index f76d4f41c55..c4b08464266 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -248,7 +248,7 @@ struct _gc_runtime_state { struct gc_generation old[2]; /* a permanent generation which won't be collected */ struct gc_generation permanent_generation; - struct gc_stats generation_stats; + struct gc_stats *generation_stats; /* true if we are currently running the collector */ int collecting; // The frame that started the current collection. It might be NULL even when diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index c21b61589bd..8da28130e9d 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -347,9 +347,9 @@ gc_get_stats_impl(PyObject *module) /* To get consistent values despite allocations while constructing the result list, we use a snapshot of the running stats. */ GCState *gcstate = get_gc_state(); - stats[0] = gcstate->generation_stats.young.items[gcstate->generation_stats.young.index]; - stats[1] = gcstate->generation_stats.old[0].items[gcstate->generation_stats.old[0].index]; - stats[2] = gcstate->generation_stats.old[1].items[gcstate->generation_stats.old[1].index]; + stats[0] = gcstate->generation_stats->young.items[gcstate->generation_stats->young.index]; + stats[1] = gcstate->generation_stats->old[0].items[gcstate->generation_stats->old[0].index]; + stats[2] = gcstate->generation_stats->old[1].items[gcstate->generation_stats->old[1].index]; PyObject *result = PyList_New(0); if (result == NULL) diff --git a/Python/gc.c b/Python/gc.c index 7bca40f6e3f..284ac725d37 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -177,6 +177,11 @@ _PyGC_Init(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; + gcstate->generation_stats = PyMem_RawCalloc(1, sizeof(struct gc_stats)); + if (gcstate->generation_stats == NULL) { + return _PyStatus_NO_MEMORY(); + } + gcstate->garbage = PyList_New(0); if (gcstate->garbage == NULL) { return _PyStatus_NO_MEMORY(); @@ -1398,13 +1403,13 @@ static struct gc_generation_stats * gc_get_stats(GCState *gcstate, int gen) { if (gen == 0) { - struct gc_young_stats_buffer *buffer = &gcstate->generation_stats.young; + struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young; buffer->index = (buffer->index + 1) % GC_YOUNG_STATS_SIZE; struct gc_generation_stats *stats = &buffer->items[buffer->index]; return stats; } else { - struct gc_old_stats_buffer *buffer = &gcstate->generation_stats.old[gen - 1]; + struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1]; buffer->index = (buffer->index + 1) % GC_OLD_STATS_SIZE; struct gc_generation_stats *stats = &buffer->items[buffer->index]; return stats; @@ -1415,12 +1420,12 @@ static struct gc_generation_stats * gc_get_prev_stats(GCState *gcstate, int gen) { if (gen == 0) { - struct gc_young_stats_buffer *buffer = &gcstate->generation_stats.young; + struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young; struct gc_generation_stats *stats = &buffer->items[buffer->index]; return stats; } else { - struct gc_old_stats_buffer *buffer = &gcstate->generation_stats.old[gen - 1]; + struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1]; struct gc_generation_stats *stats = &buffer->items[buffer->index]; return stats; } @@ -2299,6 +2304,8 @@ _PyGC_Fini(PyInterpreterState *interp) GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); + PyMem_RawFree(gcstate->generation_stats); + gcstate->generation_stats = NULL; /* Prevent a subtle bug that affects sub-interpreters that use basic * single-phase init extensions (m_size == -1). Those extensions cause objects diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index 7ad60a73a56..4b46ca04f56 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -1698,6 +1698,11 @@ _PyGC_Init(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; + gcstate->generation_stats = PyMem_RawCalloc(1, sizeof(struct gc_stats)); + if (gcstate->generation_stats == NULL) { + return _PyStatus_NO_MEMORY(); + } + gcstate->garbage = PyList_New(0); if (gcstate->garbage == NULL) { return _PyStatus_NO_MEMORY(); @@ -2387,12 +2392,12 @@ static struct gc_generation_stats * get_stats(GCState *gcstate, int gen) { if (gen == 0) { - struct gc_young_stats_buffer *buffer = &gcstate->generation_stats.young; + struct gc_young_stats_buffer *buffer = &gcstate->generation_stats->young; struct gc_generation_stats *stats = &buffer->items[buffer->index]; return stats; } else { - struct gc_old_stats_buffer *buffer = &gcstate->generation_stats.old[gen - 1]; + struct gc_old_stats_buffer *buffer = &gcstate->generation_stats->old[gen - 1]; struct gc_generation_stats *stats = &buffer->items[buffer->index]; return stats; } @@ -2831,6 +2836,8 @@ _PyGC_Fini(PyInterpreterState *interp) GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); + PyMem_RawFree(gcstate->generation_stats); + gcstate->generation_stats = NULL; /* We expect that none of this interpreters objects are shared with other interpreters. From 75be902a13c670a1ea16aee3644548723b7d7407 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Sat, 4 Apr 2026 19:02:16 +0100 Subject: [PATCH 410/775] Docs: Standardize documentation authors (#148102) --- Doc/conf.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py index f021c9eabe4..e2dff74538a 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -73,6 +73,7 @@ # General substitutions. project = 'Python' copyright = "2001 Python Software Foundation" +_doc_authors = 'Python documentation authors' # We look for the Include/patchlevel.h file in the current Python source tree # and replace the values accordingly. @@ -361,69 +362,74 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). -_stdauthor = 'The Python development team' latex_documents = [ - ('c-api/index', 'c-api.tex', 'The Python/C API', _stdauthor, 'manual'), + ('c-api/index', 'c-api.tex', 'The Python/C API', _doc_authors, 'manual'), ( 'extending/index', 'extending.tex', 'Extending and Embedding Python', - _stdauthor, + _doc_authors, 'manual', ), ( 'installing/index', 'installing.tex', 'Installing Python Modules', - _stdauthor, + _doc_authors, 'manual', ), ( 'library/index', 'library.tex', 'The Python Library Reference', - _stdauthor, + _doc_authors, 'manual', ), ( 'reference/index', 'reference.tex', 'The Python Language Reference', - _stdauthor, + _doc_authors, 'manual', ), ( 'tutorial/index', 'tutorial.tex', 'Python Tutorial', - _stdauthor, + _doc_authors, 'manual', ), ( 'using/index', 'using.tex', 'Python Setup and Usage', - _stdauthor, + _doc_authors, 'manual', ), ( 'faq/index', 'faq.tex', 'Python Frequently Asked Questions', - _stdauthor, + _doc_authors, 'manual', ), ( 'whatsnew/' + version, 'whatsnew.tex', 'What\'s New in Python', - 'A. M. Kuchling', + _doc_authors, 'howto', ), ] # Collect all HOWTOs individually latex_documents.extend( - ('howto/' + fn[:-4], 'howto-' + fn[:-4] + '.tex', '', _stdauthor, 'howto') + ( + 'howto/' + fn[:-4], + 'howto-' + fn[:-4] + '.tex', + '', + _doc_authors, + 'howto', + ) for fn in os.listdir('howto') if fn.endswith('.rst') and fn != 'index.rst' ) @@ -434,7 +440,7 @@ # Options for Epub output # ----------------------- -epub_author = 'Python Documentation Authors' +epub_author = _doc_authors epub_publisher = 'Python Software Foundation' epub_exclude_files = ( 'index.xhtml', From 8bf8bf92921a13cc18f7d1b5bed8bd32c8485ba4 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 4 Apr 2026 21:26:16 +0300 Subject: [PATCH 411/775] gh-73613: Support Base32 and Base64 without padding (GH-147974) Add the padded parameter in functions related to Base32 and Base64 codecs in the binascii and base64 modules. In the encoding functions it controls whether the pad character can be added in the output, in the decoding functions it controls whether padding is required in input. Padding of input no longer required in base64.urlsafe_b64decode() by default. --- Doc/library/base64.rst | 57 +++++-- Doc/library/binascii.rst | 32 +++- Doc/whatsnew/3.15.rst | 18 +++ .../pycore_global_objects_fini_generated.h | 1 + Include/internal/pycore_global_strings.h | 1 + .../internal/pycore_runtime_init_generated.h | 1 + .../internal/pycore_unicodeobject_generated.h | 4 + Lib/base64.py | 53 ++++--- Lib/test/test_base64.py | 110 +++++++++++++ Lib/test/test_binascii.py | 66 ++++++++ ...6-04-01-18-17-55.gh-issue-73613.PLEebm.rst | 7 + Modules/binascii.c | 88 +++++++---- Modules/clinic/binascii.c.h | 145 ++++++++++++------ 13 files changed, 463 insertions(+), 120 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 1a1785cb587..425dff8f2a9 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -51,7 +51,7 @@ The :rfc:`4648` encodings are suitable for encoding binary data so that it can b safely sent by email, used as parts of URLs, or included as part of an HTTP POST request. -.. function:: b64encode(s, altchars=None, *, wrapcol=0) +.. function:: b64encode(s, altchars=None, *, padded=True, wrapcol=0) Encode the :term:`bytes-like object` *s* using Base64 and return the encoded :class:`bytes`. @@ -61,6 +61,10 @@ POST request. This allows an application to e.g. generate URL or filesystem safe Base64 strings. The default is ``None``, for which the standard Base64 alphabet is used. + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 4. + If *padded* is false, do not add the pad characters. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. @@ -69,11 +73,11 @@ POST request. :exc:`TypeError` if *altchars* is not a :term:`bytes-like object`. .. versionchanged:: 3.15 - Added the *wrapcol* parameter. + Added the *padded* and *wrapcol* parameters. -.. function:: b64decode(s, altchars=None, validate=False) - b64decode(s, altchars=None, validate=True, *, ignorechars) +.. function:: b64decode(s, altchars=None, validate=False, *, padded=True) + b64decode(s, altchars=None, validate=True, *, ignorechars, padded=True) Decode the Base64 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -82,6 +86,11 @@ POST request. of length 2 which specifies the alternative alphabet used instead of the ``+`` and ``/`` characters. + If *padded* is true, the last group of 4 base 64 alphabet characters must + be padded with the '=' character. + If *padded* is false, the '=' character is treated as other non-alphabet + characters (depending on the value of *validate* and *ignorechars*). + A :exc:`binascii.Error` exception is raised if *s* is incorrectly padded. @@ -106,7 +115,7 @@ POST request. For more information about the strict base64 check, see :func:`binascii.a2b_base64` .. versionchanged:: 3.15 - Added the *ignorechars* parameter. + Added the *ignorechars* and *padded* parameters. .. deprecated:: 3.15 Accepting the ``+`` and ``/`` characters with an alternative alphabet @@ -125,16 +134,19 @@ POST request. Base64 alphabet and return the decoded :class:`bytes`. -.. function:: urlsafe_b64encode(s) +.. function:: urlsafe_b64encode(s, *, padded=True) Encode :term:`bytes-like object` *s* using the URL- and filesystem-safe alphabet, which substitutes ``-`` instead of ``+`` and ``_`` instead of ``/`` in the standard Base64 alphabet, and return the encoded :class:`bytes`. The result - can still contain ``=``. + can still contain ``=`` if *padded* is true (default). + + .. versionchanged:: next + Added the *padded* parameter. -.. function:: urlsafe_b64decode(s) +.. function:: urlsafe_b64decode(s, *, padded=False) Decode :term:`bytes-like object` or ASCII string *s* using the URL- and filesystem-safe @@ -142,24 +154,32 @@ POST request. ``/`` in the standard Base64 alphabet, and return the decoded :class:`bytes`. + .. versionchanged:: next + Added the *padded* parameter. + Padding of input is no longer required by default. + .. deprecated:: 3.15 Accepting the ``+`` and ``/`` characters is now deprecated. -.. function:: b32encode(s, *, wrapcol=0) +.. function:: b32encode(s, *, padded=True, wrapcol=0) Encode the :term:`bytes-like object` *s* using Base32 and return the encoded :class:`bytes`. + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 8. + If *padded* is false, do not add the pad characters. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not add any newlines. .. versionchanged:: next - Added the *wrapcol* parameter. + Added the *padded* and *wrapcol* parameters. -.. function:: b32decode(s, casefold=False, map01=None, *, ignorechars=b'') +.. function:: b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b'') Decode the Base32 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. @@ -175,6 +195,11 @@ POST request. digit 0 is always mapped to the letter O). For security purposes the default is ``None``, so that 0 and 1 are not allowed in the input. + If *padded* is true, the last group of 8 base 32 alphabet characters must + be padded with the '=' character. + If *padded* is false, the '=' character is treated as other non-alphabet + characters (depending on the value of *ignorechars*). + *ignorechars* should be a :term:`bytes-like object` containing characters to ignore from the input. @@ -183,10 +208,10 @@ POST request. input. .. versionchanged:: next - Added the *ignorechars* parameter. + Added the *ignorechars* and *padded* parameters. -.. function:: b32hexencode(s, *, wrapcol=0) +.. function:: b32hexencode(s, *, padded=True, wrapcol=0) Similar to :func:`b32encode` but uses the Extended Hex Alphabet, as defined in :rfc:`4648`. @@ -194,10 +219,10 @@ POST request. .. versionadded:: 3.10 .. versionchanged:: next - Added the *wrapcol* parameter. + Added the *padded* and *wrapcol* parameters. -.. function:: b32hexdecode(s, casefold=False, *, ignorechars=b'') +.. function:: b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'') Similar to :func:`b32decode` but uses the Extended Hex Alphabet, as defined in :rfc:`4648`. @@ -210,7 +235,7 @@ POST request. .. versionadded:: 3.10 .. versionchanged:: next - Added the *ignorechars* parameter. + Added the *ignorechars* and *padded* parameters. .. function:: b16encode(s, *, wrapcol=0) diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 4a82d0742ae..4f2edb7eff8 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -48,8 +48,8 @@ The :mod:`!binascii` module defines the following functions: Added the *backtick* parameter. -.. function:: a2b_base64(string, /, *, alphabet=BASE64_ALPHABET, strict_mode=False) - a2b_base64(string, /, *, ignorechars, alphabet=BASE64_ALPHABET, strict_mode=True) +.. function:: a2b_base64(string, /, *, padded=True, alphabet=BASE64_ALPHABET, strict_mode=False) + a2b_base64(string, /, *, ignorechars, padded=True, alphabet=BASE64_ALPHABET, strict_mode=True) Convert a block of base64 data back to binary and return the binary data. More than one line may be passed at a time. @@ -57,6 +57,11 @@ The :mod:`!binascii` module defines the following functions: Optional *alphabet* must be a :class:`bytes` object of length 64 which specifies an alternative alphabet. + If *padded* is true, the last group of 4 base 64 alphabet characters must + be padded with the '=' character. + If *padded* is false, the '=' character is treated as other non-alphabet + characters (depending on the value of *strict_mode* and *ignorechars*). + If *ignorechars* is specified, it should be a :term:`bytes-like object` containing characters to ignore from the input when *strict_mode* is true. If *ignorechars* contains the pad character ``'='``, the pad characters @@ -79,14 +84,18 @@ The :mod:`!binascii` module defines the following functions: Added the *strict_mode* parameter. .. versionchanged:: 3.15 - Added the *alphabet* and *ignorechars* parameters. + Added the *alphabet*, *ignorechars* and *padded* parameters. -.. function:: b2a_base64(data, *, alphabet=BASE64_ALPHABET, wrapcol=0, newline=True) +.. function:: b2a_base64(data, *, padded=True, alphabet=BASE64_ALPHABET, wrapcol=0, newline=True) Convert binary data to a line(s) of ASCII characters in base64 coding, as specified in :rfc:`4648`. + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 4. + If *padded* is false, do not add the pad characters. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. @@ -98,7 +107,7 @@ The :mod:`!binascii` module defines the following functions: Added the *newline* parameter. .. versionchanged:: 3.15 - Added the *alphabet* and *wrapcol* parameters. + Added the *alphabet*, *padded* and *wrapcol* parameters. .. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b'') @@ -190,7 +199,7 @@ The :mod:`!binascii` module defines the following functions: .. versionadded:: 3.15 -.. function:: a2b_base32(string, /, *, alphabet=BASE32_ALPHABET, ignorechars=b'') +.. function:: a2b_base32(string, /, *, padded=True, alphabet=BASE32_ALPHABET, ignorechars=b'') Convert base32 data back to binary and return the binary data. @@ -208,6 +217,11 @@ The :mod:`!binascii` module defines the following functions: Optional *alphabet* must be a :class:`bytes` object of length 32 which specifies an alternative alphabet. + If *padded* is true, the last group of 8 base 32 alphabet characters must + be padded with the '=' character. + If *padded* is false, the '=' character is treated as other non-alphabet + characters (depending on the value of *ignorechars*). + *ignorechars* should be a :term:`bytes-like object` containing characters to ignore from the input. If *ignorechars* contains the pad character ``'='``, the pad characters @@ -218,7 +232,7 @@ The :mod:`!binascii` module defines the following functions: .. versionadded:: next -.. function:: b2a_base32(data, /, *, alphabet=BASE32_ALPHABET, wrapcol=0) +.. function:: b2a_base32(data, /, *, padded=True, alphabet=BASE32_ALPHABET, wrapcol=0) Convert binary data to a line of ASCII characters in base32 coding, as specified in :rfc:`4648`. The return value is the converted line. @@ -226,6 +240,10 @@ The :mod:`!binascii` module defines the following functions: Optional *alphabet* must be a :term:`bytes-like object` of length 32 which specifies an alternative alphabet. + If *padded* is true (default), pad the encoded data with the '=' + character to a size multiple of 8. + If *padded* is false, do not add the pad characters. + If *wrapcol* is non-zero, insert a newline (``b'\n'``) character after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 287109035f1..d1d4b92bcf4 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -657,6 +657,13 @@ base64 * Added the *pad* parameter in :func:`~base64.z85encode`. (Contributed by Hauke Dämpfling in :gh:`143103`.) +* Added the *padded* parameter in + :func:`~base64.b32encode`, :func:`~base64.b32decode`, + :func:`~base64.b32hexencode`, :func:`~base64.b32hexdecode`, + :func:`~base64.b64encode`, :func:`~base64.b64decode`, + :func:`~base64.urlsafe_b64encode`, and :func:`~base64.urlsafe_b64decode`. + (Contributed by Serhiy Storchaka in :gh:`73613`.) + * Added the *wrapcol* parameter in :func:`~base64.b16encode`, :func:`~base64.b32encode`, :func:`~base64.b32hexencode`, :func:`~base64.b64encode`, :func:`~base64.b85encode`, and @@ -686,6 +693,11 @@ binascii (Contributed by James Seo and Serhiy Storchaka in :gh:`101178`.) +* Added the *padded* parameter in + :func:`~binascii.b2a_base32`, :func:`~binascii.a2b_base32`, + :func:`~binascii.b2a_base64`, and :func:`~binascii.a2b_base64`. + (Contributed by Serhiy Storchaka in :gh:`73613`.) + * Added the *wrapcol* parameter in :func:`~binascii.b2a_base64`. (Contributed by Serhiy Storchaka in :gh:`143214`.) @@ -2027,3 +2039,9 @@ that may require changes to your code. *dest* is now ``'foo'`` instead of ``'f'``. Pass an explicit *dest* argument to preserve the old behavior. (Contributed by Serhiy Storchaka in :gh:`138697`.) + +* Padding of input no longer required in :func:`base64.urlsafe_b64decode`. + Pass a new argument ``padded=True`` or use :func:`base64.b64decode` + with argument ``altchars=b'-_'`` (this works with older Python versions) + to make padding required. + (Contributed by Serhiy Storchaka in :gh:`73613`.) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 4b1e289c6ff..beae65213a2 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1974,6 +1974,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(overlapped)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(owner)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pad)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(padded)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pages)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(parameter)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(parent)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 6ee649b59a5..bb1c6dbaf03 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -697,6 +697,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(overlapped) STRUCT_FOR_ID(owner) STRUCT_FOR_ID(pad) + STRUCT_FOR_ID(padded) STRUCT_FOR_ID(pages) STRUCT_FOR_ID(parameter) STRUCT_FOR_ID(parent) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 778db946c2a..64b029797ab 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1972,6 +1972,7 @@ extern "C" { INIT_ID(overlapped), \ INIT_ID(owner), \ INIT_ID(pad), \ + INIT_ID(padded), \ INIT_ID(pages), \ INIT_ID(parameter), \ INIT_ID(parent), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index bd8f50ff0ee..461ee36dceb 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -2568,6 +2568,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(padded); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(pages); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Lib/base64.py b/Lib/base64.py index 47b90643e8d..a94bec4d031 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -46,13 +46,15 @@ def _bytes_from_decode_data(s): # Base64 encoding/decoding uses binascii -def b64encode(s, altchars=None, *, wrapcol=0): +def b64encode(s, altchars=None, *, padded=True, wrapcol=0): """Encode the bytes-like object s using Base64 and return a bytes object. Optional altchars should be a byte string of length 2 which specifies an alternative alphabet for the '+' and '/' characters. This allows an application to e.g. generate url or filesystem safe Base64 strings. + If padded is false, omit padding in the output. + If wrapcol is non-zero, insert a newline (b'\\n') character after at most every wrapcol characters. """ @@ -60,18 +62,21 @@ def b64encode(s, altchars=None, *, wrapcol=0): if len(altchars) != 2: raise ValueError(f'invalid altchars: {altchars!r}') alphabet = binascii.BASE64_ALPHABET[:-2] + altchars - return binascii.b2a_base64(s, wrapcol=wrapcol, newline=False, + return binascii.b2a_base64(s, padded=padded, wrapcol=wrapcol, newline=False, alphabet=alphabet) - return binascii.b2a_base64(s, wrapcol=wrapcol, newline=False) + return binascii.b2a_base64(s, padded=padded, wrapcol=wrapcol, newline=False) -def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, *, ignorechars=_NOT_SPECIFIED): +def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, + *, padded=True, ignorechars=_NOT_SPECIFIED): """Decode the Base64 encoded bytes-like object or ASCII string s. Optional altchars must be a bytes-like object or ASCII string of length 2 which specifies the alternative alphabet used instead of the '+' and '/' characters. + If padded is false, padding in input is not required. + The result is returned as a bytes object. A binascii.Error is raised if s is incorrectly padded. @@ -105,11 +110,11 @@ def b64decode(s, altchars=None, validate=_NOT_SPECIFIED, *, ignorechars=_NOT_SPE alphabet = binascii.BASE64_ALPHABET[:-2] + altchars return binascii.a2b_base64(s, strict_mode=validate, alphabet=alphabet, - ignorechars=ignorechars) + padded=padded, ignorechars=ignorechars) if ignorechars is _NOT_SPECIFIED: ignorechars = b'' result = binascii.a2b_base64(s, strict_mode=validate, - ignorechars=ignorechars) + padded=padded, ignorechars=ignorechars) if badchar is not None: import warnings if validate: @@ -145,17 +150,19 @@ def standard_b64decode(s): _urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/') -def urlsafe_b64encode(s): +def urlsafe_b64encode(s, *, padded=True): """Encode bytes using the URL- and filesystem-safe Base64 alphabet. Argument s is a bytes-like object to encode. The result is returned as a bytes object. The alphabet uses '-' instead of '+' and '_' instead of '/'. + + If padded is false, omit padding in the output. """ - return binascii.b2a_base64(s, newline=False, + return binascii.b2a_base64(s, padded=padded, newline=False, alphabet=binascii.URLSAFE_BASE64_ALPHABET) -def urlsafe_b64decode(s): +def urlsafe_b64decode(s, *, padded=False): """Decode bytes using the URL- and filesystem-safe Base64 alphabet. Argument s is a bytes-like object or ASCII string to decode. The result @@ -164,6 +171,8 @@ def urlsafe_b64decode(s): alphabet, and are not a plus '+' or slash '/', are discarded prior to the padding check. + If padded is false, padding in input is not required. + The alphabet uses '-' instead of '+' and '_' instead of '/'. """ s = _bytes_from_decode_data(s) @@ -173,7 +182,7 @@ def urlsafe_b64decode(s): badchar = b break s = s.translate(_urlsafe_decode_translation) - result = binascii.a2b_base64(s, strict_mode=False) + result = binascii.a2b_base64(s, strict_mode=False, padded=padded) if badchar is not None: import warnings warnings.warn(f'invalid character {chr(badchar)!a} in URL-safe Base64 data ' @@ -187,6 +196,8 @@ def urlsafe_b64decode(s): _B32_ENCODE_DOCSTRING = ''' Encode the bytes-like objects using {encoding} and return a bytes object. +If padded is false, omit padding in the output. + If wrapcol is non-zero, insert a newline (b'\\n') character after at most every wrapcol characters. ''' @@ -196,6 +207,8 @@ def urlsafe_b64decode(s): Optional casefold is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default is False. +If padded is false, padding in input is not required. + ignorechars should be a byte string containing characters to ignore from the input. {extra_args} @@ -213,11 +226,11 @@ def urlsafe_b64decode(s): 0 and 1 are not allowed in the input. ''' -def b32encode(s, *, wrapcol=0): - return binascii.b2a_base32(s, wrapcol=wrapcol) +def b32encode(s, *, padded=True, wrapcol=0): + return binascii.b2a_base32(s, padded=padded, wrapcol=wrapcol) b32encode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32') -def b32decode(s, casefold=False, map01=None, *, ignorechars=b''): +def b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b''): s = _bytes_from_decode_data(s) # Handle section 2.4 zero and one mapping. The flag map01 will be either # False, or the character to map the digit 1 (one) to. It should be @@ -228,22 +241,22 @@ def b32decode(s, casefold=False, map01=None, *, ignorechars=b''): s = s.translate(bytes.maketrans(b'01', b'O' + map01)) if casefold: s = s.upper() - return binascii.a2b_base32(s, ignorechars=ignorechars) + return binascii.a2b_base32(s, padded=padded, ignorechars=ignorechars) b32decode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32', extra_args=_B32_DECODE_MAP01_DOCSTRING) -def b32hexencode(s, *, wrapcol=0): - return binascii.b2a_base32(s, wrapcol=wrapcol, +def b32hexencode(s, *, padded=True, wrapcol=0): + return binascii.b2a_base32(s, padded=padded, wrapcol=wrapcol, alphabet=binascii.BASE32HEX_ALPHABET) b32hexencode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32hex') -def b32hexdecode(s, casefold=False, *, ignorechars=b''): +def b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b''): s = _bytes_from_decode_data(s) # base32hex does not have the 01 mapping if casefold: s = s.upper() return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET, - ignorechars=ignorechars) + padded=padded, ignorechars=ignorechars) b32hexdecode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32hex', extra_args='') @@ -341,7 +354,7 @@ def b85encode(b, pad=False, *, wrapcol=0): """ return binascii.b2a_base85(b, wrapcol=wrapcol, pad=pad) -def b85decode(b, *, ignorechars=b''): +def b85decode(b, *, ignorechars=b''): """Decode the base85-encoded bytes-like object or ASCII string b The result is returned as a bytes object. @@ -360,7 +373,7 @@ def z85encode(s, pad=False, *, wrapcol=0): return binascii.b2a_base85(s, wrapcol=wrapcol, pad=pad, alphabet=binascii.Z85_ALPHABET) -def z85decode(s, *, ignorechars=b''): +def z85decode(s, *, ignorechars=b''): """Decode the z85-encoded bytes-like object or ASCII string b The result is returned as a bytes object. diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index d5f8f44e280..1a4dd56a553 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -209,6 +209,25 @@ def test_b64encode(self): b'\xd3V\xbeo\xf7\x1d', b'01a-b_cd') self.check_encode_type_errors(base64.urlsafe_b64encode) + def test_b64encode_padded(self): + b64encode = base64.b64encode + self.assertEqual(b64encode(b'', padded=False), b'') + self.assertEqual(b64encode(b'a', padded=False), b'YQ') + self.assertEqual(b64encode(b'ab', padded=False), b'YWI') + self.assertEqual(b64encode(b'abc', padded=False), b'YWJj') + self.assertEqual(b64encode(b'\xfb', padded=False, altchars=b'-_'), b'-w') + self.assertEqual(b64encode(b'\xfb\xff', padded=False, altchars=b'-_'), + b'-_8') + self.assertEqual(b64encode(b'\xfb\xff\xbf', padded=False, altchars=b'-_'), + b'-_-_') + + urlsafe_b64encode = base64.urlsafe_b64encode + self.assertEqual(urlsafe_b64encode(b'', padded=False), b'') + self.assertEqual(urlsafe_b64encode(b'\xfb', padded=False), b'-w') + self.assertEqual(urlsafe_b64encode(b'\xfb\xff', padded=False), b'-_8') + self.assertEqual(urlsafe_b64encode(b'\xfb\xff\xbf', padded=False), + b'-_-_') + def _common_test_wrapcol(self, func, data): eq = self.assertEqual expected = func(data) @@ -314,6 +333,36 @@ def test_b64decode_padding_error(self): self.assertRaises(binascii.Error, base64.b64decode, b'abc') self.assertRaises(binascii.Error, base64.b64decode, 'abc') + def test_b64decode_padded(self): + b64decode = base64.b64decode + urlsafe_b64decode = base64.urlsafe_b64decode + def check(data, expected, padded=0): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + b64decode(data, padded=False, validate=True) + self.assertEqual(b64decode(data, padded=False, ignorechars=b'='), + expected) + self.assertEqual(urlsafe_b64decode(data, padded=True), expected) + self.assertEqual(urlsafe_b64decode(data, padded=False), expected) + data = data.replace(b'=', b'') + self.assertEqual(b64decode(data, padded=False), expected) + self.assertEqual(b64decode(data, padded=False, validate=True), + expected) + self.assertEqual(urlsafe_b64decode(data), expected) + + check(b'', b'') + check(b'YQ==', b'a') + check(b'YWI=', b'ab') + check(b'YWJj', b'abc') + check(b'Y=WJj', b'abc') + check(b'YW=Jj', b'abc') + check(b'YWJ=j', b'abc') + + with self.assertRaisesRegex(binascii.Error, 'Incorrect padding'): + urlsafe_b64decode(b'YQ', padded=True) + with self.assertRaisesRegex(binascii.Error, 'Incorrect padding'): + urlsafe_b64decode(b'YWI', padded=True) + def _common_test_ignorechars(self, func): eq = self.assertEqual eq(func(b'', ignorechars=b' \n'), b'') @@ -487,6 +536,15 @@ def test_b32encode(self): self.check_other_types(base64.b32encode, b'abcd', b'MFRGGZA=') self.check_encode_type_errors(base64.b32encode) + def test_b32encode_padded(self): + b32encode = base64.b32encode + self.assertEqual(b32encode(b'', padded=False), b'') + self.assertEqual(b32encode(b'a', padded=False), b'ME') + self.assertEqual(b32encode(b'ab', padded=False), b'MFRA') + self.assertEqual(b32encode(b'abc', padded=False), b'MFRGG') + self.assertEqual(b32encode(b'abcd', padded=False), b'MFRGGZA') + self.assertEqual(b32encode(b'abcde', padded=False), b'MFRGGZDF') + def test_b32encode_wrapcol(self): eq = self.assertEqual b = b'www.python.org' @@ -564,6 +622,31 @@ def test_b32decode_map01(self): eq(base64.b32decode(b'M%c023456' % map01, map01=map01), res) eq(base64.b32decode(b'M%cO23456' % map01, map01=map01), res) + def test_b32decode_padded(self): + b32decode = base64.b32decode + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + b32decode(data, padded=False) + self.assertEqual(b32decode(data, padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(b32decode(data, padded=False), expected) + + check(b'', b'') + check(b'ME======', b'a') + check(b'MFRA====', b'ab') + check(b'MFRGG===', b'abc') + check(b'MFRGGZA=', b'abcd') + check(b'MFRGGZDF', b'abcde') + check(b'M=FRGGZDF', b'abcde') + check(b'MF=RGGZDF', b'abcde') + check(b'MFR=GGZDF', b'abcde') + check(b'MFRG=GZDF', b'abcde') + check(b'MFRGG=ZDF', b'abcde') + check(b'MFRGGZ=DF', b'abcde') + check(b'MFRGGZD=F', b'abcde') + def test_b32decode_ignorechars(self): self._common_test_ignorechars(base64.b32decode) eq = self.assertEqual @@ -632,6 +715,8 @@ def test_b32hexencode(self): for to_encode, expected in test_cases: with self.subTest(to_decode=to_encode): self.assertEqual(base64.b32hexencode(to_encode), expected) + self.assertEqual(base64.b32hexencode(to_encode, padded=False), + expected.rstrip(b'=')) def test_b32hexencode_other_types(self): self.check_other_types(base64.b32hexencode, b'abcd', b'C5H66P0=') @@ -679,6 +764,31 @@ def test_b32hexdecode_other_types(self): self.check_other_types(base64.b32hexdecode, b'C5H66===', b'abc') self.check_decode_type_errors(base64.b32hexdecode) + def test_b32hexdecode_padded(self): + b32hexdecode = base64.b32hexdecode + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + b32hexdecode(data, padded=False) + self.assertEqual(b32hexdecode(data, padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(b32hexdecode(data, padded=False), expected) + + check(b'', b'') + check(b'C4======', b'a') + check(b'C5H0====', b'ab') + check(b'C5H66===', b'abc') + check(b'C5H66P0=', b'abcd') + check(b'C5H66P35', b'abcde') + check(b'C=5H66P35', b'abcde') + check(b'C5=H66P35', b'abcde') + check(b'C5H=66P35', b'abcde') + check(b'C5H6=6P35', b'abcde') + check(b'C5H66=P35', b'abcde') + check(b'C5H66P=35', b'abcde') + check(b'C5H66P3=5', b'abcde') + def test_b32hexdecode_ignorechars(self): self._common_test_ignorechars(base64.b32hexdecode) eq = self.assertEqual diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index c8dbf3fec40..81cdacb9624 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -233,6 +233,28 @@ def assertInvalidLength(data, *args, length=None, **kwargs): assertExcessPadding(b'abcd====efgh', b'i\xb7\x1dy\xf8!') assertExcessPadding(b'abcd=====efgh', b'i\xb7\x1dy\xf8!') + def test_a2b_base64_padded(self): + a2b_base64 = binascii.a2b_base64 + t = self.type2test + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + a2b_base64(t(data), padded=False, strict_mode=True) + self.assertEqual(a2b_base64(t(data), padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(a2b_base64(t(data), padded=False), expected) + self.assertEqual(a2b_base64(t(data), padded=False, strict_mode=True), + expected) + + check(b'', b'') + check(b'YQ==', b'a') + check(b'YWI=', b'ab') + check(b'YWJj', b'abc') + check(b'Y=WJj', b'abc') + check(b'YW=Jj', b'abc') + check(b'YWJ=j', b'abc') + def _common_test_ignorechars(self, func): eq = self.assertEqual empty = self.type2test(b'') @@ -913,6 +935,42 @@ def assertInvalidLength(data, *args, length=None, **kwargs): assertInvalidLength(b" ABC=====", ignorechars=b' ') assertInvalidLength(b" ABCDEF==", ignorechars=b' ') + def test_a2b_base32_padded(self): + a2b_base32 = binascii.a2b_base32 + t = self.type2test + def check(data, expected): + if b'=' in data: + with self.assertRaisesRegex(binascii.Error, 'Padding not allowed'): + a2b_base32(t(data), padded=False) + self.assertEqual(a2b_base32(t(data), padded=False, ignorechars=b'='), + expected) + data = data.replace(b'=', b'') + self.assertEqual(a2b_base32(t(data), padded=False), expected) + + check(b'', b'') + check(b'ME======', b'a') + check(b'MFRA====', b'ab') + check(b'MFRGG===', b'abc') + check(b'MFRGGZA=', b'abcd') + check(b'MFRGGZDF', b'abcde') + check(b'M=FRGGZDF', b'abcde') + check(b'MF=RGGZDF', b'abcde') + check(b'MFR=GGZDF', b'abcde') + check(b'MFRG=GZDF', b'abcde') + check(b'MFRGG=ZDF', b'abcde') + check(b'MFRGGZ=DF', b'abcde') + check(b'MFRGGZD=F', b'abcde') + + def test_b2a_base32_padded(self): + b2a_base32 = binascii.b2a_base32 + t = self.type2test + self.assertEqual(b2a_base32(t(b''), padded=False), b'') + self.assertEqual(b2a_base32(t(b'a'), padded=False), b'ME') + self.assertEqual(b2a_base32(t(b'ab'), padded=False), b'MFRA') + self.assertEqual(b2a_base32(t(b'abc'), padded=False), b'MFRGG') + self.assertEqual(b2a_base32(t(b'abcd'), padded=False), b'MFRGGZA') + self.assertEqual(b2a_base32(t(b'abcde'), padded=False), b'MFRGGZDF') + def test_base32_wrapcol(self): self._common_test_wrapcol(binascii.b2a_base32) b = self.type2test(b'www.python.org') @@ -1255,6 +1313,14 @@ def test_b2a_base64_newline(self): self.assertEqual(binascii.b2a_base64(b, newline=True), b'\n') self.assertEqual(binascii.b2a_base64(b, newline=False), b'') + def test_b2a_base64_padded(self): + b2a_base64 = binascii.b2a_base64 + t = self.type2test + self.assertEqual(b2a_base64(t(b''), padded=False), b'\n') + self.assertEqual(b2a_base64(t(b'a'), padded=False), b'YQ\n') + self.assertEqual(b2a_base64(t(b'ab'), padded=False), b'YWI\n') + self.assertEqual(b2a_base64(t(b'abc'), padded=False), b'YWJj\n') + def test_b2a_base64_wrapcol(self): self._common_test_wrapcol(binascii.b2a_base64) b = self.type2test(b'www.python.org') diff --git a/Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst b/Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst new file mode 100644 index 00000000000..8c50972d3ca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst @@ -0,0 +1,7 @@ +Add the *padded* parameter in functions related to Base32 and Base64 codecs +in the :mod:`binascii` and :mod:`base64` modules. +In the encoding functions it controls whether the pad character can be added +in the output, in the decoding functions it controls whether padding is +required in input. +Padding of input no longer required in :func:`base64.urlsafe_b64decode` +by default. diff --git a/Modules/binascii.c b/Modules/binascii.c index d0ef2d2d2cc..9193137877a 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -723,6 +723,8 @@ binascii.a2b_base64 When set to true, bytes that are not part of the base64 standard are not allowed. The same applies to excess data after padding (= / ==). Set to True by default if ignorechars is specified, False otherwise. + padded: bool = True + When set to false, padding in input is not required. alphabet: PyBytesObject(c_default="NULL") = BASE64_ALPHABET ignorechars: Py_buffer = NULL A byte string containing characters to ignore from the input when @@ -733,8 +735,9 @@ Decode a line of base64 data. static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, - PyBytesObject *alphabet, Py_buffer *ignorechars) -/*[clinic end generated code: output=72f15fcc0681d666 input=195c8d60b03aaa6f]*/ + int padded, PyBytesObject *alphabet, + Py_buffer *ignorechars) +/*[clinic end generated code: output=525d840a299ff132 input=74a53dd3b23474b3]*/ { assert(data->len >= 0); @@ -798,7 +801,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, /* Check for pad sequences and ignore ** the invalid ones. */ - if (this_ch == BASE64_PAD) { + if (padded && this_ch == BASE64_PAD) { pads++; if (quad_pos >= 2 && quad_pos + pads <= 4) { continue; @@ -831,7 +834,10 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, if (strict_mode && !ignorechar(this_ch, ignorechars, ignorecache)) { state = get_binascii_state(module); if (state) { - PyErr_SetString(state->Error, "Only base64 data is allowed"); + PyErr_SetString(state->Error, + (this_ch == BASE64_PAD) + ? "Padding not allowed" + : "Only base64 data is allowed"); } goto error_end; } @@ -895,7 +901,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, goto error_end; } - if (quad_pos != 0 && quad_pos + pads < 4) { + if (padded && quad_pos != 0 && quad_pos + pads < 4) { state = get_binascii_state(module); if (state) { PyErr_SetString(state->Error, "Incorrect padding"); @@ -919,6 +925,8 @@ binascii.b2a_base64 data: Py_buffer / * + padded: bool = True + When set to false, omit padding in the output. wrapcol: size_t = 0 newline: bool = True alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE64_ALPHABET @@ -927,9 +935,9 @@ Base64-code line of data. [clinic start generated code]*/ static PyObject * -binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, - int newline, Py_buffer *alphabet) -/*[clinic end generated code: output=9d9657e5fbe28c64 input=ffa3af8520c312ac]*/ +binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, int newline, Py_buffer *alphabet) +/*[clinic end generated code: output=a2057b906dc201ab input=cfa33ad73051d3f7]*/ { const unsigned char *table_b2a = table_b2a_base64; const unsigned char *bin_data = data->buf; @@ -950,6 +958,11 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, * Use unsigned integer arithmetic to avoid signed integer overflow. */ size_t out_len = ((size_t)bin_len + 2u) / 3u * 4u; + unsigned int pads = (3 - (bin_len % 3)) % 3 * 4 / 3; + if (!padded) { + out_len -= pads; + pads = 0; + } if (wrapcol && out_len) { /* Each line should encode a whole number of bytes. */ wrapcol = wrapcol < 4 ? 4 : wrapcol / 4 * 4; @@ -982,18 +995,23 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, /* Handle remaining 0-2 bytes */ if (bin_len == 1) { /* 1 byte remaining: produces 2 base64 chars + 2 padding */ + assert(!padded || pads == 2); unsigned int val = bin_data[0]; *ascii_data++ = table_b2a[(val >> 2) & 0x3f]; *ascii_data++ = table_b2a[(val << 4) & 0x3f]; - *ascii_data++ = BASE64_PAD; - *ascii_data++ = BASE64_PAD; } else if (bin_len == 2) { /* 2 bytes remaining: produces 3 base64 chars + 1 padding */ + assert(!padded || pads == 1); unsigned int val = ((unsigned int)bin_data[0] << 8) | bin_data[1]; *ascii_data++ = table_b2a[(val >> 10) & 0x3f]; *ascii_data++ = table_b2a[(val >> 4) & 0x3f]; *ascii_data++ = table_b2a[(val << 2) & 0x3f]; + } + else { + assert(pads == 0); + } + for (; pads; pads--) { *ascii_data++ = BASE64_PAD; } @@ -1512,6 +1530,8 @@ binascii.a2b_base32 data: ascii_buffer / * + padded: bool = True + When set to false, padding in input is not required. alphabet: PyBytesObject(c_default="NULL") = BASE32_ALPHABET ignorechars: Py_buffer = b'' A byte string containing characters to ignore from the input. @@ -1520,9 +1540,9 @@ Decode a line of base32 data. [clinic start generated code]*/ static PyObject * -binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, +binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, int padded, PyBytesObject *alphabet, Py_buffer *ignorechars) -/*[clinic end generated code: output=2cf7c8c9e6e98b88 input=b0333508aad1b3ac]*/ +/*[clinic end generated code: output=7dbbaa816d956b1c input=07a3721acdf9b688]*/ { const unsigned char *ascii_data = data->buf; Py_ssize_t ascii_len = data->len; @@ -1581,7 +1601,7 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, unsigned char this_ch = *ascii_data; /* Check for pad sequences. They may only occur at certain positions. */ - if (this_ch == BASE32_PAD) { + if (padded && this_ch == BASE32_PAD) { pads++; if ((octa_pos == 2 || octa_pos == 4 || octa_pos == 5 || octa_pos == 7) @@ -1617,7 +1637,10 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, if (!ignorechar(this_ch, ignorechars, ignorecache)) { state = get_binascii_state(module); if (state) { - PyErr_SetString(state->Error, "Only base32 data is allowed"); + PyErr_SetString(state->Error, + (this_ch == BASE32_PAD) + ? "Padding not allowed" + : "Only base32 data is allowed"); } goto error; } @@ -1692,7 +1715,7 @@ binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, goto error; } - if (octa_pos != 0 && octa_pos + pads < 8) { + if (padded && octa_pos != 0 && octa_pos + pads < 8) { state = get_binascii_state(module); if (state) { PyErr_SetString(state->Error, "Incorrect padding"); @@ -1715,6 +1738,8 @@ binascii.b2a_base32 data: Py_buffer / * + padded: bool = True + When set to false, omit padding in the output. wrapcol: size_t = 0 alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE32_ALPHABET @@ -1722,9 +1747,9 @@ Base32-code line of data. [clinic start generated code]*/ static PyObject * -binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, - Py_buffer *alphabet) -/*[clinic end generated code: output=d41fafbdaf29e280 input=a3d93b73836f2879]*/ +binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, Py_buffer *alphabet) +/*[clinic end generated code: output=acc09e685569aab9 input=1889b0c497a1d3c2]*/ { const unsigned char *table_b2a = table_b2a_base32; const unsigned char *bin_data = data->buf; @@ -1746,6 +1771,11 @@ binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, * Use unsigned integer arithmetic to avoid signed integer overflow. */ size_t ascii_len = ((size_t)bin_len + 4u) / 5u * 8u; + unsigned int pads = (5 - (bin_len % 5)) % 5 * 8 / 5; + if (!padded) { + ascii_len -= pads; + pads = 0; + } if (wrapcol && ascii_len) { /* Each line should encode a whole number of bytes. */ wrapcol = wrapcol < 8 ? 8 : wrapcol / 8 * 8; @@ -1774,30 +1804,23 @@ binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, /* Handle the remaining 0-4 bytes. */ if (bin_len == 1) { /* 1 byte remaining: produces 2 encoded + 6 padding chars. */ + assert(!padded || pads == 6); uint32_t val = bin_data[0]; *ascii_data++ = table_b2a[(val >> 3) & 0x1f]; *ascii_data++ = table_b2a[(val << 2) & 0x1f]; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; } else if (bin_len == 2) { /* 2 bytes remaining: produces 4 encoded + 4 padding chars. */ + assert(!padded || pads == 4); uint32_t val = ((uint32_t)bin_data[0] << 8) | bin_data[1]; *ascii_data++ = table_b2a[(val >> 11) & 0x1f]; *ascii_data++ = table_b2a[(val >> 6) & 0x1f]; *ascii_data++ = table_b2a[(val >> 1) & 0x1f]; *ascii_data++ = table_b2a[(val << 4) & 0x1f]; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; } else if (bin_len == 3) { /* 3 bytes remaining: produces 5 encoded + 3 padding chars. */ + assert(!padded || pads == 3); uint32_t val = ((uint32_t)bin_data[0] << 16) | ((uint32_t)bin_data[1] << 8) | bin_data[2]; @@ -1806,12 +1829,10 @@ binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, *ascii_data++ = table_b2a[(val >> 9) & 0x1f]; *ascii_data++ = table_b2a[(val >> 4) & 0x1f]; *ascii_data++ = table_b2a[(val << 1) & 0x1f]; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; - *ascii_data++ = BASE32_PAD; } else if (bin_len == 4) { /* 4 bytes remaining: produces 7 encoded + 1 padding chars. */ + assert(!padded || pads == 1); uint32_t val = ((uint32_t)bin_data[0] << 24) | ((uint32_t)bin_data[1] << 16) | ((uint32_t)bin_data[2] << 8) @@ -1823,6 +1844,11 @@ binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, *ascii_data++ = table_b2a[(val >> 7) & 0x1f]; *ascii_data++ = table_b2a[(val >> 2) & 0x1f]; *ascii_data++ = table_b2a[(val << 3) & 0x1f]; + } + else { + assert(pads == 0); + } + for (; pads; pads--) { *ascii_data++ = BASE32_PAD; } diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h index d27a6599724..0a2d33c428d 100644 --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -118,7 +118,8 @@ exit: PyDoc_STRVAR(binascii_a2b_base64__doc__, "a2b_base64($module, data, /, *, strict_mode=,\n" -" alphabet=BASE64_ALPHABET, ignorechars=)\n" +" padded=True, alphabet=BASE64_ALPHABET,\n" +" ignorechars=)\n" "--\n" "\n" "Decode a line of base64 data.\n" @@ -127,6 +128,8 @@ PyDoc_STRVAR(binascii_a2b_base64__doc__, " When set to true, bytes that are not part of the base64 standard are\n" " not allowed. The same applies to excess data after padding (= / ==).\n" " Set to True by default if ignorechars is specified, False otherwise.\n" +" padded\n" +" When set to false, padding in input is not required.\n" " ignorechars\n" " A byte string containing characters to ignore from the input when\n" " strict_mode is true."); @@ -136,7 +139,8 @@ PyDoc_STRVAR(binascii_a2b_base64__doc__, static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode, - PyBytesObject *alphabet, Py_buffer *ignorechars); + int padded, PyBytesObject *alphabet, + Py_buffer *ignorechars); static PyObject * binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -144,7 +148,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -153,7 +157,7 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(strict_mode), &_Py_ID(alphabet), &_Py_ID(ignorechars), }, + .ob_item = { &_Py_ID(strict_mode), &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -162,17 +166,18 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "strict_mode", "alphabet", "ignorechars", NULL}; + static const char * const _keywords[] = {"", "strict_mode", "padded", "alphabet", "ignorechars", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_base64", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; int strict_mode = -1; + int padded = 1; PyBytesObject *alphabet = NULL; Py_buffer ignorechars = {NULL, NULL}; @@ -197,20 +202,29 @@ binascii_a2b_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } } if (args[2]) { - if (!PyBytes_Check(args[2])) { - _PyArg_BadArgument("a2b_base64", "argument 'alphabet'", "bytes", args[2]); + padded = PyObject_IsTrue(args[2]); + if (padded < 0) { goto exit; } - alphabet = (PyBytesObject *)args[2]; if (!--noptargs) { goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { + if (args[3]) { + if (!PyBytes_Check(args[3])) { + _PyArg_BadArgument("a2b_base64", "argument 'alphabet'", "bytes", args[3]); + goto exit; + } + alphabet = (PyBytesObject *)args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[4], &ignorechars, PyBUF_SIMPLE) != 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_a2b_base64_impl(module, &data, strict_mode, alphabet, &ignorechars); + return_value = binascii_a2b_base64_impl(module, &data, strict_mode, padded, alphabet, &ignorechars); exit: /* Cleanup for data */ @@ -225,18 +239,21 @@ exit: } PyDoc_STRVAR(binascii_b2a_base64__doc__, -"b2a_base64($module, data, /, *, wrapcol=0, newline=True,\n" +"b2a_base64($module, data, /, *, padded=True, wrapcol=0, newline=True,\n" " alphabet=BASE64_ALPHABET)\n" "--\n" "\n" -"Base64-code line of data."); +"Base64-code line of data.\n" +"\n" +" padded\n" +" When set to false, omit padding in the output."); #define BINASCII_B2A_BASE64_METHODDEF \ {"b2a_base64", _PyCFunction_CAST(binascii_b2a_base64), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base64__doc__}, static PyObject * -binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, size_t wrapcol, - int newline, Py_buffer *alphabet); +binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, int newline, Py_buffer *alphabet); static PyObject * binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -244,7 +261,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -253,7 +270,7 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(wrapcol), &_Py_ID(newline), &_Py_ID(alphabet), }, + .ob_item = { &_Py_ID(padded), &_Py_ID(wrapcol), &_Py_ID(newline), &_Py_ID(alphabet), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -262,16 +279,17 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "wrapcol", "newline", "alphabet", NULL}; + static const char * const _keywords[] = {"", "padded", "wrapcol", "newline", "alphabet", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "b2a_base64", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; + int padded = 1; size_t wrapcol = 0; int newline = 1; Py_buffer alphabet = {NULL, NULL}; @@ -288,7 +306,8 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } if (args[1]) { - if (!_PyLong_Size_t_Converter(args[1], &wrapcol)) { + padded = PyObject_IsTrue(args[1]); + if (padded < 0) { goto exit; } if (!--noptargs) { @@ -296,7 +315,15 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } } if (args[2]) { - newline = PyObject_IsTrue(args[2]); + if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + newline = PyObject_IsTrue(args[3]); if (newline < 0) { goto exit; } @@ -304,11 +331,11 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[3], &alphabet, PyBUF_SIMPLE) != 0) { + if (PyObject_GetBuffer(args[4], &alphabet, PyBUF_SIMPLE) != 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_b2a_base64_impl(module, &data, wrapcol, newline, &alphabet); + return_value = binascii_b2a_base64_impl(module, &data, padded, wrapcol, newline, &alphabet); exit: /* Cleanup for data */ @@ -740,12 +767,14 @@ exit: } PyDoc_STRVAR(binascii_a2b_base32__doc__, -"a2b_base32($module, data, /, *, alphabet=BASE32_ALPHABET,\n" +"a2b_base32($module, data, /, *, padded=True, alphabet=BASE32_ALPHABET,\n" " ignorechars=b\'\')\n" "--\n" "\n" "Decode a line of base32 data.\n" "\n" +" padded\n" +" When set to false, padding in input is not required.\n" " ignorechars\n" " A byte string containing characters to ignore from the input."); @@ -753,7 +782,7 @@ PyDoc_STRVAR(binascii_a2b_base32__doc__, {"a2b_base32", _PyCFunction_CAST(binascii_a2b_base32), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base32__doc__}, static PyObject * -binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, +binascii_a2b_base32_impl(PyObject *module, Py_buffer *data, int padded, PyBytesObject *alphabet, Py_buffer *ignorechars); static PyObject * @@ -762,7 +791,7 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -771,7 +800,7 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), }, + .ob_item = { &_Py_ID(padded), &_Py_ID(alphabet), &_Py_ID(ignorechars), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -780,16 +809,17 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "alphabet", "ignorechars", NULL}; + static const char * const _keywords[] = {"", "padded", "alphabet", "ignorechars", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "a2b_base32", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[3]; + PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; + int padded = 1; PyBytesObject *alphabet = NULL; Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0}; @@ -805,20 +835,29 @@ binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } if (args[1]) { - if (!PyBytes_Check(args[1])) { - _PyArg_BadArgument("a2b_base32", "argument 'alphabet'", "bytes", args[1]); + padded = PyObject_IsTrue(args[1]); + if (padded < 0) { goto exit; } - alphabet = (PyBytesObject *)args[1]; if (!--noptargs) { goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) { + if (args[2]) { + if (!PyBytes_Check(args[2])) { + _PyArg_BadArgument("a2b_base32", "argument 'alphabet'", "bytes", args[2]); + goto exit; + } + alphabet = (PyBytesObject *)args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[3], &ignorechars, PyBUF_SIMPLE) != 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_a2b_base32_impl(module, &data, alphabet, &ignorechars); + return_value = binascii_a2b_base32_impl(module, &data, padded, alphabet, &ignorechars); exit: /* Cleanup for data */ @@ -833,17 +872,21 @@ exit: } PyDoc_STRVAR(binascii_b2a_base32__doc__, -"b2a_base32($module, data, /, *, wrapcol=0, alphabet=BASE32_ALPHABET)\n" +"b2a_base32($module, data, /, *, padded=True, wrapcol=0,\n" +" alphabet=BASE32_ALPHABET)\n" "--\n" "\n" -"Base32-code line of data."); +"Base32-code line of data.\n" +"\n" +" padded\n" +" When set to false, omit padding in the output."); #define BINASCII_B2A_BASE32_METHODDEF \ {"b2a_base32", _PyCFunction_CAST(binascii_b2a_base32), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base32__doc__}, static PyObject * -binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol, - Py_buffer *alphabet); +binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, int padded, + size_t wrapcol, Py_buffer *alphabet); static PyObject * binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -851,7 +894,7 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -860,7 +903,7 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(wrapcol), &_Py_ID(alphabet), }, + .ob_item = { &_Py_ID(padded), &_Py_ID(wrapcol), &_Py_ID(alphabet), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -869,16 +912,17 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "wrapcol", "alphabet", NULL}; + static const char * const _keywords[] = {"", "padded", "wrapcol", "alphabet", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "b2a_base32", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[3]; + PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer data = {NULL, NULL}; + int padded = 1; size_t wrapcol = 0; Py_buffer alphabet = {NULL, NULL}; @@ -894,18 +938,27 @@ binascii_b2a_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_kwonly; } if (args[1]) { - if (!_PyLong_Size_t_Converter(args[1], &wrapcol)) { + padded = PyObject_IsTrue(args[1]); + if (padded < 0) { goto exit; } if (!--noptargs) { goto skip_optional_kwonly; } } - if (PyObject_GetBuffer(args[2], &alphabet, PyBUF_SIMPLE) != 0) { + if (args[2]) { + if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyObject_GetBuffer(args[3], &alphabet, PyBUF_SIMPLE) != 0) { goto exit; } skip_optional_kwonly: - return_value = binascii_b2a_base32_impl(module, &data, wrapcol, &alphabet); + return_value = binascii_b2a_base32_impl(module, &data, padded, wrapcol, &alphabet); exit: /* Cleanup for data */ @@ -1581,4 +1634,4 @@ exit: return return_value; } -/*[clinic end generated code: output=197a0f70aa392d39 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2acab1ceb0058b1a input=a9049054013a1b77]*/ From c43b490ca3f511bbdb3d462587db6c506a410036 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Sat, 4 Apr 2026 20:47:11 +0100 Subject: [PATCH 412/775] gh-145000: Find correct merge base in `reusable-check-html-ids.yml` workflow (#147975) --- .github/workflows/reusable-check-html-ids.yml | 45 +++++++++++-------- Tools/build/compute-changes.py | 2 +- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/.github/workflows/reusable-check-html-ids.yml b/.github/workflows/reusable-check-html-ids.yml index 4a1d321a8ce..4f827c55cac 100644 --- a/.github/workflows/reusable-check-html-ids.yml +++ b/.github/workflows/reusable-check-html-ids.yml @@ -15,11 +15,33 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - name: 'Check out base commit' + - name: 'Check out PR head' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - ref: ${{ github.event.pull_request.base.sha }} + ref: ${{ github.event.pull_request.head.sha }} + - name: 'Find merge base' + id: merge-base + run: | + BASE="${{ github.event.pull_request.base.sha }}" + HEAD="${{ github.event.pull_request.head.sha }}" + git fetch --depth=$((${{ github.event.pull_request.commits }} + 10)) --no-tags origin "$BASE" "$HEAD" + + if ! MERGE_BASE=$(git merge-base "$BASE" "$HEAD" 2>/dev/null); then + git fetch --deepen=1 --no-tags origin "$BASE" "$HEAD" + + OLDEST=$(git rev-list --reflog --max-parents=0 --reverse "${BASE}^" "${HEAD}^" | head -1) + TIMESTAMP=$(git show --format=%at --no-patch "$OLDEST") + + git fetch --shallow-since="$TIMESTAMP" --no-tags origin "$BASE" "$HEAD" + + MERGE_BASE=$(git merge-base "$BASE" "$HEAD") + fi + echo "sha=$MERGE_BASE" >> "$GITHUB_OUTPUT" + - name: 'Create worktree at merge base' + env: + MERGE_BASE: ${{ steps.merge-base.outputs.sha }} + run: git worktree add /tmp/merge-base "$MERGE_BASE" --detach - name: 'Set up Python' uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: @@ -27,24 +49,11 @@ jobs: cache: 'pip' cache-dependency-path: 'Doc/requirements.txt' - name: 'Install build dependencies' - run: make -C Doc/ venv + run: make -C /tmp/merge-base/Doc/ venv - name: 'Build HTML documentation' - run: make -C Doc/ SPHINXOPTS="--quiet" html - - name: 'Check out PR head tools' - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - sparse-checkout: | - Doc/tools/check-html-ids.py - Doc/tools/removed-ids.txt - sparse-checkout-cone-mode: false - path: pr-head - - name: 'Use PR head tools' - run: | - cp pr-head/Doc/tools/check-html-ids.py Doc/tools/check-html-ids.py - [ -f pr-head/Doc/tools/removed-ids.txt ] && cp pr-head/Doc/tools/removed-ids.txt Doc/tools/removed-ids.txt + run: make -C /tmp/merge-base/Doc/ SPHINXOPTS="--quiet" html - name: 'Collect HTML IDs' - run: python Doc/tools/check-html-ids.py collect Doc/build/html -o /tmp/html-ids-base.json.gz + run: python Doc/tools/check-html-ids.py collect /tmp/merge-base/Doc/build/html -o /tmp/html-ids-base.json.gz - name: 'Download PR head HTML IDs' uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/Tools/build/compute-changes.py b/Tools/build/compute-changes.py index 4870388da0d..53d7b8fe32f 100644 --- a/Tools/build/compute-changes.py +++ b/Tools/build/compute-changes.py @@ -238,7 +238,7 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs: run_tests = run_ci_fuzz = run_ci_fuzz_stdlib = run_windows_tests = True has_platform_specific_change = False continue - if file.name == "reusable-docs.yml": + if file.name in ("reusable-docs.yml", "reusable-check-html-ids.yml"): run_docs = True continue if file.name == "reusable-windows.yml": From 4ff8b07a3d907c5a755a862a86496ed6c6fb2f3d Mon Sep 17 00:00:00 2001 From: ivonastojanovic <80911834+ivonastojanovic@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:55:05 +0100 Subject: [PATCH 413/775] gh-142927: Show self time in flamegraph tooltip (#147706) We already show self time in differential flamegraphs, but it should be included in regular flamegraphs as well. Display the time spent in the function body excluding callees, not just the total inclusive time. --- .../sampling/_flamegraph_assets/flamegraph.js | 11 ++++++++++- Lib/profiling/sampling/stack_collector.py | 1 + .../test_sampling_profiler/test_collectors.py | 4 +++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js index 166c03d03fb..d7a8890d4a1 100644 --- a/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js +++ b/Lib/profiling/sampling/_flamegraph_assets/flamegraph.js @@ -292,6 +292,8 @@ function createPythonTooltip(data) { } const timeMs = (d.data.value / 1000).toFixed(2); + const selfSamples = d.data.self || 0; + const selfMs = (selfSamples / 1000).toFixed(2); const percentage = ((d.data.value / data.value) * 100).toFixed(2); const calls = d.data.calls || 0; const childCount = d.children ? d.children.length : 0; @@ -403,9 +405,14 @@ function createPythonTooltip(data) { ${fileLocationHTML}
- Execution Time: + Total Time: ${timeMs} ms + ${selfSamples > 0 ? ` + Self Time: + ${selfMs} ms + ` : ''} + Percentage: ${percentage}% @@ -1271,6 +1278,7 @@ function accumulateInvertedNode(parent, stackFrame, leaf, isDifferential) { const newNode = { name: stackFrame.name, value: 0, + self: 0, children: {}, filename: stackFrame.filename, lineno: stackFrame.lineno, @@ -1293,6 +1301,7 @@ function accumulateInvertedNode(parent, stackFrame, leaf, isDifferential) { const node = parent.children[key]; node.value += leaf.value; + node.self += stackFrame.self || 0; if (leaf.threads) { leaf.threads.forEach(t => node.threads.add(t)); } diff --git a/Lib/profiling/sampling/stack_collector.py b/Lib/profiling/sampling/stack_collector.py index 31102d3eb0f..461ce95a258 100644 --- a/Lib/profiling/sampling/stack_collector.py +++ b/Lib/profiling/sampling/stack_collector.py @@ -207,6 +207,7 @@ def convert_children(children, min_samples): child_entry = { "name": name_idx, "value": samples, + "self": node.get("self", 0), "children": [], "filename": filename_idx, "lineno": func[1], diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py index 86fb9d4c05b..503430ddf02 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py @@ -435,12 +435,14 @@ def test_flamegraph_collector_basic(self): strings = data.get("strings", []) name = resolve_name(data, strings) self.assertTrue(name.startswith("Program Root: ")) - self.assertIn("func2 (file.py:20)", name) # formatted name + self.assertIn("func2 (file.py:20)", name) + self.assertEqual(data["self"], 0) # non-leaf: no self time children = data.get("children", []) self.assertEqual(len(children), 1) child = children[0] self.assertIn("func1 (file.py:10)", resolve_name(child, strings)) self.assertEqual(child["value"], 1) + self.assertEqual(child["self"], 1) # leaf: all time is self def test_flamegraph_collector_export(self): """Test flamegraph HTML export functionality.""" From 1f36a510a2a16e8ff15572f44090c7db43bb7935 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sun, 5 Apr 2026 06:31:54 +0800 Subject: [PATCH 414/775] Add `permissions: {}` to all reusable workflows (#148114) Add permissions: {} to all reusable workflows --- .github/workflows/reusable-check-c-api-docs.yml | 3 +-- .github/workflows/reusable-check-html-ids.yml | 3 +-- .github/workflows/reusable-cifuzz.yml | 2 ++ .github/workflows/reusable-context.yml | 2 ++ .github/workflows/reusable-docs.yml | 3 +-- .github/workflows/reusable-emscripten.yml | 2 ++ .github/workflows/reusable-macos.yml | 2 ++ .github/workflows/reusable-san.yml | 2 ++ .github/workflows/reusable-ubuntu.yml | 2 ++ .github/workflows/reusable-wasi.yml | 2 ++ .github/workflows/reusable-windows-msi.yml | 3 +-- .github/workflows/reusable-windows.yml | 2 ++ 12 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.github/workflows/reusable-check-c-api-docs.yml b/.github/workflows/reusable-check-c-api-docs.yml index 49e5ef7f768..5fae57a1dbd 100644 --- a/.github/workflows/reusable-check-c-api-docs.yml +++ b/.github/workflows/reusable-check-c-api-docs.yml @@ -3,8 +3,7 @@ name: Reusable C API Docs Check on: workflow_call: -permissions: - contents: read +permissions: {} env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-check-html-ids.yml b/.github/workflows/reusable-check-html-ids.yml index 4f827c55cac..03ed714ca58 100644 --- a/.github/workflows/reusable-check-html-ids.yml +++ b/.github/workflows/reusable-check-html-ids.yml @@ -3,8 +3,7 @@ name: Reusable check HTML IDs on: workflow_call: -permissions: - contents: read +permissions: {} env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-cifuzz.yml b/.github/workflows/reusable-cifuzz.yml index 339fca7919c..093b2c859ef 100644 --- a/.github/workflows/reusable-cifuzz.yml +++ b/.github/workflows/reusable-cifuzz.yml @@ -13,6 +13,8 @@ on: required: true type: string +permissions: {} + jobs: cifuzz: name: ${{ inputs.oss-fuzz-project-name }} (${{ inputs.sanitizer }}) diff --git a/.github/workflows/reusable-context.yml b/.github/workflows/reusable-context.yml index 0f0ca3475b3..cc9841ebf32 100644 --- a/.github/workflows/reusable-context.yml +++ b/.github/workflows/reusable-context.yml @@ -54,6 +54,8 @@ on: # yamllint disable-line rule:truthy description: Whether to run the Windows tests value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool +permissions: {} + jobs: compute-changes: name: Create context from changed files diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml index 0453b6ab555..3d534feb2ed 100644 --- a/.github/workflows/reusable-docs.yml +++ b/.github/workflows/reusable-docs.yml @@ -4,8 +4,7 @@ on: workflow_call: workflow_dispatch: -permissions: - contents: read +permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/reusable-emscripten.yml b/.github/workflows/reusable-emscripten.yml index ce3e65f11a3..300731deb78 100644 --- a/.github/workflows/reusable-emscripten.yml +++ b/.github/workflows/reusable-emscripten.yml @@ -3,6 +3,8 @@ name: Reusable Emscripten on: workflow_call: +permissions: {} + env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-macos.yml b/.github/workflows/reusable-macos.yml index 785dcc77f54..a372d571529 100644 --- a/.github/workflows/reusable-macos.yml +++ b/.github/workflows/reusable-macos.yml @@ -12,6 +12,8 @@ on: required: true type: string +permissions: {} + env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-san.yml b/.github/workflows/reusable-san.yml index 4e2891ab9b7..33cfd578d68 100644 --- a/.github/workflows/reusable-san.yml +++ b/.github/workflows/reusable-san.yml @@ -12,6 +12,8 @@ on: type: boolean default: false +permissions: {} + env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml index 87274a7b8a3..b2ab525c976 100644 --- a/.github/workflows/reusable-ubuntu.yml +++ b/.github/workflows/reusable-ubuntu.yml @@ -23,6 +23,8 @@ on: type: string default: '' +permissions: {} + env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml index 9bff508bd66..83f9d2399ce 100644 --- a/.github/workflows/reusable-wasi.yml +++ b/.github/workflows/reusable-wasi.yml @@ -3,6 +3,8 @@ name: Reusable WASI on: workflow_call: +permissions: {} + env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml index a74724323ec..7c724f184f3 100644 --- a/.github/workflows/reusable-windows-msi.yml +++ b/.github/workflows/reusable-windows-msi.yml @@ -8,8 +8,7 @@ on: required: true type: string -permissions: - contents: read +permissions: {} env: FORCE_COLOR: 1 diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml index 1c399689cde..2cfe338a652 100644 --- a/.github/workflows/reusable-windows.yml +++ b/.github/workflows/reusable-windows.yml @@ -17,6 +17,8 @@ on: required: true type: string +permissions: {} + env: FORCE_COLOR: 1 IncludeUwp: >- From 1c4408aeca4b532b5810f18c9fbc641397c88267 Mon Sep 17 00:00:00 2001 From: Antonio Cuni Date: Sun, 5 Apr 2026 16:23:07 +0200 Subject: [PATCH 415/775] gh-130472: Integrate fancycompleter with the new repl, to get colored tab completions (#130473) Co-authored-by: Pablo Galindo --- Doc/using/cmdline.rst | 7 + Lib/_colorize.py | 29 +- Lib/_pyrepl/completing_reader.py | 12 +- Lib/_pyrepl/fancycompleter.py | 210 +++++++++++++++ Lib/_pyrepl/readline.py | 8 +- Lib/test/test_pyrepl/test_fancycompleter.py | 247 ++++++++++++++++++ Lib/test/test_pyrepl/test_pyrepl.py | 88 +++++++ ...-09-19-13-54-54.gh-issue-130472.LODfdk.rst | 1 + 8 files changed, 595 insertions(+), 7 deletions(-) create mode 100644 Lib/_pyrepl/fancycompleter.py create mode 100644 Lib/test/test_pyrepl/test_fancycompleter.py create mode 100644 Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 73cd8d31d0b..d0355ce47a6 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -1338,6 +1338,13 @@ conflict. .. versionadded:: 3.13 +.. envvar:: PYTHON_BASIC_COMPLETER + + If this variable is set to any value, PyREPL will use :mod:`rlcompleter` to + implement tab completion, instead of the default one which uses colors. + + .. versionadded:: 3.15 + .. envvar:: PYTHON_HISTORY This environment variable can be used to set the location of a diff --git a/Lib/_colorize.py b/Lib/_colorize.py index fd0ae9d6145..8361ddbea89 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -15,7 +15,6 @@ class ANSIColors: RESET = "\x1b[0m" - BLACK = "\x1b[30m" BLUE = "\x1b[34m" CYAN = "\x1b[36m" @@ -200,6 +199,30 @@ class Difflib(ThemeSection): reset: str = ANSIColors.RESET +@dataclass(frozen=True, kw_only=True) +class FancyCompleter(ThemeSection): + # functions and methods + function: str = ANSIColors.BOLD_BLUE + builtin_function_or_method: str = ANSIColors.BOLD_BLUE + method: str = ANSIColors.BOLD_CYAN + method_wrapper: str = ANSIColors.BOLD_CYAN + wrapper_descriptor: str = ANSIColors.BOLD_CYAN + method_descriptor: str = ANSIColors.BOLD_CYAN + + # numbers + int: str = ANSIColors.BOLD_YELLOW + float: str = ANSIColors.BOLD_YELLOW + complex: str = ANSIColors.BOLD_YELLOW + bool: str = ANSIColors.BOLD_YELLOW + + # others + type: str = ANSIColors.BOLD_MAGENTA + module: str = ANSIColors.CYAN + NoneType: str = ANSIColors.GREY + bytes: str = ANSIColors.BOLD_GREEN + str: str = ANSIColors.BOLD_GREEN + + @dataclass(frozen=True, kw_only=True) class LiveProfiler(ThemeSection): """Theme section for the live profiling TUI (Tachyon profiler). @@ -354,6 +377,7 @@ class Theme: """ argparse: Argparse = field(default_factory=Argparse) difflib: Difflib = field(default_factory=Difflib) + fancycompleter: FancyCompleter = field(default_factory=FancyCompleter) live_profiler: LiveProfiler = field(default_factory=LiveProfiler) syntax: Syntax = field(default_factory=Syntax) traceback: Traceback = field(default_factory=Traceback) @@ -364,6 +388,7 @@ def copy_with( *, argparse: Argparse | None = None, difflib: Difflib | None = None, + fancycompleter: FancyCompleter | None = None, live_profiler: LiveProfiler | None = None, syntax: Syntax | None = None, traceback: Traceback | None = None, @@ -377,6 +402,7 @@ def copy_with( return type(self)( argparse=argparse or self.argparse, difflib=difflib or self.difflib, + fancycompleter=fancycompleter or self.fancycompleter, live_profiler=live_profiler or self.live_profiler, syntax=syntax or self.syntax, traceback=traceback or self.traceback, @@ -394,6 +420,7 @@ def no_colors(cls) -> Self: return cls( argparse=Argparse.no_colors(), difflib=Difflib.no_colors(), + fancycompleter=FancyCompleter.no_colors(), live_profiler=LiveProfiler.no_colors(), syntax=Syntax.no_colors(), traceback=Traceback.no_colors(), diff --git a/Lib/_pyrepl/completing_reader.py b/Lib/_pyrepl/completing_reader.py index 9d2d43be514..5802920a907 100644 --- a/Lib/_pyrepl/completing_reader.py +++ b/Lib/_pyrepl/completing_reader.py @@ -178,12 +178,14 @@ def do(self) -> None: if not completions: r.error("no matches") elif len(completions) == 1: - if completions_unchangable and len(completions[0]) == len(stem): + completion = stripcolor(completions[0]) + if completions_unchangable and len(completion) == len(stem): r.msg = "[ sole completion ]" r.dirty = True - r.insert(completions[0][len(stem):]) + r.insert(completion[len(stem):]) else: - p = prefix(completions, len(stem)) + clean_completions = [stripcolor(word) for word in completions] + p = prefix(clean_completions, len(stem)) if p: r.insert(p) if last_is_completer: @@ -195,7 +197,7 @@ def do(self) -> None: r.dirty = True elif not r.cmpltn_menu_visible: r.cmpltn_message_visible = True - if stem + p in completions: + if stem + p in clean_completions: r.msg = "[ complete but not unique ]" r.dirty = True else: @@ -215,7 +217,7 @@ def do(self) -> None: r.cmpltn_reset() else: completions = [w for w in r.cmpltn_menu_choices - if w.startswith(stem)] + if stripcolor(w).startswith(stem)] if completions: r.cmpltn_menu, r.cmpltn_menu_end = build_menu( r.console, completions, 0, diff --git a/Lib/_pyrepl/fancycompleter.py b/Lib/_pyrepl/fancycompleter.py new file mode 100644 index 00000000000..5b5b7ae5f2b --- /dev/null +++ b/Lib/_pyrepl/fancycompleter.py @@ -0,0 +1,210 @@ +# Copyright 2010-2025 Antonio Cuni +# Daniel Hahler +# +# All Rights Reserved +"""Colorful tab completion for Python prompt""" +from _colorize import ANSIColors, get_colors, get_theme +import rlcompleter +import keyword +import types + +class Completer(rlcompleter.Completer): + """ + When doing something like a.b., keep the full a.b.attr completion + stem so readline-style completion can keep refining the menu as you type. + + Optionally, display the various completions in different colors + depending on the type. + """ + def __init__( + self, + namespace=None, + *, + use_colors='auto', + consider_getitems=True, + ): + from _pyrepl import readline + rlcompleter.Completer.__init__(self, namespace) + if use_colors == 'auto': + # use colors only if we can + use_colors = get_colors().RED != "" + self.use_colors = use_colors + self.consider_getitems = consider_getitems + + if self.use_colors: + # In GNU readline, this prevents escaping of ANSI control + # characters in completion results. pyrepl's parse_and_bind() + # is a no-op, but pyrepl handles ANSI sequences natively + # via real_len()/stripcolor(). + readline.parse_and_bind('set dont-escape-ctrl-chars on') + self.theme = get_theme() + else: + self.theme = None + + if self.consider_getitems: + delims = readline.get_completer_delims() + delims = delims.replace('[', '') + delims = delims.replace(']', '') + readline.set_completer_delims(delims) + + def complete(self, text, state): + # if you press at the beginning of a line, insert an actual + # \t. Else, trigger completion. + if text == "": + return ('\t', None)[state] + else: + return rlcompleter.Completer.complete(self, text, state) + + def _callable_postfix(self, val, word): + # disable automatic insertion of '(' for global callables + return word + + def _callable_attr_postfix(self, val, word): + return rlcompleter.Completer._callable_postfix(self, val, word) + + def global_matches(self, text): + names = rlcompleter.Completer.global_matches(self, text) + prefix = commonprefix(names) + if prefix and prefix != text: + return [prefix] + + names.sort() + values = [] + for name in names: + clean_name = name.rstrip(': ') + if keyword.iskeyword(clean_name) or keyword.issoftkeyword(clean_name): + values.append(None) + else: + try: + values.append(eval(name, self.namespace)) + except Exception: + values.append(None) + if self.use_colors and names: + return self.colorize_matches(names, values) + return names + + def attr_matches(self, text): + try: + expr, attr, names, values = self._attr_matches(text) + except ValueError: + return [] + + if not names: + return [] + + if len(names) == 1: + # No coloring: when returning a single completion, readline + # inserts it directly into the prompt, so ANSI codes would + # appear as literal characters. + return [self._callable_attr_postfix(values[0], f'{expr}.{names[0]}')] + + prefix = commonprefix(names) + if prefix and prefix != attr: + return [f'{expr}.{prefix}'] # autocomplete prefix + + names = [f'{expr}.{name}' for name in names] + if self.use_colors: + return self.colorize_matches(names, values) + + if prefix: + names.append(' ') + return names + + def _attr_matches(self, text): + expr, attr = text.rsplit('.', 1) + if '(' in expr or ')' in expr: # don't call functions + return expr, attr, [], [] + try: + thisobject = eval(expr, self.namespace) + except Exception: + return expr, attr, [], [] + + # get the content of the object, except __builtins__ + words = set(dir(thisobject)) - {'__builtins__'} + + if hasattr(thisobject, '__class__'): + words.add('__class__') + words.update(rlcompleter.get_class_members(thisobject.__class__)) + names = [] + values = [] + n = len(attr) + if attr == '': + noprefix = '_' + elif attr == '_': + noprefix = '__' + else: + noprefix = None + + # sort the words now to make sure to return completions in + # alphabetical order. It's easier to do it now, else we would need to + # sort 'names' later but make sure that 'values' in kept in sync, + # which is annoying. + words = sorted(words) + while True: + for word in words: + if ( + word[:n] == attr + and not (noprefix and word[:n+1] == noprefix) + ): + # Mirror rlcompleter's safeguards so completion does not + # call properties or reify lazy module attributes. + if isinstance(getattr(type(thisobject), word, None), property): + value = None + elif ( + isinstance(thisobject, types.ModuleType) + and isinstance( + thisobject.__dict__.get(word), + types.LazyImportType, + ) + ): + value = thisobject.__dict__.get(word) + else: + value = getattr(thisobject, word, None) + + names.append(word) + values.append(value) + if names or not noprefix: + break + if noprefix == '_': + noprefix = '__' + else: + noprefix = None + + return expr, attr, names, values + + def colorize_matches(self, names, values): + matches = [self._color_for_obj(i, name, obj) + for i, (name, obj) + in enumerate(zip(names, values))] + # We add a space at the end to prevent the automatic completion of the + # common prefix, which is the ANSI escape sequence. + matches.append(' ') + return matches + + def _color_for_obj(self, i, name, value): + t = type(value) + color = self._color_by_type(t) + # Encode the match index into a fake escape sequence that + # stripcolor() can still remove once i reaches four digits. + N = f"\x1b[{i // 100:03d};{i % 100:02d}m" + return f"{N}{color}{name}{ANSIColors.RESET}" + + def _color_by_type(self, t): + typename = t.__name__ + # this is needed e.g. to turn method-wrapper into method_wrapper, + # because if we want _colorize.FancyCompleter to be "dataclassable" + # our keys need to be valid identifiers. + typename = typename.replace('-', '_').replace('.', '_') + return getattr(self.theme.fancycompleter, typename, ANSIColors.RESET) + + +def commonprefix(names): + """Return the common prefix of all 'names'""" + if not names: + return '' + s1 = min(names) + s2 = max(names) + for i, c in enumerate(s1): + if c != s2[i]: + return s1[:i] + return s1 diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index 23b8fa6b9c7..17319963b19 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -40,6 +40,7 @@ from .completing_reader import CompletingReader from .console import Console as ConsoleType from ._module_completer import ModuleCompleter, make_default_module_completer +from .fancycompleter import Completer as FancyCompleter Console: type[ConsoleType] _error: tuple[type[Exception], ...] | type[Exception] @@ -609,7 +610,12 @@ def _setup(namespace: Mapping[str, Any]) -> None: if not isinstance(namespace, dict): namespace = dict(namespace) _wrapper.config.module_completer = ModuleCompleter(namespace) - _wrapper.config.readline_completer = RLCompleter(namespace).complete + use_basic_completer = ( + not sys.flags.ignore_environment + and os.getenv("PYTHON_BASIC_COMPLETER") + ) + completer_cls = RLCompleter if use_basic_completer else FancyCompleter + _wrapper.config.readline_completer = completer_cls(namespace).complete # this is not really what readline.c does. Better than nothing I guess import builtins diff --git a/Lib/test/test_pyrepl/test_fancycompleter.py b/Lib/test/test_pyrepl/test_fancycompleter.py new file mode 100644 index 00000000000..77c80853a3c --- /dev/null +++ b/Lib/test/test_pyrepl/test_fancycompleter.py @@ -0,0 +1,247 @@ +import importlib +import os +import types +import unittest + +from _colorize import ANSIColors, get_theme +from _pyrepl.completing_reader import stripcolor +from _pyrepl.fancycompleter import Completer, commonprefix +from test.support.import_helper import ready_to_import + +class MockPatch: + def __init__(self): + self.original_values = {} + + def setattr(self, obj, name, value): + if obj not in self.original_values: + self.original_values[obj] = {} + if name not in self.original_values[obj]: + self.original_values[obj][name] = getattr(obj, name) + setattr(obj, name, value) + + def restore_all(self): + for obj, attrs in self.original_values.items(): + for name, value in attrs.items(): + setattr(obj, name, value) + +class FancyCompleterTests(unittest.TestCase): + def setUp(self): + self.mock_patch = MockPatch() + + def tearDown(self): + self.mock_patch.restore_all() + + def test_commonprefix(self): + self.assertEqual(commonprefix(['isalpha', 'isdigit', 'foo']), '') + self.assertEqual(commonprefix(['isalpha', 'isdigit']), 'is') + self.assertEqual(commonprefix([]), '') + + def test_complete_attribute(self): + compl = Completer({'a': None}, use_colors=False) + self.assertEqual(compl.attr_matches('a.'), ['a.__']) + matches = compl.attr_matches('a.__') + self.assertNotIn('__class__', matches) + self.assertIn('a.__class__', matches) + match = compl.attr_matches('a.__class') + self.assertEqual(len(match), 1) + self.assertTrue(match[0].startswith('a.__class__')) + + def test_complete_attribute_prefix(self): + class C(object): + attr = 1 + _attr = 2 + __attr__attr = 3 + compl = Completer({'a': C}, use_colors=False) + self.assertEqual(compl.attr_matches('a.'), ['a.attr', 'a.mro']) + self.assertEqual( + compl.attr_matches('a._'), + ['a._C__attr__attr', 'a._attr', ' '], + ) + matches = compl.attr_matches('a.__') + self.assertNotIn('__class__', matches) + self.assertIn('a.__class__', matches) + match = compl.attr_matches('a.__class') + self.assertEqual(len(match), 1) + self.assertTrue(match[0].startswith('a.__class__')) + + compl = Completer({'a': None}, use_colors=False) + self.assertEqual(compl.attr_matches('a._'), ['a.__']) + + def test_complete_attribute_colored(self): + theme = get_theme() + compl = Completer({'a': 42}, use_colors=True) + matches = compl.attr_matches('a.__') + self.assertGreater(len(matches), 2) + expected_color = theme.fancycompleter.type + expected_part = f'{expected_color}a.__class__{ANSIColors.RESET}' + for match in matches: + if expected_part in match: + break + else: + self.assertFalse(True, matches) + self.assertIn(' ', matches) + + def test_preserves_callable_postfix_for_single_attribute_match(self): + compl = Completer({'os': os}, use_colors=False) + self.assertEqual(compl.attr_matches('os.getpid'), ['os.getpid()']) + + def test_property_method_not_called(self): + class Foo: + property_called = False + + @property + def bar(self): + self.property_called = True + return 1 + + foo = Foo() + compl = Completer({'foo': foo}, use_colors=False) + self.assertEqual(compl.attr_matches('foo.b'), ['foo.bar']) + self.assertFalse(foo.property_called) + + def test_excessive_getattr(self): + class Foo: + calls = 0 + bar = '' + + def __getattribute__(self, name): + if name == 'bar': + self.calls += 1 + return None + return super().__getattribute__(name) + + foo = Foo() + compl = Completer({'foo': foo}, use_colors=False) + self.assertEqual(compl.complete('foo.b', 0), 'foo.bar') + self.assertEqual(foo.calls, 1) + + def test_uncreated_attr(self): + class Foo: + __slots__ = ('bar',) + + compl = Completer({'foo': Foo()}, use_colors=False) + self.assertEqual(compl.complete('foo.', 0), 'foo.bar') + + def test_module_attributes_do_not_reify_lazy_imports(self): + with ready_to_import("test_pyrepl_lazy_mod", "lazy import json\n") as (name, _): + module = importlib.import_module(name) + self.assertIs(type(module.__dict__["json"]), types.LazyImportType) + + compl = Completer({name: module}, use_colors=False) + self.assertEqual(compl.attr_matches(f"{name}.j"), [f"{name}.json"]) + self.assertIs(type(module.__dict__["json"]), types.LazyImportType) + + def test_complete_colored_single_match(self): + """No coloring, via commonprefix.""" + compl = Completer({'foobar': 42}, use_colors=True) + matches = compl.global_matches('foob') + self.assertEqual(matches, ['foobar']) + + def test_does_not_color_single_match(self): + class obj: + msgs = [] + + compl = Completer({'obj': obj}, use_colors=True) + matches = compl.attr_matches('obj.msgs') + self.assertEqual(matches, ['obj.msgs']) + + def test_complete_global(self): + compl = Completer({'foobar': 1, 'foobazzz': 2}, use_colors=False) + self.assertEqual(compl.global_matches('foo'), ['fooba']) + matches = compl.global_matches('fooba') + self.assertEqual(set(matches), set(['foobar', 'foobazzz'])) + self.assertEqual(compl.global_matches('foobaz'), ['foobazzz']) + self.assertEqual(compl.global_matches('nothing'), []) + + def test_complete_global_colored(self): + theme = get_theme() + compl = Completer({'foobar': 1, 'foobazzz': 2}, use_colors=True) + self.assertEqual(compl.global_matches('foo'), ['fooba']) + matches = compl.global_matches('fooba') + + # these are the fake escape sequences which are needed so that + # readline displays the matches in the proper order + N0 = f"\x1b[000;00m" + N1 = f"\x1b[000;01m" + int_color = theme.fancycompleter.int + self.assertEqual(set(matches), { + ' ', + f'{N0}{int_color}foobar{ANSIColors.RESET}', + f'{N1}{int_color}foobazzz{ANSIColors.RESET}', + }) + self.assertEqual(compl.global_matches('foobaz'), ['foobazzz']) + self.assertEqual(compl.global_matches('nothing'), []) + + def test_large_color_sort_prefix_is_stripped(self): + compl = Completer({'a': 42}, use_colors=True) + match = compl._color_for_obj(1000, 'spam', 1) + self.assertEqual(stripcolor(match), 'spam') + + def test_complete_with_indexer(self): + compl = Completer({'lst': [None, 2, 3]}, use_colors=False) + self.assertEqual(compl.attr_matches('lst[0].'), ['lst[0].__']) + matches = compl.attr_matches('lst[0].__') + self.assertNotIn('__class__', matches) + self.assertIn('lst[0].__class__', matches) + match = compl.attr_matches('lst[0].__class') + self.assertEqual(len(match), 1) + self.assertTrue(match[0].startswith('lst[0].__class__')) + + def test_autocomplete(self): + class A: + aaa = None + abc_1 = None + abc_2 = None + abc_3 = None + bbb = None + compl = Completer({'A': A}, use_colors=False) + # + # In this case, we want to display all attributes which start with + # 'a'. Moreover, we also include a space to prevent readline to + # automatically insert the common prefix (which will the the ANSI escape + # sequence if we use colors). + matches = compl.attr_matches('A.a') + self.assertEqual( + sorted(matches), + [' ', 'A.aaa', 'A.abc_1', 'A.abc_2', 'A.abc_3'], + ) + # + # If there is an actual common prefix, we return just it, so that readline + # will insert it into place + matches = compl.attr_matches('A.ab') + self.assertEqual(matches, ['A.abc_']) + # + # Finally, at the next tab, we display again all the completions available + # for this common prefix. Again, we insert a spurious space to prevent the + # automatic completion of ANSI sequences. + matches = compl.attr_matches('A.abc_') + self.assertEqual( + sorted(matches), + [' ', 'A.abc_1', 'A.abc_2', 'A.abc_3'], + ) + + def test_complete_exception(self): + compl = Completer({}, use_colors=False) + self.assertEqual(compl.attr_matches('xxx.'), []) + + def test_complete_invalid_attr(self): + compl = Completer({'str': str}, use_colors=False) + self.assertEqual(compl.attr_matches('str.xx'), []) + + def test_complete_function_skipped(self): + compl = Completer({'str': str}, use_colors=False) + self.assertEqual(compl.attr_matches('str.split().'), []) + + def test_unicode_in___dir__(self): + class Foo(object): + def __dir__(self): + return ['hello', 'world'] + + compl = Completer({'a': Foo()}, use_colors=False) + matches = compl.attr_matches('a.') + self.assertEqual(matches, ['a.hello', 'a.world']) + self.assertIs(type(matches[0]), str) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 8854b19efce..18e88ce4e77 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -33,6 +33,8 @@ ModuleCompleter, HARDCODED_SUBMODULES, ) +from _pyrepl.fancycompleter import Completer as FancyCompleter +import _pyrepl.readline as pyrepl_readline from _pyrepl.readline import ( ReadlineAlikeReader, ReadlineConfig, @@ -941,6 +943,92 @@ def test_func(self): self.assertEqual(mock_stderr.getvalue(), "") +class TestPyReplFancyCompleter(TestCase): + def prepare_reader(self, events, namespace, *, use_colors): + console = FakeConsole(events) + config = ReadlineConfig() + config.readline_completer = FancyCompleter( + namespace, use_colors=use_colors + ).complete + reader = ReadlineAlikeReader(console=console, config=config) + return reader + + def test_simple_completion_preserves_callable_postfix(self): + events = code_to_events("os.getpid\t\n") + + namespace = {"os": os} + reader = self.prepare_reader(events, namespace, use_colors=False) + + output = multiline_input(reader, namespace) + self.assertEqual(output, "os.getpid()") + + def test_attribute_menu_tracks_typed_stem(self): + class Obj: + apple = 1 + apricot = 2 + banana = 3 + + namespace = {"obj": Obj} + reader = self.prepare_reader( + code_to_events("obj.\t\ta"), + namespace, + use_colors=True, + ) + + with self.assertRaises(StopIteration): + while True: + reader.handle1() + + self.assertEqual("".join(reader.buffer), "obj.a") + self.assertTrue(reader.cmpltn_menu_visible) + menu = "\n".join(reader.cmpltn_menu) + self.assertIn("apple", menu) + self.assertIn("apricot", menu) + self.assertNotIn("banana", menu) + self.assertNotIn("mro", menu) + + +class TestPyReplReadlineSetup(TestCase): + def test_setup_ignores_basic_completer_env_when_env_is_disabled(self): + class FakeFancyCompleter: + def __init__(self, namespace): + self.namespace = namespace + + def complete(self, text, state): + return None + + class FakeBasicCompleter(FakeFancyCompleter): + pass + + wrapper = Mock() + wrapper.config = ReadlineConfig() + stdin = Mock() + stdout = Mock() + stdin.fileno.return_value = 0 + stdout.fileno.return_value = 1 + + with ( + patch.object(pyrepl_readline, "_wrapper", wrapper), + patch.object(pyrepl_readline, "raw_input", None), + patch.object(pyrepl_readline, "FancyCompleter", FakeFancyCompleter), + patch.object(pyrepl_readline, "RLCompleter", FakeBasicCompleter), + patch.object(pyrepl_readline.sys, "stdin", stdin), + patch.object(pyrepl_readline.sys, "stdout", stdout), + patch.object(pyrepl_readline.sys, "flags", Mock(ignore_environment=True)), + patch.object(pyrepl_readline.os, "isatty", return_value=True), + patch.object(pyrepl_readline.os, "getenv") as mock_getenv, + patch("builtins.input", lambda prompt="": prompt), + ): + mock_getenv.return_value = "1" + pyrepl_readline._setup({}) + + self.assertIsInstance( + wrapper.config.readline_completer.__self__, + FakeFancyCompleter, + ) + mock_getenv.assert_not_called() + + class TestPyReplModuleCompleter(TestCase): def setUp(self): # Make iter_modules() search only the standard library. diff --git a/Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst b/Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst new file mode 100644 index 00000000000..3d2a7f00d3e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst @@ -0,0 +1 @@ +Add fancycompleter and enable it by default when using pyrepl. This gives colored tab completion. From 668c5723ebf30441961fceb7795566c17222c04b Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Sun, 5 Apr 2026 17:25:14 +0200 Subject: [PATCH 416/775] GH-139922: add interpreter types to InternalDocs/interpreter.md (GH-148035) --- InternalDocs/interpreter.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/InternalDocs/interpreter.md b/InternalDocs/interpreter.md index 75acdf596a7..7fc41a807dd 100644 --- a/InternalDocs/interpreter.md +++ b/InternalDocs/interpreter.md @@ -507,6 +507,38 @@ ### Maintaining stats After an optimization has been deferred in the adaptive instruction, that should be recorded with `STAT_INC(BASE_INSTRUCTION, deferred)`. +## Interpreter types +There are three different types of interpreters to choose from based on compiler support: + + * traditional switch-case interpreter + + Supported by all compilers covered in PEP 7. + + * computed-gotos interpreter + + Enabled using configure option `--with-computed-gotos` and used by default on supported compilers. + It uses [Labels as Values](https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) + for more efficient dispatching. + + * tail-calling interpreter + + Enabled using configure option `--with-tail-call-interp` (or `--tail-call-interp` for build.bat on Windows). + It uses [tail calls](https://clang.llvm.org/docs/AttributeReference.html#musttail) and the + [preserve_none](https://clang.llvm.org/docs/AttributeReference.html#preserve-none) + calling convention between the small C functions that implement individual Python opcodes. + + Not all compilers support these and if they do not all targets might be supported (for example, + MSVC currently only supports x64 and only in optimized builds). + + In addition, compilers must do [escape analysis](https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html#index-musttail) + of the lifetimes of automatic variables, function parameters, and temporaries to ensure proper tail-calls. They + emit a compile error in case of a violation or detection failure. The ability to detect this varies depending on the compiler and + also on the optimization level. Following techniques are particularly helpful to the MSVC compiler in this regard + * [Introducing additional scopes](https://github.com/python/cpython/blob/3908593039bde9d4b591ab09919003ee57418d64/Python/bytecodes.c#L2526) + * [extracting problematic code paths into a separate function](https://github.com/python/cpython/pull/143068/files#diff-729a985b0cb8b431cb291f1edb561bbbfea22e3f8c262451cd83328a0936a342R3724) + * [returning a pointer instead of taking it as an output parameter](https://github.com/python/cpython/blob/3908593039bde9d4b591ab09919003ee57418d64/Include/internal/pycore_ceval.h#L489-L492) + + Using `restrict` is another (currently unused) remedy. Additional resources -------------------- From 77fc2f5a5e4ca92c609b87425a4080b71c5fa188 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Sun, 5 Apr 2026 16:29:38 +0100 Subject: [PATCH 417/775] gh-144319: Fix huge page leak in datastack chunk allocator (#147963) Fix huge page leak in datastack chunk allocator The original fix rounded datastack chunk allocations in pystate.c so that _PyObject_VirtualFree() would receive the full huge page mapping size. Change direction and move that logic into _PyObject_VirtualAlloc() and _PyObject_VirtualFree() instead. The key invariant is that munmap() must see the full mapped size, so alloc and free now apply the same platform-specific rounding in the allocator layer. This keeps _PyStackChunk bookkeeping in requested-size units, avoids a hardcoded 2 MB assumption, and also covers other small virtual-memory users such as the JIT tracer state allocation in optimizer.c. --- Include/internal/pycore_obmalloc.h | 6 +- ...-04-01-12-52-31.gh-issue-144319.iZk4hs.rst | 3 + Objects/obmalloc.c | 60 ++++++++++++++++++- 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst diff --git a/Include/internal/pycore_obmalloc.h b/Include/internal/pycore_obmalloc.h index 0b23bb48dd5..d4dbe541e6d 100644 --- a/Include/internal/pycore_obmalloc.h +++ b/Include/internal/pycore_obmalloc.h @@ -691,7 +691,11 @@ struct _obmalloc_state { /* Allocate memory directly from the O/S virtual memory system, - * where supported. Otherwise fallback on malloc */ + * where supported. Otherwise fallback on malloc. + * + * Large-page and huge-page backends may round the mapped size up + * internally, so pass the original requested size back to + * _PyObject_VirtualFree(). */ void *_PyObject_VirtualAlloc(size_t size); void _PyObject_VirtualFree(void *, size_t size); diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst new file mode 100644 index 00000000000..f3f07ab35db --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst @@ -0,0 +1,3 @@ +Fix a bug that could cause applications with specific allocation patterns to +leak memory via Huge Pages if compiled with Huge Page support. Patch by +Pablo Galindo diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 983bdddbf02..e2d5b012955 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -14,6 +14,7 @@ #include // malloc() #include #include // fopen(), fgets(), sscanf() +#include // errno #ifdef WITH_MIMALLOC // Forward declarations of functions used in our mimalloc modifications static void _PyMem_mi_page_clear_qsbr(mi_page_t *page); @@ -572,6 +573,49 @@ _pymalloc_system_hugepage_size(void) } #endif +#if (defined(MS_WINDOWS) && defined(PYMALLOC_USE_HUGEPAGES)) || \ + (defined(PYMALLOC_USE_HUGEPAGES) && defined(ARENAS_USE_MMAP) && defined(MAP_HUGETLB)) +static size_t +_pymalloc_round_up_to_multiple(size_t size, size_t multiple) +{ + if (multiple == 0 || size == 0) { + return size; + } + + size_t remainder = size % multiple; + if (remainder == 0) { + return size; + } + + size_t padding = multiple - remainder; + if (size > SIZE_MAX - padding) { + return 0; + } + return size + padding; +} +#endif + +static size_t +_pymalloc_virtual_alloc_size(size_t size) +{ +#if defined(MS_WINDOWS) && defined(PYMALLOC_USE_HUGEPAGES) + if (_PyRuntime.allocators.use_hugepages) { + SIZE_T large_page_size = GetLargePageMinimum(); + if (large_page_size > 0) { + return _pymalloc_round_up_to_multiple(size, (size_t)large_page_size); + } + } +#elif defined(PYMALLOC_USE_HUGEPAGES) && defined(ARENAS_USE_MMAP) && defined(MAP_HUGETLB) + if (_PyRuntime.allocators.use_hugepages) { + size_t hp_size = _pymalloc_system_hugepage_size(); + if (hp_size > 0) { + return _pymalloc_round_up_to_multiple(size, hp_size); + } + } +#endif + return size; +} + void * _PyMem_ArenaAlloc(void *Py_UNUSED(ctx), size_t size) { @@ -648,7 +692,11 @@ _PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr, if (ptr == NULL) { return; } - munmap(ptr, size); + if (munmap(ptr, size) < 0) { + _Py_FatalErrorFormat(__func__, + "munmap(%p, %zu) failed with errno %d", + ptr, size, errno); + } #else free(ptr); #endif @@ -1128,13 +1176,19 @@ PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator) void * _PyObject_VirtualAlloc(size_t size) { - return _PyObject_Arena.alloc(_PyObject_Arena.ctx, size); + size_t alloc_size = _pymalloc_virtual_alloc_size(size); + if (alloc_size == 0 && size != 0) { + return NULL; + } + return _PyObject_Arena.alloc(_PyObject_Arena.ctx, alloc_size); } void _PyObject_VirtualFree(void *obj, size_t size) { - _PyObject_Arena.free(_PyObject_Arena.ctx, obj, size); + size_t alloc_size = _pymalloc_virtual_alloc_size(size); + assert(alloc_size != 0 || size == 0); + _PyObject_Arena.free(_PyObject_Arena.ctx, obj, alloc_size); } From a1cf4430ed89ec702528ef074138c407ccf89946 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Sun, 5 Apr 2026 11:07:07 -0700 Subject: [PATCH 418/775] gh-94632: document the subprocess need for extra_groups=() with user= (GH-148129) --- Doc/library/subprocess.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 9e261a0ca03..fe64daa3291 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -627,6 +627,12 @@ functions. the value in ``pw_uid`` will be used. If the value is an integer, it will be passed verbatim. (POSIX only) + .. note:: + + Specifying *user* will not drop existing supplementary group memberships! + The caller must also pass ``extra_groups=()`` to reduce the group membership + of the child process for security purposes. + .. availability:: POSIX .. versionadded:: 3.9 From d6e044512c59ab7b83f14e00e7047756a31ac3e3 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Sun, 5 Apr 2026 19:22:10 +0100 Subject: [PATCH 419/775] Silence `unused-variable` warnings in `optimizer_cases.c.h` (#148127) --- Python/optimizer_bytecodes.c | 3 +++ Python/optimizer_cases.c.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index f2645553513..b8148ef57ed 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -2124,18 +2124,21 @@ dummy_func(void) { } op(_GUARD_CODE_VERSION_RETURN_VALUE, (version/2 -- )) { + (void)version; if (ctx->frame->caller) { REPLACE_OP(this_instr, _NOP, 0, 0); } } op(_GUARD_CODE_VERSION_YIELD_VALUE, (version/2 -- )) { + (void)version; if (ctx->frame->caller) { REPLACE_OP(this_instr, _NOP, 0, 0); } } op(_GUARD_CODE_VERSION_RETURN_GENERATOR, (version/2 -- )) { + (void)version; if (ctx->frame->caller) { REPLACE_OP(this_instr, _NOP, 0, 0); } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index fb3ec39a42e..a15b5ae1d13 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -5092,6 +5092,7 @@ case _GUARD_CODE_VERSION_YIELD_VALUE: { uint32_t version = (uint32_t)this_instr->operand0; + (void)version; if (ctx->frame->caller) { REPLACE_OP(this_instr, _NOP, 0, 0); } @@ -5100,6 +5101,7 @@ case _GUARD_CODE_VERSION_RETURN_VALUE: { uint32_t version = (uint32_t)this_instr->operand0; + (void)version; if (ctx->frame->caller) { REPLACE_OP(this_instr, _NOP, 0, 0); } @@ -5108,6 +5110,7 @@ case _GUARD_CODE_VERSION_RETURN_GENERATOR: { uint32_t version = (uint32_t)this_instr->operand0; + (void)version; if (ctx->frame->caller) { REPLACE_OP(this_instr, _NOP, 0, 0); } From c64baff1d82e8a113d971869b6074551e99eece9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Simon?= Date: Sun, 5 Apr 2026 20:31:19 +0200 Subject: [PATCH 420/775] gh-69605: Add math.integer to PyREPL module completer hardcoded list (#144811) --- Lib/_pyrepl/_module_completer.py | 1 + Lib/test/test_pyrepl/test_pyrepl.py | 1 + .../2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst | 1 + 3 files changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst diff --git a/Lib/_pyrepl/_module_completer.py b/Lib/_pyrepl/_module_completer.py index 2098d0a54ab..bba59599e97 100644 --- a/Lib/_pyrepl/_module_completer.py +++ b/Lib/_pyrepl/_module_completer.py @@ -23,6 +23,7 @@ # Standard library submodules that are not detected by pkgutil.iter_modules # but can be imported, so should be proposed in completion "collections": ["abc"], + "math": ["integer"], "os": ["path"], "xml.parsers.expat": ["errors", "model"], } diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 18e88ce4e77..82628f79279 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -1187,6 +1187,7 @@ def test_hardcoded_stdlib_submodules(self): cases = ( ("import collections.\t\n", "import collections.abc"), ("from os import \t\n", "from os import path"), + ("import math.\t\n", "import math.integer"), ("import xml.parsers.expat.\t\te\t\n\n", "import xml.parsers.expat.errors"), ("from xml.parsers.expat import \t\tm\t\n\n", "from xml.parsers.expat import model"), ) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst new file mode 100644 index 00000000000..c00b7b99f8e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst @@ -0,0 +1 @@ +Add :mod:`math.integer` to :term:`REPL` auto-completion of imports. From b07becb57371b733b9cc91233ab93b02a6b2f014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Simon?= Date: Sun, 5 Apr 2026 21:10:59 +0200 Subject: [PATCH 421/775] gh-140870: PyREPL auto-complete module attributes in import statements (#140871) Co-authored-by: Pablo Galindo Salgado --- Lib/_pyrepl/_module_completer.py | 118 ++++++-- Lib/_pyrepl/completing_reader.py | 35 ++- Lib/_pyrepl/reader.py | 13 +- Lib/_pyrepl/readline.py | 10 +- Lib/_pyrepl/types.py | 1 + Lib/test/test_pyrepl/test_pyrepl.py | 251 +++++++++++++++++- ...-11-01-01-49-52.gh-issue-140870.iknc12.rst | 2 + 7 files changed, 393 insertions(+), 37 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst diff --git a/Lib/_pyrepl/_module_completer.py b/Lib/_pyrepl/_module_completer.py index bba59599e97..a22b0297b24 100644 --- a/Lib/_pyrepl/_module_completer.py +++ b/Lib/_pyrepl/_module_completer.py @@ -3,6 +3,7 @@ import importlib import os import pkgutil +import re import sys import token import tokenize @@ -16,7 +17,9 @@ TYPE_CHECKING = False if TYPE_CHECKING: + from types import ModuleType from typing import Any, Iterable, Iterator, Mapping + from .types import CompletionAction HARDCODED_SUBMODULES = { @@ -28,6 +31,17 @@ "xml.parsers.expat": ["errors", "model"], } +AUTO_IMPORT_DENYLIST = { + # Standard library modules/submodules that have import side effects + # and must not be automatically imported to complete attributes + re.compile(r"antigravity"), # Calls webbrowser.open + re.compile(r"idlelib\..+"), # May open IDLE GUI + re.compile(r"test\..+"), # Various side-effects + re.compile(r"this"), # Prints to stdout + re.compile(r"_ios_support"), # Spawns a subprocess + re.compile(r".+\.__main__"), # Should not be imported +} + def make_default_module_completer() -> ModuleCompleter: # Inside pyrepl, __package__ is set to None by default @@ -53,11 +67,17 @@ class ModuleCompleter: def __init__(self, namespace: Mapping[str, Any] | None = None) -> None: self.namespace = namespace or {} self._global_cache: list[pkgutil.ModuleInfo] = [] + self._failed_imports: set[str] = set() self._curr_sys_path: list[str] = sys.path[:] self._stdlib_path = os.path.dirname(importlib.__path__[0]) - def get_completions(self, line: str) -> list[str] | None: - """Return the next possible import completions for 'line'.""" + def get_completions(self, line: str) -> tuple[list[str], CompletionAction | None] | None: + """Return the next possible import completions for 'line'. + + For attributes completion, if the module to complete from is not + imported, also return an action (prompt + callback to run if the + user press TAB again) to import the module. + """ result = ImportParser(line).parse() if not result: return None @@ -66,24 +86,26 @@ def get_completions(self, line: str) -> list[str] | None: except Exception: # Some unexpected error occurred, make it look like # no completions are available - return [] + return [], None - def complete(self, from_name: str | None, name: str | None) -> list[str]: + def complete(self, from_name: str | None, name: str | None) -> tuple[list[str], CompletionAction | None]: if from_name is None: # import x.y.z assert name is not None path, prefix = self.get_path_and_prefix(name) modules = self.find_modules(path, prefix) - return [self.format_completion(path, module) for module in modules] + return [self.format_completion(path, module) for module in modules], None if name is None: # from x.y.z path, prefix = self.get_path_and_prefix(from_name) modules = self.find_modules(path, prefix) - return [self.format_completion(path, module) for module in modules] + return [self.format_completion(path, module) for module in modules], None # from x.y import z - return self.find_modules(from_name, name) + submodules = self.find_modules(from_name, name) + attributes, action = self.find_attributes(from_name, name) + return sorted({*submodules, *attributes}), action def find_modules(self, path: str, prefix: str) -> list[str]: """Find all modules under 'path' that start with 'prefix'.""" @@ -101,23 +123,25 @@ def _find_modules(self, path: str, prefix: str) -> list[str]: if self.is_suggestion_match(module.name, prefix)] return sorted(builtin_modules + third_party_modules) - if path.startswith('.'): - # Convert relative path to absolute path - package = self.namespace.get('__package__', '') - path = self.resolve_relative_name(path, package) # type: ignore[assignment] - if path is None: - return [] + path = self._resolve_relative_path(path) # type: ignore[assignment] + if path is None: + return [] modules: Iterable[pkgutil.ModuleInfo] = self.global_cache imported_module = sys.modules.get(path.split('.')[0]) if imported_module: - # Filter modules to those who name and specs match the + # Filter modules to those whose name and specs match the # imported module to avoid invalid suggestions spec = imported_module.__spec__ if spec: + def _safe_find_spec(mod: pkgutil.ModuleInfo) -> bool: + try: + return mod.module_finder.find_spec(mod.name, None) == spec + except Exception: + return False modules = [mod for mod in modules if mod.name == spec.name - and mod.module_finder.find_spec(mod.name, None) == spec] + and _safe_find_spec(mod)] else: modules = [] @@ -142,6 +166,32 @@ def _is_stdlib_module(self, module_info: pkgutil.ModuleInfo) -> bool: return (isinstance(module_info.module_finder, FileFinder) and module_info.module_finder.path == self._stdlib_path) + def find_attributes(self, path: str, prefix: str) -> tuple[list[str], CompletionAction | None]: + """Find all attributes of module 'path' that start with 'prefix'.""" + attributes, action = self._find_attributes(path, prefix) + # Filter out invalid attribute names + # (for example those containing dashes that cannot be imported with 'import') + return [attr for attr in attributes if attr.isidentifier()], action + + def _find_attributes(self, path: str, prefix: str) -> tuple[list[str], CompletionAction | None]: + path = self._resolve_relative_path(path) # type: ignore[assignment] + if path is None: + return [], None + + imported_module = sys.modules.get(path) + if not imported_module: + if path in self._failed_imports: # Do not propose to import again + return [], None + imported_module = self._maybe_import_module(path) + if not imported_module: + return [], self._get_import_completion_action(path) + try: + module_attributes = dir(imported_module) + except Exception: + module_attributes = [] + return [attr_name for attr_name in module_attributes + if self.is_suggestion_match(attr_name, prefix)], None + def is_suggestion_match(self, module_name: str, prefix: str) -> bool: if prefix: return module_name.startswith(prefix) @@ -186,6 +236,13 @@ def format_completion(self, path: str, module: str) -> str: return f'{path}{module}' return f'{path}.{module}' + def _resolve_relative_path(self, path: str) -> str | None: + """Resolve a relative import path to absolute. Returns None if unresolvable.""" + if path.startswith('.'): + package = self.namespace.get('__package__', '') + return self.resolve_relative_name(path, package) + return path + def resolve_relative_name(self, name: str, package: str) -> str | None: """Resolve a relative module name to an absolute name. @@ -210,8 +267,39 @@ def global_cache(self) -> list[pkgutil.ModuleInfo]: if not self._global_cache or self._curr_sys_path != sys.path: self._curr_sys_path = sys.path[:] self._global_cache = list(pkgutil.iter_modules()) + self._failed_imports.clear() # retry on sys.path change return self._global_cache + def _maybe_import_module(self, fqname: str) -> ModuleType | None: + if any(pattern.fullmatch(fqname) for pattern in AUTO_IMPORT_DENYLIST): + # Special-cased modules with known import side-effects + return None + root = fqname.split(".")[0] + mod_info = next((m for m in self.global_cache if m.name == root), None) + if not mod_info or not self._is_stdlib_module(mod_info): + # Only import stdlib modules (no risk of import side-effects) + return None + try: + return importlib.import_module(fqname) + except Exception: + sys.modules.pop(fqname, None) # Clean half-imported module + return None + + def _get_import_completion_action(self, path: str) -> CompletionAction: + prompt = ("[ module not imported, press again to import it " + "and propose attributes ]") + + def _do_import() -> str | None: + try: + importlib.import_module(path) + return None + except Exception as exc: + sys.modules.pop(path, None) # Clean half-imported module + self._failed_imports.add(path) + return f"[ error during import: {exc} ]" + + return (prompt, _do_import) + class ImportParser: """ diff --git a/Lib/_pyrepl/completing_reader.py b/Lib/_pyrepl/completing_reader.py index 5802920a907..39d0a8af5df 100644 --- a/Lib/_pyrepl/completing_reader.py +++ b/Lib/_pyrepl/completing_reader.py @@ -29,8 +29,9 @@ # types Command = commands.Command -if False: - from .types import KeySpec, CommandName +TYPE_CHECKING = False +if TYPE_CHECKING: + from .types import KeySpec, CommandName, CompletionAction def prefix(wordlist: list[str], j: int = 0) -> str: @@ -168,15 +169,25 @@ def do(self) -> None: r: CompletingReader r = self.reader # type: ignore[assignment] last_is_completer = r.last_command_is(self.__class__) + if r.cmpltn_action: + if last_is_completer: # double-tab: execute action + msg = r.cmpltn_action[1]() + r.cmpltn_action = None # consumed + if msg: + r.msg = msg + else: # other input since last tab: cancel action + r.cmpltn_action = None + immutable_completions = r.assume_immutable_completions completions_unchangable = last_is_completer and immutable_completions stem = r.get_stem() if not completions_unchangable: - r.cmpltn_menu_choices = r.get_completions(stem) + r.cmpltn_menu_choices, r.cmpltn_action = r.get_completions(stem) completions = r.cmpltn_menu_choices if not completions: - r.error("no matches") + if not r.cmpltn_action: + r.error("no matches") elif len(completions) == 1: completion = stripcolor(completions[0]) if completions_unchangable and len(completion) == len(stem): @@ -204,6 +215,16 @@ def do(self) -> None: r.msg = "[ not unique ]" r.dirty = True + if r.cmpltn_action: + if r.msg and r.cmpltn_message_visible: + # There is already a message (eg. [ not unique ]) that + # would conflict for next tab: cancel action + r.cmpltn_action = None + else: + r.msg = r.cmpltn_action[0] + r.cmpltn_message_visible = True + r.dirty = True + class self_insert(commands.self_insert): def do(self) -> None: @@ -242,6 +263,7 @@ class CompletingReader(Reader): cmpltn_message_visible: bool = field(init=False) cmpltn_menu_end: int = field(init=False) cmpltn_menu_choices: list[str] = field(init=False) + cmpltn_action: CompletionAction | None = field(init=False) def __post_init__(self) -> None: super().__post_init__() @@ -283,6 +305,7 @@ def cmpltn_reset(self) -> None: self.cmpltn_message_visible = False self.cmpltn_menu_end = 0 self.cmpltn_menu_choices = [] + self.cmpltn_action = None def get_stem(self) -> str: st = self.syntax_table @@ -293,8 +316,8 @@ def get_stem(self) -> str: p -= 1 return ''.join(b[p+1:self.pos]) - def get_completions(self, stem: str) -> list[str]: - return [] + def get_completions(self, stem: str) -> tuple[list[str], CompletionAction | None]: + return [], None def get_line(self) -> str: """Return the current line until the cursor position.""" diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py index 9ab92f64d1e..f35a99fb06a 100644 --- a/Lib/_pyrepl/reader.py +++ b/Lib/_pyrepl/reader.py @@ -381,9 +381,17 @@ def calc_screen(self) -> list[str]: self.screeninfo = screeninfo self.cxy = self.pos2xy() if self.msg: + width = self.console.width for mline in self.msg.split("\n"): - screen.append(mline) - screeninfo.append((0, [])) + # If self.msg is larger than console width, make it fit + # TODO: try to split between words? + if not mline: + screen.append("") + screeninfo.append((0, [])) + continue + for r in range((len(mline) - 1) // width + 1): + screen.append(mline[r * width : (r + 1) * width]) + screeninfo.append((0, [])) self.last_refresh_cache.update_cache(self, screen, screeninfo) return screen @@ -628,7 +636,6 @@ def suspend_colorization(self) -> SimpleContextManager: finally: self.can_colorize = old_can_colorize - def finish(self) -> None: """Called when a command signals that we're finished.""" pass diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index 17319963b19..687084601e7 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -56,7 +56,7 @@ # types Command = commands.Command from collections.abc import Callable, Collection -from .types import Callback, Completer, KeySpec, CommandName +from .types import Callback, Completer, KeySpec, CommandName, CompletionAction TYPE_CHECKING = False @@ -135,7 +135,7 @@ def get_stem(self) -> str: p -= 1 return "".join(b[p + 1 : self.pos]) - def get_completions(self, stem: str) -> list[str]: + def get_completions(self, stem: str) -> tuple[list[str], CompletionAction | None]: module_completions = self.get_module_completions() if module_completions is not None: return module_completions @@ -145,7 +145,7 @@ def get_completions(self, stem: str) -> list[str]: while p > 0 and b[p - 1] != "\n": p -= 1 num_spaces = 4 - ((self.pos - p) % 4) - return [" " * num_spaces] + return [" " * num_spaces], None result = [] function = self.config.readline_completer if function is not None: @@ -166,9 +166,9 @@ def get_completions(self, stem: str) -> list[str]: # emulate the behavior of the standard readline that sorts # the completions before displaying them. result.sort() - return result + return result, None - def get_module_completions(self) -> list[str] | None: + def get_module_completions(self) -> tuple[list[str], CompletionAction | None] | None: line = self.get_line() return self.config.module_completer.get_completions(line) diff --git a/Lib/_pyrepl/types.py b/Lib/_pyrepl/types.py index c5b7ebc1a40..e19607bf18e 100644 --- a/Lib/_pyrepl/types.py +++ b/Lib/_pyrepl/types.py @@ -8,3 +8,4 @@ type Completer = Callable[[str, int], str | None] type CharBuffer = list[str] type CharWidths = list[int] +type CompletionAction = tuple[str, Callable[[], str | None]] diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 82628f79279..c3556823c72 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -1,3 +1,4 @@ +import contextlib import importlib import io import itertools @@ -13,7 +14,14 @@ from pkgutil import ModuleInfo from unittest import TestCase, skipUnless, skipIf, SkipTest from unittest.mock import Mock, patch -from test.support import force_not_colorized, make_clean_env, Py_DEBUG +import warnings +from test.support import ( + captured_stdout, + captured_stderr, + force_not_colorized, + make_clean_env, + Py_DEBUG, +) from test.support import has_subprocess_support, SHORT_TIMEOUT, STDLIB_DIR from test.support.import_helper import import_module from test.support.os_helper import EnvironmentVarGuard, unlink @@ -50,6 +58,10 @@ import readline as readline_module except ImportError: readline_module = None +try: + import tkinter +except ImportError: + tkinter = None class ReplTestCase(TestCase): @@ -1050,7 +1062,9 @@ def prepare_reader(self, events, namespace): reader = ReadlineAlikeReader(console=console, config=config) return reader - def test_import_completions(self): + @patch.dict(sys.modules, + {"importlib.resources": object()}) # don't propose to import it + def test_completions(self): cases = ( ("import path\t\n", "import pathlib"), ("import importlib.\t\tres\t\n", "import importlib.resources"), @@ -1104,7 +1118,7 @@ def test_sub_module_private_completions(self): # Return public methods by default ("from foo import \t\n", "from foo import public"), # Return private methods if explicitly specified - ("from foo import _\t\n", "from foo import _private"), + ("from foo import _p\t\n", "from foo import _private"), ) for code, expected in cases: with self.subTest(code=code): @@ -1125,12 +1139,13 @@ def test_builtin_completion_top_level(self): output = reader.readline() self.assertEqual(output, expected) - def test_relative_import_completions(self): + def test_relative_completions(self): cases = ( (None, "from .readl\t\n", "from .readl"), (None, "from . import readl\t\n", "from . import readl"), ("_pyrepl", "from .readl\t\n", "from .readline"), ("_pyrepl", "from . import readl\t\n", "from . import readline"), + ("_pyrepl", "from .readline import mul\t\n", "from .readline import multiline_input"), ("_pyrepl", "from .. import toodeep\t\n", "from .. import toodeep"), ("concurrent", "from .futures.i\t\n", "from .futures.interpreter"), ) @@ -1162,7 +1177,7 @@ def test_no_fallback_on_regular_completion(self): cases = ( ("import pri\t\n", "import pri"), ("from pri\t\n", "from pri"), - ("from typing import Na\t\n", "from typing import Na"), + ("from typong import Na\t\n", "from typong import Na"), ) for code, expected in cases: with self.subTest(code=code): @@ -1175,8 +1190,8 @@ def test_global_cache(self): with (tempfile.TemporaryDirectory() as _dir1, patch.object(sys, "path", [_dir1, *sys.path])): dir1 = pathlib.Path(_dir1) - (dir1 / "mod_aa.py").mkdir() - (dir1 / "mod_bb.py").mkdir() + (dir1 / "mod_aa.py").touch() + (dir1 / "mod_bb.py").touch() events = code_to_events("import mod_a\t\nimport mod_b\t\n") reader = self.prepare_reader(events, namespace={}) output_1, output_2 = reader.readline(), reader.readline() @@ -1186,7 +1201,7 @@ def test_global_cache(self): def test_hardcoded_stdlib_submodules(self): cases = ( ("import collections.\t\n", "import collections.abc"), - ("from os import \t\n", "from os import path"), + ("import os.\t\n", "import os.path"), ("import math.\t\n", "import math.integer"), ("import xml.parsers.expat.\t\te\t\n\n", "import xml.parsers.expat.errors"), ("from xml.parsers.expat import \t\tm\t\n\n", "from xml.parsers.expat import model"), @@ -1300,6 +1315,115 @@ def test_already_imported_module_without_origin_or_spec(self): self.assertEqual(output, f"import {mod}.") del sys.modules[mod] + @patch.dict(sys.modules) + def test_attribute_completion(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("bar = 42") + (dir / "bar.py").write_text("baz = 42") + (dir / "pack").mkdir() + (dir / "pack" / "__init__.py").write_text("attr = 42") + (dir / "pack" / "foo.py").touch() + (dir / "pack" / "bar.py").touch() + (dir / "pack" / "baz.py").touch() + sys.modules.pop("graphlib", None) # test modules may have been imported by previous tests + sys.modules.pop("antigravity", None) + sys.modules.pop("unittest.__main__", None) + with patch.object(sys, "path", [_dir, *sys.path]): + pkgutil.get_importer(_dir).invalidate_caches() + importlib.import_module("bar") + cases = ( + # needs 2 tabs to import (show prompt, then import) + ("from foo import \t\n", "from foo import ", set()), + ("from foo import \t\t\n", "from foo import bar", {"foo"}), + ("from foo import ba\t\n", "from foo import ba", set()), + ("from foo import ba\t\t\n", "from foo import bar", {"foo"}), + # reset if a character is inserted between tabs + ("from foo import \tb\ta\t\n", "from foo import ba", set()), + # packages: needs 3 tabs ([ not unique ], prompt, import) + ("from pack import \t\t\n", "from pack import ", set()), + ("from pack import \t\t\t\n", "from pack import ", {"pack"}), + ("from pack import \t\t\ta\t\n", "from pack import attr", {"pack"}), + # one match: needs 2 tabs (insert + show prompt, import) + ("from pack import f\t\n", "from pack import foo", set()), + ("from pack import f\t\t\n", "from pack import foo", {"pack"}), + # common prefix: needs 3 tabs (insert + [ not unique ], prompt, import) + ("from pack import b\t\n", "from pack import ba", set()), + ("from pack import b\t\t\n", "from pack import ba", set()), + ("from pack import b\t\t\t\n", "from pack import ba", {"pack"}), + # module already imported + ("from bar import b\t\n", "from bar import baz", set()), + # stdlib modules are automatically imported + ("from graphlib import T\t\n", "from graphlib import TopologicalSorter", {"graphlib"}), + # except those with known side-effects + ("from antigravity import g\t\n", "from antigravity import g", set()), + ("from unittest.__main__ import \t\n", "from unittest.__main__ import ", set()), + ) + for code, expected, expected_imports in cases: + with self.subTest(code=code), patch.dict(sys.modules): + _imported = set(sys.modules.keys()) + events = code_to_events(code) + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertEqual(output, expected) + new_imports = sys.modules.keys() - _imported + self.assertEqual(new_imports, expected_imports) + + @patch.dict(sys.modules) + def test_attribute_completion_error_on_import(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("bar = 42") + (dir / "boom.py").write_text("1 <> 2") + with patch.object(sys, "path", [_dir, *sys.path]): + cases = ( + ("from boom import \t\t\n", "from boom import "), + ("from foo import \t\t\n", "from foo import bar"), # still working + ) + for code, expected in cases: + with self.subTest(code=code): + events = code_to_events(code) + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertEqual(output, expected) + self.assertNotIn("boom", sys.modules) + + @patch.dict(sys.modules) + def test_attribute_completion_error_on_attributes_access(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "boom").mkdir() + (dir / "boom"/"__init__.py").write_text("def __dir__(): raise ValueError()") + (dir / "boom"/"submodule.py").touch() + with patch.object(sys, "path", [_dir, *sys.path]): + events = code_to_events("from boom import \t\t\n") # trigger import + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertIn("boom", sys.modules) + # ignore attributes, just propose submodule + self.assertEqual(output, "from boom import submodule") + + @patch.dict(sys.modules) + def test_attribute_completion_private_and_invalid_names(self): + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("_secret = 'bar'") + with patch.object(sys, "path", [_dir, *sys.path]): + mod = importlib.import_module("foo") + mod.__dict__["invalid-identifier"] = "baz" + cases = ( + ("from foo import \t\n", "from foo import "), + ("from foo import _s\t\n", "from foo import _secret"), + ("from foo import inv\t\n", "from foo import inv"), + ) + for code, expected in cases: + with self.subTest(code=code): + events = code_to_events(code) + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertEqual(output, expected) + + def test_get_path_and_prefix(self): cases = ( ('', ('', '')), @@ -1431,8 +1555,119 @@ def test_parse_error(self): with self.subTest(code=code): self.assertEqual(actual, None) + @patch.dict(sys.modules) + def test_suggestions_and_messages(self) -> None: + # more unitary tests checking the exact suggestions provided + # (sorting, de-duplication, import action...) + _prompt = ("[ module not imported, press again to import it " + "and propose attributes ]") + _error = "[ error during import: division by zero ]" + with tempfile.TemporaryDirectory() as _dir: + dir = pathlib.Path(_dir) + (dir / "foo.py").write_text("bar = 42") + (dir / "boom.py").write_text("1/0") + (dir / "pack").mkdir() + (dir / "pack" / "__init__.py").write_text("foo = 1; bar = 2;") + (dir / "pack" / "bar.py").touch() + sys.modules.pop("graphlib", None) # test modules may have been imported by previous tests + sys.modules.pop("string.templatelib", None) + with patch.object(sys, "path", [_dir, *sys.path]): + pkgutil.get_importer(_dir).invalidate_caches() + # NOTE: Cases are intentionally sequential and share completer + # state. Earlier cases may import modules that later cases + # depend on. Do NOT reorder without understanding dependencies. + cases = ( + # no match != not an import + ("import nope", ([], None), set()), + ("improt nope", None, set()), + # names sorting + ("import col", (["collections", "colorsys"], None), set()), + # module auto-import + ("import fo", (["foo"], None), set()), + ("from foo import ", ([], (_prompt, None)), {"foo"}), + ("from foo import ", (["bar"], None), set()), # now imported + ("from foo import ba", (["bar"], None), set()), + # error during import + ("from boom import ", ([], (_prompt, _error)), set()), + ("from boom import ", ([], None), set()), # do not retry + # packages + ("from collections import a", (["abc"], None), set()), + ("from pack import ", (["bar"], (_prompt, None)), {"pack"}), + ("from pack import ", (["bar", "foo"], None), set()), + ("from pack.bar import ", ([], (_prompt, None)), {"pack.bar"}), + ("from pack.bar import ", ([], None), set()), + # stdlib = auto-imported + ("from graphlib import T", (["TopologicalSorter"], None), {"graphlib"}), + ("from string.templatelib import c", (["convert"], None), {"string.templatelib"}), + ) + completer = ModuleCompleter() + for i, (code, expected, expected_imports) in enumerate(cases): + with self.subTest(code=code, i=i): + _imported = set(sys.modules.keys()) + result = completer.get_completions(code) + self.assertEqual(result is None, expected is None) + if result: + compl, act = result + self.assertEqual(compl, expected[0]) + self.assertEqual(act is None, expected[1] is None) + if act: + msg, func = act + self.assertEqual(msg, expected[1][0]) + act_result = func() + self.assertEqual(act_result, expected[1][1]) + + new_imports = sys.modules.keys() - _imported + self.assertSetEqual(new_imports, expected_imports) + + +# Audit hook used to check for stdlib modules import side-effects +# Defined globally to avoid adding one hook per test run (refleak) +_audit_events: set[str] | None = None + + +def _hook(name: str, _args: tuple): + if _audit_events is not None: # No-op when not activated + _audit_events.add(name) +sys.addaudithook(_hook) + + +@contextlib.contextmanager +def _capture_audit_events(): + global _audit_events + _audit_events = set() + try: + yield _audit_events + finally: + _audit_events = None + + +class TestModuleCompleterAutomaticImports(TestCase): + def test_no_side_effects(self): + from test.test___all__ import AllTest # TODO: extract to a helper? + + completer = ModuleCompleter() + for _, modname in AllTest().walk_modules(completer._stdlib_path, ""): + with self.subTest(modname=modname): + with (captured_stdout() as out, + captured_stderr() as err, + _capture_audit_events() as audit_events, + (patch("tkinter._tkinter.create") if tkinter + else contextlib.nullcontext()) as tk_mock, + warnings.catch_warnings(action="ignore")): + completer._maybe_import_module(modname) + # Test no module is imported that + # 1. prints any text + self.assertEqual(out.getvalue(), "") + self.assertEqual(err.getvalue(), "") + # 2. spawn any subprocess (eg. webbrowser.open) + self.assertNotIn("subprocess.Popen", audit_events) + # 3. launch a Tk window + if tk_mock is not None: + tk_mock.assert_not_called() + class TestHardcodedSubmodules(TestCase): + @patch.dict(sys.modules) def test_hardcoded_stdlib_submodules_are_importable(self): for parent_path, submodules in HARDCODED_SUBMODULES.items(): for module_name in submodules: diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst new file mode 100644 index 00000000000..aadf57622a4 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst @@ -0,0 +1,2 @@ +Add support for module attributes in the :term:`REPL` auto-completion of +imports. From bce96a181350f348560fe0623361f39a6d5c6361 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Sun, 5 Apr 2026 20:23:43 +0100 Subject: [PATCH 422/775] gh-145098: Use `macos-15-intel` instead of unstable `macos-26-intel` in `{jit,tail-call}.yml` (#148126) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- .github/actionlint.yaml | 5 ----- .github/workflows/add-issue-header.yml | 1 + .github/workflows/build.yml | 3 +-- .github/workflows/jit.yml | 7 +++---- .github/workflows/lint.yml | 3 +-- .github/workflows/mypy.yml | 3 +-- .github/workflows/new-bugs-announce-notifier.yml | 5 +++-- .github/workflows/require-pr-label.yml | 2 ++ .github/workflows/stale.yml | 2 ++ .github/workflows/tail-call.yml | 7 +++---- .github/workflows/verify-ensurepip-wheels.yml | 3 +-- .github/workflows/verify-expat.yml | 3 +-- 12 files changed, 19 insertions(+), 25 deletions(-) diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 3004466b80e..eacfff24889 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -1,8 +1,3 @@ -self-hosted-runner: - # Pending release of actionlint > 1.7.11 for macos-26-intel support - # https://github.com/rhysd/actionlint/pull/629 - labels: ["macos-26-intel"] - config-variables: null paths: diff --git a/.github/workflows/add-issue-header.yml b/.github/workflows/add-issue-header.yml index 8a8571eedd1..00b7ae50cb9 100644 --- a/.github/workflows/add-issue-header.yml +++ b/.github/workflows/add-issue-header.yml @@ -12,6 +12,7 @@ on: # Only ever run once - opened +permissions: {} jobs: add-header: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a80262e3c02..c34f8f699d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,8 +11,7 @@ on: - 'main' - '3.*' -permissions: - contents: read +permissions: {} concurrency: # https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 483ace25554..81d75ef1820 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -15,8 +15,7 @@ on: paths: *paths workflow_dispatch: -permissions: - contents: read +permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -99,9 +98,9 @@ jobs: - false include: - target: x86_64-apple-darwin/clang - runner: macos-26-intel + runner: macos-15-intel - target: aarch64-apple-darwin/clang - runner: macos-26 + runner: macos-15 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e9a4eb2b080..fb2b94b7362 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,8 +2,7 @@ name: Lint on: [push, pull_request, workflow_dispatch] -permissions: - contents: read +permissions: {} env: FORCE_COLOR: 1 diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index e5a5b3939e5..583dc1808df 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -33,8 +33,7 @@ on: - "Tools/requirements-dev.txt" workflow_dispatch: -permissions: - contents: read +permissions: {} env: PIP_DISABLE_PIP_VERSION_CHECK: 1 diff --git a/.github/workflows/new-bugs-announce-notifier.yml b/.github/workflows/new-bugs-announce-notifier.yml index 1f28b9befb4..be375a970a4 100644 --- a/.github/workflows/new-bugs-announce-notifier.yml +++ b/.github/workflows/new-bugs-announce-notifier.yml @@ -5,12 +5,13 @@ on: types: - opened -permissions: - issues: read +permissions: {} jobs: notify-new-bugs-announce: runs-on: ubuntu-latest + permissions: + issues: read timeout-minutes: 10 steps: - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 diff --git a/.github/workflows/require-pr-label.yml b/.github/workflows/require-pr-label.yml index 94cb219aeee..262299fc30f 100644 --- a/.github/workflows/require-pr-label.yml +++ b/.github/workflows/require-pr-label.yml @@ -4,6 +4,8 @@ on: pull_request: types: [opened, reopened, labeled, unlabeled, synchronize] +permissions: {} + jobs: label-dnm: name: DO-NOT-MERGE diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 37220783f9c..2c73d10350f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -4,6 +4,8 @@ on: schedule: - cron: "0 */6 * * *" +permissions: {} + jobs: stale: if: github.repository_owner == 'python' diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index a86a3135246..35c62acb28b 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -11,8 +11,7 @@ on: paths: *paths workflow_dispatch: -permissions: - contents: read +permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -32,9 +31,9 @@ jobs: matrix: include: - target: x86_64-apple-darwin/clang - runner: macos-26-intel + runner: macos-15-intel - target: aarch64-apple-darwin/clang - runner: macos-26 + runner: macos-15 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/verify-ensurepip-wheels.yml b/.github/workflows/verify-ensurepip-wheels.yml index cb40f6abc0b..4ac25bc909b 100644 --- a/.github/workflows/verify-ensurepip-wheels.yml +++ b/.github/workflows/verify-ensurepip-wheels.yml @@ -13,8 +13,7 @@ on: - '.github/workflows/verify-ensurepip-wheels.yml' - 'Tools/build/verify_ensurepip_wheels.py' -permissions: - contents: read +permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/verify-expat.yml b/.github/workflows/verify-expat.yml index 472a11db2da..e193dfa4603 100644 --- a/.github/workflows/verify-expat.yml +++ b/.github/workflows/verify-expat.yml @@ -11,8 +11,7 @@ on: - 'Modules/expat/**' - '.github/workflows/verify-expat.yml' -permissions: - contents: read +permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} From fbfc6ccb0abf362a0ecdc02cd0aa2d16c1a4ce44 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Mon, 6 Apr 2026 00:23:07 +0100 Subject: [PATCH 423/775] gh-148144: Initialize visited on copied interpreter frames (#148143) _PyFrame_Copy() copied interpreter frames into generator and frame-object storage without initializing the visited byte. Incremental GC later reads frame->visited in mark_stacks() on non-start passes, so copied frames could expose an uninitialized value once they became live on a thread stack again. Reset visited when copying a frame so copied frames start with defined GC bookkeeping state. Preserve lltrace in Py_DEBUG builds. --- Include/internal/pycore_interpframe.h | 5 +++++ .../2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst diff --git a/Include/internal/pycore_interpframe.h b/Include/internal/pycore_interpframe.h index 8db1aebdc11..d744dd12cd0 100644 --- a/Include/internal/pycore_interpframe.h +++ b/Include/internal/pycore_interpframe.h @@ -149,6 +149,11 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame * int stacktop = (int)(src->stackpointer - src->localsplus); assert(stacktop >= 0); dest->stackpointer = dest->localsplus + stacktop; + // visited is GC bookkeeping for the current stack walk, not frame state. + dest->visited = 0; +#ifdef Py_DEBUG + dest->lltrace = src->lltrace; +#endif for (int i = 0; i < stacktop; i++) { dest->localsplus[i] = PyStackRef_MakeHeapSafe(src->localsplus[i]); } diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst new file mode 100644 index 00000000000..beda992a95b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst @@ -0,0 +1,3 @@ +Initialize ``_PyInterpreterFrame.visited`` when copying interpreter frames so +incremental GC does not read an uninitialized byte from generator and +frame-object copies. From a95ee3a21d97afdbe6bd2ce4cd8343a36cd13b02 Mon Sep 17 00:00:00 2001 From: Malcolm Smith Date: Mon, 6 Apr 2026 06:48:00 +0100 Subject: [PATCH 424/775] gh-144418: Increase Android testbed emulator RAM to 4 GB (#148054) Pre-create the Android emulator image so that the the configuration can be modified to use 4GB of RAM. --- Android/README.md | 8 - Android/testbed/app/build.gradle.kts | 147 +++++++++++++++++- ...-04-03-21-37-18.gh-issue-144418.PusC0S.rst | 1 + 3 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst diff --git a/Android/README.md b/Android/README.md index 9f71aeb934f..0004f26e72b 100644 --- a/Android/README.md +++ b/Android/README.md @@ -103,14 +103,6 @@ ## Testing Actions, the test script will do this automatically using the commands shown [here](https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/). -The test suite can usually be run on a device with 2 GB of RAM, but this is -borderline, so you may need to increase it to 4 GB. As of Android -Studio Koala, 2 GB is the default for all emulators, although the user interface -may indicate otherwise. Locate the emulator's directory under `~/.android/avd`, -and find `hw.ramSize` in both config.ini and hardware-qemu.ini. Either set these -manually to the same value, or use the Android Studio Device Manager, which will -update both files. - You can run the test suite either: * Within the CPython repository, after doing a build as described above. On diff --git a/Android/testbed/app/build.gradle.kts b/Android/testbed/app/build.gradle.kts index 7529fdb8f78..b58edc04a92 100644 --- a/Android/testbed/app/build.gradle.kts +++ b/Android/testbed/app/build.gradle.kts @@ -20,6 +20,14 @@ val KNOWN_ABIS = mapOf( "x86_64-linux-android" to "x86_64", ) +val osArch = System.getProperty("os.arch") +val NATIVE_ABI = mapOf( + "aarch64" to "arm64-v8a", + "amd64" to "x86_64", + "arm64" to "arm64-v8a", + "x86_64" to "x86_64", +)[osArch] ?: throw GradleException("Unknown os.arch '$osArch'") + // Discover prefixes. val prefixes = ArrayList() if (inSourceTree) { @@ -151,6 +159,9 @@ android { testOptions { managedDevices { localDevices { + // systemImageSource should use what its documentation calls an + // "explicit source", i.e. the sdkmanager package name format, because + // that will be required in CreateEmulatorTask below. create("minVersion") { device = "Small Phone" @@ -159,13 +170,13 @@ android { // ATD devices are smaller and faster, but have a minimum // API level of 30. - systemImageSource = if (apiLevel >= 30) "aosp-atd" else "aosp" + systemImageSource = if (apiLevel >= 30) "aosp_atd" else "default" } create("maxVersion") { device = "Small Phone" apiLevel = defaultConfig.targetSdk!! - systemImageSource = "aosp-atd" + systemImageSource = "aosp_atd" } } @@ -191,6 +202,138 @@ dependencies { } +afterEvaluate { + // Every new emulator has a maximum of 2 GB RAM, regardless of its hardware profile + // (https://cs.android.com/android-studio/platform/tools/base/+/refs/tags/studio-2025.3.2:sdklib/src/main/java/com/android/sdklib/internal/avd/EmulatedProperties.java;l=68). + // This is barely enough to test Python, and not enough to test Pandas + // (https://github.com/python/cpython/pull/137186#issuecomment-3136301023, + // https://github.com/pandas-dev/pandas/pull/63405#issuecomment-3667846159). + // So we'll increase it by editing the emulator configuration files. + // + // If the emulator doesn't exist yet, we want to edit it after it's created, but + // before it starts for the first time. Otherwise it'll need to be cold-booted + // again, which would slow down the first run, which is likely the only run in CI + // environments. But the Setup task both creates and starts the emulator if it + // doesn't already exist. So we create it ourselves before the Setup task runs. + for (device in android.testOptions.managedDevices.localDevices) { + val createTask = tasks.register("${device.name}Create") { + this.device = device.device + apiLevel = device.apiLevel + systemImageSource = device.systemImageSource + abi = NATIVE_ABI + } + tasks.named("${device.name}Setup") { + dependsOn(createTask) + } + } +} + +abstract class CreateEmulatorTask : DefaultTask() { + @get:Input abstract val device: Property + @get:Input abstract val apiLevel: Property + @get:Input abstract val systemImageSource: Property + @get:Input abstract val abi: Property + @get:Inject abstract val execOps: ExecOperations + + private val avdName by lazy { + listOf( + "dev${apiLevel.get()}", + systemImageSource.get(), + abi.get(), + device.get().replace(' ', '_'), + ).joinToString("_") + } + + private val avdDir by lazy { + // XDG_CONFIG_HOME is respected by both avdmanager and Gradle. + val userHome = System.getenv("ANDROID_USER_HOME") ?: ( + (System.getenv("XDG_CONFIG_HOME") ?: System.getProperty("user.home")!!) + + "/.android" + ) + File("$userHome/avd/gradle-managed", "$avdName.avd") + } + + @TaskAction + fun run() { + if (!avdDir.exists()) { + createAvd() + } + updateAvd() + } + + fun createAvd() { + val systemImage = listOf( + "system-images", + "android-${apiLevel.get()}", + systemImageSource.get(), + abi.get(), + ).joinToString(";") + + runCmdlineTool("sdkmanager", systemImage) + runCmdlineTool( + "avdmanager", "create", "avd", + "--name", avdName, + "--path", avdDir, + "--device", device.get().lowercase().replace(" ", "_"), + "--package", systemImage, + ) + + val iniName = "$avdName.ini" + if (!File(avdDir.parentFile.parentFile, iniName).renameTo( + File(avdDir.parentFile, iniName) + )) { + throw GradleException("Failed to rename $iniName") + } + } + + fun updateAvd() { + for (filename in listOf( + "config.ini", // Created by avdmanager; always exists + "hardware-qemu.ini", // Created on first run; might not exist + )) { + val iniFile = File(avdDir, filename) + if (!iniFile.exists()) { + if (filename == "config.ini") { + throw GradleException("$iniFile does not exist") + } + continue + } + + val iniText = iniFile.readText() + val pattern = Regex( + """^\s*hw.ramSize\s*=\s*(.+?)\s*$""", RegexOption.MULTILINE + ) + val matches = pattern.findAll(iniText).toList() + if (matches.size != 1) { + throw GradleException( + "Found ${matches.size} instances of $pattern in $iniFile; expected 1" + ) + } + + val expectedRam = "4096" + if (matches[0].groupValues[1] != expectedRam) { + iniFile.writeText( + iniText.replace(pattern, "hw.ramSize = $expectedRam") + ) + } + } + } + + fun runCmdlineTool(tool: String, vararg args: Any) { + val androidHome = System.getenv("ANDROID_HOME")!! + val exeSuffix = + if (System.getProperty("os.name").lowercase().startsWith("win")) ".exe" + else "" + val command = + listOf("$androidHome/cmdline-tools/latest/bin/$tool$exeSuffix", *args) + println(command.joinToString(" ")) + execOps.exec { + commandLine(command) + } + } +} + + // Create some custom tasks to copy Python and its standard library from // elsewhere in the repository. androidComponents.onVariants { variant -> diff --git a/Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst b/Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst new file mode 100644 index 00000000000..dd72996d51a --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst @@ -0,0 +1 @@ +The Android testbed's emulator RAM has been increased from 2 GB to 4 GB. From d0e204fb1da2ba7956ec2dff6501c3374eee1d43 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 Apr 2026 13:47:27 +0300 Subject: [PATCH 425/775] gh-148153: Do not use assert for parameter validation in base64 (GH-148154) base64.b32encode() now always raises ValueError instead of AssertionError for the value of map01 with invalid length. --- Doc/library/base64.rst | 3 --- Lib/base64.py | 1 - Lib/test/test_base64.py | 5 +++++ .../Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 425dff8f2a9..6e6e5d603e3 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -69,9 +69,6 @@ POST request. after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. - May assert or raise a :exc:`ValueError` if the length of *altchars* is not 2. Raises a - :exc:`TypeError` if *altchars* is not a :term:`bytes-like object`. - .. versionchanged:: 3.15 Added the *padded* and *wrapcol* parameters. diff --git a/Lib/base64.py b/Lib/base64.py index a94bec4d031..7f39c68070b 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -237,7 +237,6 @@ def b32decode(s, casefold=False, map01=None, *, padded=True, ignorechars=b''): # either L (el) or I (eye). if map01 is not None: map01 = _bytes_from_decode_data(map01) - assert len(map01) == 1, repr(map01) s = s.translate(bytes.maketrans(b'01', b'O' + map01)) if casefold: s = s.upper() diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index 1a4dd56a553..868abcfee24 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -607,6 +607,11 @@ def test_b32decode_map01(self): self.assertRaises(binascii.Error, base64.b32decode, b'M1O23456') self.assertRaises(binascii.Error, base64.b32decode, b'ML023456') self.assertRaises(binascii.Error, base64.b32decode, b'MI023456') + self.assertRaises(ValueError, base64.b32decode, b'', map01=b'') + self.assertRaises(ValueError, base64.b32decode, b'', map01=b'LI') + self.assertRaises(TypeError, base64.b32decode, b'', map01=0) + eq(base64.b32decode(b'MLO23456', map01=None), res_L) + self.assertRaises(binascii.Error, base64.b32decode, b'M1023456', map01=None) data = b'M1023456' data_str = data.decode('ascii') diff --git a/Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst b/Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst new file mode 100644 index 00000000000..7fd30562739 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst @@ -0,0 +1,2 @@ +:func:`base64.b32encode` now always raises :exc:`ValueError` instead of +:exc:`AssertionError` for the value of *map01* with invalid length. From acf5229081bba5477480403b0d7188518ff877da Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 6 Apr 2026 14:21:59 +0300 Subject: [PATCH 426/775] Docs: Update "Installing Python modules" (#146249) --- Doc/installing/index.rst | 90 ++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 59 deletions(-) diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index 412005f3ec8..c372d9f4741 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -1,14 +1,14 @@ -.. highlight:: none +.. highlight:: shell .. _installing-index: ************************* -Installing Python Modules +Installing Python modules ************************* As a popular open source development project, Python has an active supporting community of contributors and users that also make their software -available for other Python developers to use under open source license terms. +available for other Python developers to use under open-source license terms. This allows Python users to share and collaborate effectively, benefiting from the solutions others have already created to common (and sometimes @@ -32,34 +32,24 @@ creating and sharing your own Python projects, refer to the Key terms ========= -* ``pip`` is the preferred installer program. Starting with Python 3.4, it +* :program:`pip` is the preferred installer program. It is included by default with the Python binary installers. * A *virtual environment* is a semi-isolated Python environment that allows packages to be installed for use by a particular application, rather than being installed system wide. -* ``venv`` is the standard tool for creating virtual environments, and has - been part of Python since Python 3.3. Starting with Python 3.4, it - defaults to installing ``pip`` into all created virtual environments. -* ``virtualenv`` is a third party alternative (and predecessor) to - ``venv``. It allows virtual environments to be used on versions of - Python prior to 3.4, which either don't provide ``venv`` at all, or - aren't able to automatically install ``pip`` into created environments. -* The `Python Package Index `__ is a public +* ``venv`` is the standard tool for creating virtual environments. + It defaults to installing :program:`pip` into all created virtual environments. +* ``virtualenv`` is a third-party alternative (and predecessor) to + ``venv``. +* The `Python Package Index (PyPI) `__ is a public repository of open source licensed packages made available for use by other Python users. -* the `Python Packaging Authority +* The `Python Packaging Authority `__ is the group of developers and documentation authors responsible for the maintenance and evolution of the standard packaging tools and the associated metadata and file format standards. They maintain a variety of tools, documentation, and issue trackers on `GitHub `__. -* ``distutils`` is the original build and distribution system first added to - the Python standard library in 1998. While direct use of ``distutils`` is - being phased out, it still laid the foundation for the current packaging - and distribution infrastructure, and it not only remains part of the - standard library, but its name lives on in other ways (such as the name - of the mailing list used to coordinate Python packaging standards - development). .. versionchanged:: 3.5 The use of ``venv`` is now recommended for creating virtual environments. @@ -77,7 +67,7 @@ The standard packaging tools are all designed to be used from the command line. The following command will install the latest version of a module and its -dependencies from the Python Package Index:: +dependencies from PyPI:: python -m pip install SomePackage @@ -104,7 +94,7 @@ explicitly:: python -m pip install --upgrade SomePackage -More information and resources regarding ``pip`` and its capabilities can be +More information and resources regarding :program:`pip` and its capabilities can be found in the `Python Packaging User Guide `__. Creation of virtual environments is done through the :mod:`venv` module. @@ -122,19 +112,6 @@ How do I ...? These are quick answers or links for some common tasks. -... install ``pip`` in versions of Python prior to Python 3.4? --------------------------------------------------------------- - -Python only started bundling ``pip`` with Python 3.4. For earlier versions, -``pip`` needs to be "bootstrapped" as described in the Python Packaging -User Guide. - -.. seealso:: - - `Python Packaging User Guide: Requirements for Installing Packages - `__ - - .. installing-per-user-installation: ... install packages just for the current user? @@ -148,10 +125,10 @@ package just for the current user, rather than for all users of the system. --------------------------------------- A number of scientific Python packages have complex binary dependencies, and -aren't currently easy to install using ``pip`` directly. At this point in -time, it will often be easier for users to install these packages by +aren't currently easy to install using :program:`pip` directly. +It will often be easier for users to install these packages by `other means `__ -rather than attempting to install them with ``pip``. +rather than attempting to install them with :program:`pip`. .. seealso:: @@ -164,22 +141,18 @@ rather than attempting to install them with ``pip``. On Linux, macOS, and other POSIX systems, use the versioned Python commands in combination with the ``-m`` switch to run the appropriate copy of -``pip``:: +:program:`pip`:: - python2 -m pip install SomePackage # default Python 2 - python2.7 -m pip install SomePackage # specifically Python 2.7 - python3 -m pip install SomePackage # default Python 3 - python3.4 -m pip install SomePackage # specifically Python 3.4 + python3 -m pip install SomePackage # default Python 3 + python3.14 -m pip install SomePackage # specifically Python 3.14 -Appropriately versioned ``pip`` commands may also be available. +Appropriately versioned :program:`pip` commands may also be available. -On Windows, use the ``py`` Python launcher in combination with the ``-m`` +On Windows, use the :program:`py` Python launcher in combination with the ``-m`` switch:: - py -2 -m pip install SomePackage # default Python 2 - py -2.7 -m pip install SomePackage # specifically Python 2.7 - py -3 -m pip install SomePackage # default Python 3 - py -3.4 -m pip install SomePackage # specifically Python 3.4 + py -3 -m pip install SomePackage # default Python 3 + py -3.14 -m pip install SomePackage # specifically Python 3.14 .. other questions: @@ -199,39 +172,38 @@ On Linux systems, a Python installation will typically be included as part of the distribution. Installing into this Python installation requires root access to the system, and may interfere with the operation of the system package manager and other components of the system if a component -is unexpectedly upgraded using ``pip``. +is unexpectedly upgraded using :program:`pip`. On such systems, it is often better to use a virtual environment or a -per-user installation when installing packages with ``pip``. +per-user installation when installing packages with :program:`pip`. Pip not installed ----------------- -It is possible that ``pip`` does not get installed by default. One potential fix is:: +It is possible that :program:`pip` does not get installed by default. One potential fix is:: python -m ensurepip --default-pip -There are also additional resources for `installing pip. -`__ +There are also additional resources for `installing pip +`__. Installing binary extensions ---------------------------- -Python has typically relied heavily on source based distribution, with end +Python once relied heavily on source-based distribution, with end users being expected to compile extension modules from source as part of the installation process. -With the introduction of support for the binary ``wheel`` format, and the -ability to publish wheels for at least Windows and macOS through the -Python Package Index, this problem is expected to diminish over time, +With the introduction of the binary wheel format, and the +ability to publish wheels through PyPI, this problem is diminishing, as users are more regularly able to install pre-built extensions rather than needing to build them themselves. Some of the solutions for installing `scientific software `__ -that are not yet available as pre-built ``wheel`` files may also help with +that are not yet available as pre-built wheel files may also help with obtaining other binary extensions without needing to build them locally. .. seealso:: From 1795fccfbc7ccb89ead5c529b2f55f54622d1314 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Mon, 6 Apr 2026 12:56:36 +0100 Subject: [PATCH 427/775] gh-148157: Check for `_PyPegen_add_type_comment_to_arg` fail in `_PyPegen_name_default_pair` (#148158) --- Lib/test/test_type_comments.py | 3 +++ .../2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst | 2 ++ Parser/action_helpers.c | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst diff --git a/Lib/test/test_type_comments.py b/Lib/test/test_type_comments.py index dd2e6784165..d827ac27108 100644 --- a/Lib/test/test_type_comments.py +++ b/Lib/test/test_type_comments.py @@ -398,6 +398,9 @@ def test_non_utf8_type_comment_with_ignore_cookie(self): with self.assertRaises(UnicodeDecodeError): _testcapi.Py_CompileStringExFlags( b"a=1 # type: \x80", "", 256, flags) + with self.assertRaises(UnicodeDecodeError): + _testcapi.Py_CompileStringExFlags( + b"def a(f=8, #type: \x80\n\x80", "", 256, flags) def test_func_type_input(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst new file mode 100644 index 00000000000..6565291eb99 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst @@ -0,0 +1,2 @@ +Fix an unlikely crash when parsing an invalid type comments for function +parameters. Found by OSS Fuzz in :oss-fuzz:`492782951`. diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 1f5b6220ba1..5e52bb83871 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -435,6 +435,9 @@ _PyPegen_name_default_pair(Parser *p, arg_ty arg, expr_ty value, Token *tc) return NULL; } a->arg = _PyPegen_add_type_comment_to_arg(p, arg, tc); + if (!a->arg) { + return NULL; + } a->value = value; return a; } From 69f51625e6314883456b336b9e3471a6221d2787 Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Mon, 6 Apr 2026 20:11:30 +0800 Subject: [PATCH 428/775] gh-148119: Refactor `get_type_attr_as_size` to improve error handling in `structseq.c` (#148120) --- Objects/structseq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Objects/structseq.c b/Objects/structseq.c index 8fa9cbba3bc..9130fe6a133 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -28,7 +28,11 @@ static Py_ssize_t get_type_attr_as_size(PyTypeObject *tp, PyObject *name) { PyObject *v = PyDict_GetItemWithError(_PyType_GetDict(tp), name); - if (v == NULL && !PyErr_Occurred()) { + + if (v == NULL) { + if (PyErr_Occurred()) { + return -1; + } PyErr_Format(PyExc_TypeError, "Missed attribute '%U' of type %s", name, tp->tp_name); From 476fadc9aec9beb04dd95ee1894594b5dfa6a5cf Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Mon, 6 Apr 2026 13:47:44 +0100 Subject: [PATCH 429/775] Add Stan to docs config reviewers (#148164) --- .github/CODEOWNERS | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c5348d606b8..af904a567cf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -100,12 +100,12 @@ Lib/test/test_build_details.py @FFY00 InternalDocs/ @AA-Turner # Tools, Configuration, etc -Doc/Makefile @AA-Turner @hugovk -Doc/_static/ @AA-Turner @hugovk -Doc/conf.py @AA-Turner @hugovk -Doc/make.bat @AA-Turner @hugovk -Doc/requirements.txt @AA-Turner @hugovk -Doc/tools/ @AA-Turner @hugovk +Doc/Makefile @AA-Turner @hugovk @StanFromIreland +Doc/_static/ @AA-Turner @hugovk @StanFromIreland +Doc/conf.py @AA-Turner @hugovk @StanFromIreland +Doc/make.bat @AA-Turner @hugovk @StanFromIreland +Doc/requirements.txt @AA-Turner @hugovk @StanFromIreland +Doc/tools/ @AA-Turner @hugovk @StanFromIreland # PR Previews .readthedocs.yml @AA-Turner From efda60e2ece11beda204f89de8cf8ecd1e66fde5 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 6 Apr 2026 14:52:42 +0200 Subject: [PATCH 430/775] gh-100239: Propagate type info through _BINARY_OP_EXTEND in tier 2 (GH-148146) --- Include/internal/pycore_code.h | 7 +++++ Lib/test/test_capi/test_opt.py | 23 +++++++++++++++ ...04-06-00-00-00.gh-issue-100239.binopxt.rst | 3 ++ Python/optimizer_bytecodes.c | 12 ++++++-- Python/optimizer_cases.c.h | 12 ++++++-- Python/specialize.c | 28 +++++++++---------- 6 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 376e68a4c87..fe8d0a54f2a 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -496,6 +496,13 @@ typedef struct { int oparg; binaryopguardfunc guard; binaryopactionfunc action; + /* Static type of the result, or NULL if unknown. Used by the tier 2 + optimizer to propagate type information through _BINARY_OP_EXTEND. */ + PyTypeObject *result_type; + /* Nonzero iff `action` always returns a freshly allocated object (not + aliased to either operand). Used by the tier 2 optimizer to enable + inplace follow-up ops. */ + int result_unique; } _PyBinaryOpSpecializationDescr; /* Comparison bit masks. */ diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 56f90194b48..b31c9f68d01 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3813,6 +3813,29 @@ def f(n): self.assertIn("_UNPACK_SEQUENCE_TWO_TUPLE", uops) self.assertNotIn("_GUARD_TOS_TUPLE", uops) + def test_binary_op_extend_float_result_enables_inplace_multiply(self): + # (2 + x) * y with x, y floats: `2 + x` goes through _BINARY_OP_EXTEND + # (int + float). The result_type/result_unique info should let the + # subsequent float multiply use the inplace variant. + def testfunc(n): + x = 3.5 + y = 2.0 + res = 0.0 + for _ in range(n): + res = (2 + x) * y + return res + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, 11.0) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_BINARY_OP_EXTEND", uops) + self.assertIn("_BINARY_OP_MULTIPLY_FLOAT_INPLACE", uops) + self.assertNotIn("_BINARY_OP_MULTIPLY_FLOAT", uops) + # NOS guard on the multiply is eliminated because _BINARY_OP_EXTEND + # propagates PyFloat_Type. + self.assertNotIn("_GUARD_NOS_FLOAT", uops) + def test_unary_invert_long_type(self): def testfunc(n): for _ in range(n): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst new file mode 100644 index 00000000000..9eccef3ef9d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst @@ -0,0 +1,3 @@ +Propagate result type and uniqueness information through +``_BINARY_OP_EXTEND`` in the tier 2 optimizer, enabling elimination of +downstream type guards and selection of inplace float operations. diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index b8148ef57ed..58b50707e55 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -410,8 +410,16 @@ dummy_func(void) { } op(_BINARY_OP_EXTEND, (descr/4, left, right -- res, l, r)) { - (void)descr; - res = sym_new_not_null(ctx); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->result_type != NULL) { + res = sym_new_type(ctx, d->result_type); + if (d->result_unique) { + res = PyJitRef_MakeUnique(res); + } + } + else { + res = sym_new_not_null(ctx); + } l = left; r = right; } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index a15b5ae1d13..89188730111 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1168,8 +1168,16 @@ right = stack_pointer[-1]; left = stack_pointer[-2]; PyObject *descr = (PyObject *)this_instr->operand0; - (void)descr; - res = sym_new_not_null(ctx); + _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr *)descr; + if (d != NULL && d->result_type != NULL) { + res = sym_new_type(ctx, d->result_type); + if (d->result_unique) { + res = PyJitRef_MakeUnique(res); + } + } + else { + res = sym_new_not_null(ctx); + } l = left; r = right; CHECK_STACK_BOUNDS(1); diff --git a/Python/specialize.c b/Python/specialize.c index 09ec25767a4..0fe225dcbb6 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -2195,24 +2195,24 @@ LONG_FLOAT_ACTION(compactlong_float_true_div, /) static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = { /* long-long arithmetic */ - {NB_OR, compactlongs_guard, compactlongs_or}, - {NB_AND, compactlongs_guard, compactlongs_and}, - {NB_XOR, compactlongs_guard, compactlongs_xor}, - {NB_INPLACE_OR, compactlongs_guard, compactlongs_or}, - {NB_INPLACE_AND, compactlongs_guard, compactlongs_and}, - {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor}, + {NB_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1}, + {NB_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1}, + {NB_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1}, + {NB_INPLACE_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1}, + {NB_INPLACE_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1}, + {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1}, /* float-long arithemetic */ - {NB_ADD, float_compactlong_guard, float_compactlong_add}, - {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract}, - {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div}, - {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply}, + {NB_ADD, float_compactlong_guard, float_compactlong_add, &PyFloat_Type, 1}, + {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract, &PyFloat_Type, 1}, + {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div, &PyFloat_Type, 1}, + {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply, &PyFloat_Type, 1}, /* float-float arithmetic */ - {NB_ADD, compactlong_float_guard, compactlong_float_add}, - {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract}, - {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div}, - {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply}, + {NB_ADD, compactlong_float_guard, compactlong_float_add, &PyFloat_Type, 1}, + {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract, &PyFloat_Type, 1}, + {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div, &PyFloat_Type, 1}, + {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply, &PyFloat_Type, 1}, }; static int From 36f15ba5cd15607fb4e4908ddbfb462c44626d6b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:07:15 +0300 Subject: [PATCH 431/775] gh-140279: Stale workflow needs 'actions: write' to update its own cache (#148165) --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 2c73d10350f..a862fde5e14 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,6 +11,7 @@ jobs: if: github.repository_owner == 'python' runs-on: ubuntu-latest permissions: + actions: write pull-requests: write timeout-minutes: 10 From f8293faf37971fd0d4d30c0c83df2ac654e610a1 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Mon, 6 Apr 2026 15:57:25 +0100 Subject: [PATCH 432/775] gh-130472: Remove readline-only hacks from PyREPL completions (#148161) PyREPL was still carrying over two readline-specific tricks from the fancy completer: a synthetic CSI prefix to influence sorting and a fake blank completion entry to suppress readline's prefix insertion. Those workarounds are not appropriate in PyREPL because the reader already owns completion ordering and menu rendering, so the fake entries leaked into the UI as real terminal attributes and empty menu cells. Sort completion candidates in ReadlineAlikeReader by their visible text with stripcolor(), and let the fancy completer return only real matches. That keeps colored completions stable without emitting bogus escape sequences, removes the empty completion slot, and adds regression tests for both the low-level completer output and the reader integration. --- Lib/_pyrepl/fancycompleter.py | 21 ++++--------- Lib/_pyrepl/readline.py | 8 ++--- Lib/test/test_pyrepl/test_fancycompleter.py | 34 ++++++++------------- Lib/test/test_pyrepl/test_pyrepl.py | 22 +++++++++++++ 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/Lib/_pyrepl/fancycompleter.py b/Lib/_pyrepl/fancycompleter.py index 5b5b7ae5f2b..7a639afd74e 100644 --- a/Lib/_pyrepl/fancycompleter.py +++ b/Lib/_pyrepl/fancycompleter.py @@ -105,9 +105,6 @@ def attr_matches(self, text): names = [f'{expr}.{name}' for name in names] if self.use_colors: return self.colorize_matches(names, values) - - if prefix: - names.append(' ') return names def _attr_matches(self, text): @@ -173,21 +170,15 @@ def _attr_matches(self, text): return expr, attr, names, values def colorize_matches(self, names, values): - matches = [self._color_for_obj(i, name, obj) - for i, (name, obj) - in enumerate(zip(names, values))] - # We add a space at the end to prevent the automatic completion of the - # common prefix, which is the ANSI escape sequence. - matches.append(' ') - return matches + return [ + self._color_for_obj(name, obj) + for name, obj in zip(names, values) + ] - def _color_for_obj(self, i, name, value): + def _color_for_obj(self, name, value): t = type(value) color = self._color_by_type(t) - # Encode the match index into a fake escape sequence that - # stripcolor() can still remove once i reaches four digits. - N = f"\x1b[{i // 100:03d};{i % 100:02d}m" - return f"{N}{color}{name}{ANSIColors.RESET}" + return f"{color}{name}{ANSIColors.RESET}" def _color_by_type(self, t): typename = t.__name__ diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index 687084601e7..8d3be37b4ad 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -37,7 +37,7 @@ from rlcompleter import Completer as RLCompleter from . import commands, historical_reader -from .completing_reader import CompletingReader +from .completing_reader import CompletingReader, stripcolor from .console import Console as ConsoleType from ._module_completer import ModuleCompleter, make_default_module_completer from .fancycompleter import Completer as FancyCompleter @@ -163,9 +163,9 @@ def get_completions(self, stem: str) -> tuple[list[str], CompletionAction | None break result.append(next) state += 1 - # emulate the behavior of the standard readline that sorts - # the completions before displaying them. - result.sort() + # Emulate readline's sorting using the visible text rather than + # the raw ANSI escape sequences used for colorized matches. + result.sort(key=stripcolor) return result, None def get_module_completions(self) -> tuple[list[str], CompletionAction | None] | None: diff --git a/Lib/test/test_pyrepl/test_fancycompleter.py b/Lib/test/test_pyrepl/test_fancycompleter.py index 77c80853a3c..d2646cd3050 100644 --- a/Lib/test/test_pyrepl/test_fancycompleter.py +++ b/Lib/test/test_pyrepl/test_fancycompleter.py @@ -55,7 +55,7 @@ class C(object): self.assertEqual(compl.attr_matches('a.'), ['a.attr', 'a.mro']) self.assertEqual( compl.attr_matches('a._'), - ['a._C__attr__attr', 'a._attr', ' '], + ['a._C__attr__attr', 'a._attr'], ) matches = compl.attr_matches('a.__') self.assertNotIn('__class__', matches) @@ -79,7 +79,7 @@ def test_complete_attribute_colored(self): break else: self.assertFalse(True, matches) - self.assertIn(' ', matches) + self.assertNotIn(' ', matches) def test_preserves_callable_postfix_for_single_attribute_match(self): compl = Completer({'os': os}, use_colors=False) @@ -159,22 +159,17 @@ def test_complete_global_colored(self): self.assertEqual(compl.global_matches('foo'), ['fooba']) matches = compl.global_matches('fooba') - # these are the fake escape sequences which are needed so that - # readline displays the matches in the proper order - N0 = f"\x1b[000;00m" - N1 = f"\x1b[000;01m" int_color = theme.fancycompleter.int - self.assertEqual(set(matches), { - ' ', - f'{N0}{int_color}foobar{ANSIColors.RESET}', - f'{N1}{int_color}foobazzz{ANSIColors.RESET}', - }) + self.assertEqual(matches, [ + f'{int_color}foobar{ANSIColors.RESET}', + f'{int_color}foobazzz{ANSIColors.RESET}', + ]) self.assertEqual(compl.global_matches('foobaz'), ['foobazzz']) self.assertEqual(compl.global_matches('nothing'), []) - def test_large_color_sort_prefix_is_stripped(self): + def test_colorized_match_is_stripped(self): compl = Completer({'a': 42}, use_colors=True) - match = compl._color_for_obj(1000, 'spam', 1) + match = compl._color_for_obj('spam', 1) self.assertEqual(stripcolor(match), 'spam') def test_complete_with_indexer(self): @@ -197,13 +192,11 @@ class A: compl = Completer({'A': A}, use_colors=False) # # In this case, we want to display all attributes which start with - # 'a'. Moreover, we also include a space to prevent readline to - # automatically insert the common prefix (which will the the ANSI escape - # sequence if we use colors). + # 'a'. matches = compl.attr_matches('A.a') self.assertEqual( sorted(matches), - [' ', 'A.aaa', 'A.abc_1', 'A.abc_2', 'A.abc_3'], + ['A.aaa', 'A.abc_1', 'A.abc_2', 'A.abc_3'], ) # # If there is an actual common prefix, we return just it, so that readline @@ -211,13 +204,12 @@ class A: matches = compl.attr_matches('A.ab') self.assertEqual(matches, ['A.abc_']) # - # Finally, at the next tab, we display again all the completions available - # for this common prefix. Again, we insert a spurious space to prevent the - # automatic completion of ANSI sequences. + # Finally, at the next tab, we display again all the completions + # available for this common prefix. matches = compl.attr_matches('A.abc_') self.assertEqual( sorted(matches), - [' ', 'A.abc_1', 'A.abc_2', 'A.abc_3'], + ['A.abc_1', 'A.abc_2', 'A.abc_3'], ) def test_complete_exception(self): diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index c3556823c72..8a3cae966a6 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -36,6 +36,7 @@ code_to_events, ) from _pyrepl.console import Event +from _pyrepl.completing_reader import stripcolor from _pyrepl._module_completer import ( ImportParser, ModuleCompleter, @@ -999,6 +1000,27 @@ class Obj: self.assertNotIn("banana", menu) self.assertNotIn("mro", menu) + def test_get_completions_sorts_colored_matches_by_visible_text(self): + console = FakeConsole(iter(())) + config = ReadlineConfig() + config.readline_completer = FancyCompleter( + { + "foo_str": "value", + "foo_int": 1, + "foo_none": None, + }, + use_colors=True, + ).complete + reader = ReadlineAlikeReader(console=console, config=config) + + matches, action = reader.get_completions("foo_") + + self.assertIsNone(action) + self.assertEqual( + [stripcolor(match) for match in matches], + ["foo_int", "foo_none", "foo_str"], + ) + class TestPyReplReadlineSetup(TestCase): def test_setup_ignores_basic_completer_env_when_env_is_disabled(self): From 3d724dd9149068ec9c335262d81d410a564d3598 Mon Sep 17 00:00:00 2001 From: Junya Fukuda Date: Tue, 7 Apr 2026 00:37:02 +0900 Subject: [PATCH 433/775] gh-148072: Cache pickle.dumps/loads per interpreter in XIData (GH-148125) Store references to pickle.dumps and pickle.loads in _PyXI_state_t so they are looked up only once per interpreter lifetime, avoiding repeated PyImport_ImportModuleAttrString calls on every cross-interpreter data transfer via pickle fallback. Benchmarks show 1.7x-3.3x speedup for InterpreterPoolExecutor when transferring mutable types (list, dict) through XIData. --- Include/internal/pycore_crossinterp.h | 6 ++ ...-04-05-00-00-00.gh-issue-148072.xid9Pe.rst | 4 ++ Python/crossinterp.c | 62 +++++++++++++++++-- 3 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index 81faffac194..bed966681fa 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -265,6 +265,12 @@ typedef struct { // heap types PyObject *PyExc_NotShareableError; } exceptions; + + // Cached references to pickle.dumps/loads (per-interpreter). + struct { + PyObject *dumps; + PyObject *loads; + } pickle; } _PyXI_state_t; #define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst new file mode 100644 index 00000000000..17c6f882f24 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst @@ -0,0 +1,4 @@ +Cache ``pickle.dumps`` and ``pickle.loads`` per interpreter in the XIData +framework, avoiding repeated module lookups on every cross-interpreter data +transfer. This speeds up :class:`~concurrent.futures.InterpreterPoolExecutor` +for mutable types (``list``, ``dict``) by 1.7x--3.3x. diff --git a/Python/crossinterp.c b/Python/crossinterp.c index f92927da475..4cd4b32ef90 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -568,6 +568,48 @@ _PyObject_GetXIData(PyThreadState *tstate, /* pickle C-API */ +/* Per-interpreter cache for pickle.dumps and pickle.loads. + * + * Each interpreter has its own cache in _PyXI_state_t.pickle, preserving + * interpreter isolation. The cache is populated lazily on first use and + * cleared during interpreter finalization in _Py_xi_state_fini(). + * + * Note: the cached references are captured at first use and not invalidated + * on module reload. This matches the caching pattern used elsewhere in + * CPython (e.g. arraymodule.c, _decimal.c). */ + +static PyObject * +_get_pickle_dumps(PyThreadState *tstate) +{ + _PyXI_state_t *state = _PyXI_GET_STATE(tstate->interp); + PyObject *dumps = state->pickle.dumps; + if (dumps != NULL) { + return dumps; + } + dumps = PyImport_ImportModuleAttrString("pickle", "dumps"); + if (dumps == NULL) { + return NULL; + } + state->pickle.dumps = dumps; // owns the reference + return dumps; +} + +static PyObject * +_get_pickle_loads(PyThreadState *tstate) +{ + _PyXI_state_t *state = _PyXI_GET_STATE(tstate->interp); + PyObject *loads = state->pickle.loads; + if (loads != NULL) { + return loads; + } + loads = PyImport_ImportModuleAttrString("pickle", "loads"); + if (loads == NULL) { + return NULL; + } + state->pickle.loads = loads; // owns the reference + return loads; +} + struct _pickle_context { PyThreadState *tstate; }; @@ -575,13 +617,12 @@ struct _pickle_context { static PyObject * _PyPickle_Dumps(struct _pickle_context *ctx, PyObject *obj) { - PyObject *dumps = PyImport_ImportModuleAttrString("pickle", "dumps"); + PyObject *dumps = _get_pickle_dumps(ctx->tstate); if (dumps == NULL) { return NULL; } - PyObject *bytes = PyObject_CallOneArg(dumps, obj); - Py_DECREF(dumps); - return bytes; + // dumps is a borrowed reference from the cache. + return PyObject_CallOneArg(dumps, obj); } @@ -636,7 +677,8 @@ _PyPickle_Loads(struct _unpickle_context *ctx, PyObject *pickled) PyThreadState *tstate = ctx->tstate; PyObject *exc = NULL; - PyObject *loads = PyImport_ImportModuleAttrString("pickle", "loads"); + // loads is a borrowed reference from the per-interpreter cache. + PyObject *loads = _get_pickle_loads(tstate); if (loads == NULL) { return NULL; } @@ -682,7 +724,6 @@ _PyPickle_Loads(struct _unpickle_context *ctx, PyObject *pickled) // It might make sense to chain it (__context__). _PyErr_SetRaisedException(tstate, exc); } - Py_DECREF(loads); return obj; } @@ -3094,6 +3135,10 @@ _Py_xi_state_init(_PyXI_state_t *state, PyInterpreterState *interp) assert(state != NULL); assert(interp == NULL || state == _PyXI_GET_STATE(interp)); + // Initialize pickle function cache (before any fallible ops). + state->pickle.dumps = NULL; + state->pickle.loads = NULL; + xid_lookup_init(&state->data_lookup); // Initialize exceptions. @@ -3116,6 +3161,11 @@ _Py_xi_state_fini(_PyXI_state_t *state, PyInterpreterState *interp) assert(state != NULL); assert(interp == NULL || state == _PyXI_GET_STATE(interp)); + // Clear pickle function cache first: the cached functions may hold + // references to modules cleaned up by later finalization steps. + Py_CLEAR(state->pickle.dumps); + Py_CLEAR(state->pickle.loads); + fini_heap_exctypes(&state->exceptions); if (interp != NULL) { fini_static_exctypes(&state->exceptions, interp); From a0c57a8d17eb0f5c4e620d83a13a47cf4d85e76f Mon Sep 17 00:00:00 2001 From: Fionn <1897918+fionn@users.noreply.github.com> Date: Tue, 7 Apr 2026 00:42:10 +0800 Subject: [PATCH 434/775] gh-137586: Open external osascript program with absolute path (GH-137584) Open web browser with absolute path On macOS, web browsers are opened via popen calling osascript. However, if a user has a colliding osascript executable earlier in their PATH, this may fail or cause unwanted behaviour. Depending on one's environment or level of paranoia, this may be considered a security vulnerability. Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Lib/test/test_webbrowser.py | 2 +- Lib/turtledemo/__main__.py | 2 +- Lib/webbrowser.py | 2 +- .../next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index ea161ea1a43..299dc185fcf 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -351,7 +351,7 @@ def test_default_open(self): url = "https://python.org" self.browser.open(url) self.assertTrue(self.popen_pipe._closed) - self.assertEqual(self.popen_pipe.cmd, "osascript") + self.assertEqual(self.popen_pipe.cmd, "/usr/bin/osascript") script = self.popen_pipe.pipe.getvalue() self.assertEqual(script.strip(), f'open location "{url}"') diff --git a/Lib/turtledemo/__main__.py b/Lib/turtledemo/__main__.py index b49c0beab3c..7c2d753f4c3 100644 --- a/Lib/turtledemo/__main__.py +++ b/Lib/turtledemo/__main__.py @@ -136,7 +136,7 @@ def __init__(self, filename=None): # so that our menu bar appears. subprocess.run( [ - 'osascript', + '/usr/bin/osascript', '-e', 'tell application "System Events"', '-e', 'set frontmost of the first process whose ' 'unix id is {} to true'.format(os.getpid()), diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index deb6e64d174..0e0b5034e5f 100644 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -656,7 +656,7 @@ def open(self, url, new=0, autoraise=True): end ''' - osapipe = os.popen("osascript", "w") + osapipe = os.popen("/usr/bin/osascript", "w") if osapipe is None: return False diff --git a/Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst b/Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst new file mode 100644 index 00000000000..8e42065392a --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst @@ -0,0 +1 @@ +Invoke :program:`osascript` with absolute path in :mod:`webbrowser` and :mod:`!turtledemo`. From ca960b6f38b16a7fdf5453abc6d715cb03467279 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Mon, 6 Apr 2026 22:29:02 +0100 Subject: [PATCH 435/775] gh-148110: Resolve lazy import filter names for relative imports (#148111) --- Doc/c-api/import.rst | 6 +- Doc/library/sys.rst | 4 +- Lib/test/test_lazy_import/__init__.py | 183 ++++++++++++++++++ ...-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst | 2 + Python/clinic/sysmodule.c.h | 4 +- Python/import.c | 2 +- Python/sysmodule.c | 4 +- 7 files changed, 197 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index 367490732b9..e2d363b911a 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -372,8 +372,10 @@ Importing Modules Sets the current lazy imports filter. The *filter* should be a callable that will receive ``(importing_module_name, imported_module_name, [fromlist])`` - when an import can potentially be lazy and that must return ``True`` if - the import should be lazy and ``False`` otherwise. + when an import can potentially be lazy. The ``imported_module_name`` value + is the resolved module name, so ``lazy from .spam import eggs`` passes + ``package.spam``. The callable must return ``True`` if the import should be + lazy and ``False`` otherwise. Return ``0`` on success and ``-1`` with an exception set otherwise. diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index b1461b0cbaf..6946eb6eeaa 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1788,7 +1788,9 @@ always available. Unless explicitly noted otherwise, all variables are read-only Where: * *importing_module* is the name of the module doing the import - * *imported_module* is the name of the module being imported + * *imported_module* is the resolved name of the module being imported + (for example, ``lazy from .spam import eggs`` passes + ``package.spam``) * *fromlist* is the tuple of names being imported (for ``from ... import`` statements), or ``None`` for regular imports diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 69cb96cf4a0..a9a8cd143e0 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -1205,6 +1205,36 @@ def tearDown(self): sys.set_lazy_imports_filter(None) sys.set_lazy_imports("normal") + def _run_subprocess_with_modules(self, code, files): + with tempfile.TemporaryDirectory() as tmpdir: + for relpath, contents in files.items(): + path = os.path.join(tmpdir, relpath) + os.makedirs(os.path.dirname(path), exist_ok=True) + with open(path, "w", encoding="utf-8") as file: + file.write(textwrap.dedent(contents)) + + env = os.environ.copy() + env["PYTHONPATH"] = os.pathsep.join( + entry for entry in (tmpdir, env.get("PYTHONPATH")) if entry + ) + env["PYTHON_LAZY_IMPORTS"] = "normal" + + result = subprocess.run( + [sys.executable, "-c", textwrap.dedent(code)], + capture_output=True, + cwd=tmpdir, + env=env, + text=True, + ) + return result + + def _assert_subprocess_ok(self, code, files): + result = self._run_subprocess_with_modules(code, files) + self.assertEqual( + result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}" + ) + return result + def test_filter_receives_correct_arguments_for_import(self): """Filter should receive (importer, name, fromlist=None) for 'import x'.""" code = textwrap.dedent(""" @@ -1290,6 +1320,159 @@ def deny_filter(importer, name, fromlist): self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") self.assertIn("EAGER", result.stdout) + def test_filter_distinguishes_absolute_and_relative_from_imports(self): + """Relative imports should pass resolved module names to the filter.""" + files = { + "target.py": """ + VALUE = "absolute" + """, + "pkg/__init__.py": "", + "pkg/target.py": """ + VALUE = "relative" + """, + "pkg/runner.py": """ + import sys + + seen = [] + + def my_filter(importer, name, fromlist): + seen.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy from target import VALUE as absolute_value + lazy from .target import VALUE as relative_value + + assert seen == [ + (__name__, "target", ("VALUE",)), + (__name__, "pkg.target", ("VALUE",)), + ], seen + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + + def test_filter_receives_resolved_name_for_relative_package_import(self): + """'lazy from . import x' should report the resolved package name.""" + files = { + "pkg/__init__.py": "", + "pkg/sibling.py": """ + VALUE = 1 + """, + "pkg/runner.py": """ + import sys + + seen = [] + + def my_filter(importer, name, fromlist): + seen.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy from . import sibling + + assert seen == [ + (__name__, "pkg", ("sibling",)), + ], seen + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + + def test_filter_receives_resolved_name_for_parent_relative_import(self): + """Parent relative imports should also use the resolved module name.""" + files = { + "pkg/__init__.py": "", + "pkg/target.py": """ + VALUE = 1 + """, + "pkg/sub/__init__.py": "", + "pkg/sub/runner.py": """ + import sys + + seen = [] + + def my_filter(importer, name, fromlist): + seen.append((importer, name, fromlist)) + return True + + sys.set_lazy_imports_filter(my_filter) + + lazy from ..target import VALUE + + assert seen == [ + (__name__, "pkg.target", ("VALUE",)), + ], seen + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.sub.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + + def test_filter_can_force_eager_only_for_resolved_relative_target(self): + """Resolved names should let filters treat relative and absolute imports differently.""" + files = { + "target.py": """ + VALUE = "absolute" + """, + "pkg/__init__.py": "", + "pkg/target.py": """ + VALUE = "relative" + """, + "pkg/runner.py": """ + import sys + + def my_filter(importer, name, fromlist): + return name != "pkg.target" + + sys.set_lazy_imports_filter(my_filter) + + lazy from target import VALUE as absolute_value + lazy from .target import VALUE as relative_value + + assert "pkg.target" in sys.modules, sorted( + name for name in sys.modules + if name in {"target", "pkg.target"} + ) + assert "target" not in sys.modules, sorted( + name for name in sys.modules + if name in {"target", "pkg.target"} + ) + assert relative_value == "relative", relative_value + """, + } + + result = self._assert_subprocess_ok( + """ + import pkg.runner + print("OK") + """, + files, + ) + self.assertIn("OK", result.stdout) + class AdditionalSyntaxRestrictionTests(unittest.TestCase): """Additional syntax restriction tests per PEP 810.""" diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst new file mode 100644 index 00000000000..dc7df0e4a29 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst @@ -0,0 +1,2 @@ +Fix :func:`sys.set_lazy_imports_filter` so relative lazy imports pass the +resolved imported module name to the filter callback. Patch by Pablo Galindo. diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index f8ae7f18acc..86e942ec2b8 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -1830,7 +1830,7 @@ PyDoc_STRVAR(sys_set_lazy_imports_filter__doc__, "would otherwise be enabled. Returns True if the import is still enabled\n" "or False to disable it. The callable is called with:\n" "\n" -"(importing_module_name, imported_module_name, [fromlist])\n" +"(importing_module_name, resolved_imported_module_name, [fromlist])\n" "\n" "Pass None to clear the filter."); @@ -2121,4 +2121,4 @@ exit: #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=adbadb629b98eabf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e8333fe10c01ae66 input=a9049054013a1b77]*/ diff --git a/Python/import.c b/Python/import.c index e298fbee536..7aa96196ec1 100644 --- a/Python/import.c +++ b/Python/import.c @@ -4523,7 +4523,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, assert(!PyErr_Occurred()); fromlist = Py_NewRef(Py_None); } - PyObject *args[] = {modname, name, fromlist}; + PyObject *args[] = {modname, abs_name, fromlist}; PyObject *res = PyObject_Vectorcall(filter, args, 3, NULL); Py_DECREF(modname); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index ce9c03bda7b..408d04684a9 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2796,14 +2796,14 @@ The filter is a callable which disables lazy imports when they would otherwise be enabled. Returns True if the import is still enabled or False to disable it. The callable is called with: -(importing_module_name, imported_module_name, [fromlist]) +(importing_module_name, resolved_imported_module_name, [fromlist]) Pass None to clear the filter. [clinic start generated code]*/ static PyObject * sys_set_lazy_imports_filter_impl(PyObject *module, PyObject *filter) -/*[clinic end generated code: output=10251d49469c278c input=2eb48786bdd4ee42]*/ +/*[clinic end generated code: output=10251d49469c278c input=fd51ed8df6ab54b7]*/ { if (PyImport_SetLazyImportsFilter(filter) < 0) { return NULL; From bac4fee745569ef7f9bbe465c1c7f66856854af2 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:45:13 -0700 Subject: [PATCH 436/775] gh-73613: clarify padding= docs in for base64 & binascii modules (GH-148183) Based on mayeut's comment in https://github.com/python/cpython/pull/147974#discussion_r3038498019. --- Doc/library/base64.rst | 13 +++++++++---- Doc/library/binascii.rst | 7 +++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 6e6e5d603e3..40edd60abea 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -85,8 +85,11 @@ POST request. If *padded* is true, the last group of 4 base 64 alphabet characters must be padded with the '=' character. - If *padded* is false, the '=' character is treated as other non-alphabet - characters (depending on the value of *validate* and *ignorechars*). + If *padded* is false, padding is neither required nor recognized: + the '=' character is not treated as padding but as a non-alphabet + character, which means it is silently discarded when *validate* is false, + or causes an :exc:`~binascii.Error` when *validate* is true unless + b'=' is included in *ignorechars*. A :exc:`binascii.Error` exception is raised if *s* is incorrectly padded. @@ -194,8 +197,10 @@ POST request. If *padded* is true, the last group of 8 base 32 alphabet characters must be padded with the '=' character. - If *padded* is false, the '=' character is treated as other non-alphabet - characters (depending on the value of *ignorechars*). + If *padded* is false, padding is neither required nor recognized: + the '=' character is not treated as padding but as a non-alphabet + character, which means it raises an :exc:`~binascii.Error` unless + b'=' is included in *ignorechars*. *ignorechars* should be a :term:`bytes-like object` containing characters to ignore from the input. diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 4f2edb7eff8..de5e5766779 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -59,8 +59,11 @@ The :mod:`!binascii` module defines the following functions: If *padded* is true, the last group of 4 base 64 alphabet characters must be padded with the '=' character. - If *padded* is false, the '=' character is treated as other non-alphabet - characters (depending on the value of *strict_mode* and *ignorechars*). + If *padded* is false, padding is neither required nor recognized: + the '=' character is not treated as padding but as a non-alphabet + character, which means it is silently discarded when *strict_mode* is false, + or causes an :exc:`~binascii.Error` when *strict_mode* is true unless + b'=' is included in *ignorechars*. If *ignorechars* is specified, it should be a :term:`bytes-like object` containing characters to ignore from the input when *strict_mode* is true. From 8a73478fedaee54a409f1933ff8f50c3a6fdf883 Mon Sep 17 00:00:00 2001 From: Mazin Sharaf Date: Tue, 7 Apr 2026 09:48:38 +1000 Subject: [PATCH 437/775] gh-145844: Update WASI SDK from 30 to 32 (#145859) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Brett Cannon --- .../next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst | 1 + Platforms/WASI/config.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst diff --git a/Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst b/Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst new file mode 100644 index 00000000000..10fac03be32 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst @@ -0,0 +1 @@ +Update to WASI SDK 32. diff --git a/Platforms/WASI/config.toml b/Platforms/WASI/config.toml index 2f7a87decd6..31ec2b8023d 100644 --- a/Platforms/WASI/config.toml +++ b/Platforms/WASI/config.toml @@ -2,5 +2,5 @@ # This allows for blanket copying of the WASI build code between supported # Python versions. [targets] -wasi-sdk = 30 +wasi-sdk = 32 host-triple = "wasm32-wasip1" From 3df0c4da4c502a4e26ed00468dd97aa50a3bb260 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Mon, 6 Apr 2026 23:08:47 -0500 Subject: [PATCH 438/775] Note out-of-date obmalloc comments (#148149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vladimir's original overviews, from 1998, are still good, but going on 30 years later details have changed. Note that, but rather try to keep up with moving targets in a different file, point to sys._debugmallocstats() as the sure way to discover precise current details. No code changes, just added a block comment. Co-authored-by: Bartosz Sławecki --- Include/internal/pycore_obmalloc.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Include/internal/pycore_obmalloc.h b/Include/internal/pycore_obmalloc.h index d4dbe541e6d..f6b4bd90a23 100644 --- a/Include/internal/pycore_obmalloc.h +++ b/Include/internal/pycore_obmalloc.h @@ -14,6 +14,12 @@ typedef unsigned int pymem_uint; /* assuming >= 16 bits */ #undef uint #define uint pymem_uint +/* NOTE: the following overviews were in the initial checkin, in 1998. In + * 2026, they're still helpful, but some details have changed. For example, + * we now use 32 size classes 16 bytes apart, and an arena is generally at + * least 1MB. Use sys._debugmallocstats() to see exact current details for + * the specific version of CPython used. + */ /* An object allocator for Python. From 132abfd135c26053dedc53ee65e79d2c3900094e Mon Sep 17 00:00:00 2001 From: Semyon Moroz Date: Tue, 7 Apr 2026 08:42:54 +0400 Subject: [PATCH 439/775] gh-112632: Add optional keyword-only argument `expand` to `pprint` (#136964) Co-authored-by: stodoran Co-authored-by: StefanTodoran Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Doc/library/pprint.rst | 109 ++++- Doc/whatsnew/3.15.rst | 10 + Lib/pprint.py | 274 +++++++---- Lib/test/test_pprint.py | 458 ++++++++++++++++++ ...-02-07-00-48-07.gh-issue-112632.95MM0C.rst | 3 + 5 files changed, 768 insertions(+), 86 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 350831d6ad3..77ed44c2bb7 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -31,7 +31,8 @@ Functions --------- .. function:: pp(object, stream=None, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=False, underscore_numbers=False) + compact=False, expand=False, sort_dicts=False, \ + underscore_numbers=False) Prints the formatted representation of *object*, followed by a newline. This function may be used in the interactive interpreter @@ -69,6 +70,13 @@ Functions each item of a sequence will be formatted on a separate line, otherwise as many items as will fit within the *width* will be formatted on each output line. + Incompatible with *expand*. + + :param bool expand: + If ``True``, + opening parentheses and brackets will be followed by a newline and the + following content will be indented by one level, similar to + pretty-printed JSON. Incompatible with *compact*. :param bool sort_dicts: If ``True``, dictionaries will be formatted with @@ -95,7 +103,8 @@ Functions .. function:: pprint(object, stream=None, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + compact=False, expand=False, sort_dicts=True, \ + underscore_numbers=False) Alias for :func:`~pprint.pp` with *sort_dicts* set to ``True`` by default, which would automatically sort the dictionaries' keys, @@ -103,10 +112,11 @@ Functions .. function:: pformat(object, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + compact=False, expand=False, sort_dicts=True, \ + underscore_numbers=False) Return the formatted representation of *object* as a string. *indent*, - *width*, *depth*, *compact*, *sort_dicts* and *underscore_numbers* are + *width*, *depth*, *compact*, *expand*, *sort_dicts* and *underscore_numbers* are passed to the :class:`PrettyPrinter` constructor as formatting parameters and their meanings are as described in the documentation above. @@ -150,7 +160,8 @@ PrettyPrinter Objects .. index:: single: ...; placeholder .. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \ - compact=False, sort_dicts=True, underscore_numbers=False) + compact=False, expand=False, sort_dicts=True, \ + underscore_numbers=False) Construct a :class:`PrettyPrinter` instance. @@ -174,6 +185,22 @@ PrettyPrinter Objects 'knights', 'ni'], 'spam', 'eggs', 'lumberjack', 'knights', 'ni'] + >>> pp = pprint.PrettyPrinter(width=41, expand=True, indent=3) + >>> pp.pprint(stuff) + [ + [ + 'spam', + 'eggs', + 'lumberjack', + 'knights', + 'ni', + ], + 'spam', + 'eggs', + 'lumberjack', + 'knights', + 'ni', + ] >>> tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead', ... ('parrot', ('fresh fruit',)))))))) >>> pp = pprint.PrettyPrinter(depth=6) @@ -193,6 +220,9 @@ PrettyPrinter Objects .. versionchanged:: 3.11 No longer attempts to write to :data:`!sys.stdout` if it is ``None``. + .. versionchanged:: next + Added the *expand* parameter. + :class:`PrettyPrinter` instances have the following methods: @@ -415,3 +445,72 @@ cannot be split, the specified width will be exceeded:: 'requires_python': None, 'summary': 'A sample Python project', 'version': '1.2.0'} + +Lastly, we can format like pretty-printed JSON with the *expand* parameter. +Best results are achieved with a higher *indent* value:: + + >>> pprint.pp(project_info, indent=4, expand=True) + { + 'author': 'The Python Packaging Authority', + 'author_email': 'pypa-dev@googlegroups.com', + 'bugtrack_url': None, + 'classifiers': [ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Topic :: Software Development :: Build Tools', + ], + 'description': 'A sample Python project\n' + '=======================\n' + '\n' + 'This is the description file for the project.\n' + '\n' + 'The file should use UTF-8 encoding and be written using ReStructured ' + 'Text. It\n' + 'will be used to generate the project webpage on PyPI, and should be ' + 'written for\n' + 'that purpose.\n' + '\n' + 'Typical contents for this file would include an overview of the project, ' + 'basic\n' + 'usage examples, etc. Generally, including the project changelog in here ' + 'is not\n' + 'a good idea, although a simple "What\'s New" section for the most recent ' + 'version\n' + 'may be appropriate.', + 'description_content_type': None, + 'docs_url': None, + 'download_url': 'UNKNOWN', + 'downloads': {'last_day': -1, 'last_month': -1, 'last_week': -1}, + 'dynamic': None, + 'home_page': 'https://github.com/pypa/sampleproject', + 'keywords': 'sample setuptools development', + 'license': 'MIT', + 'license_expression': None, + 'license_files': None, + 'maintainer': None, + 'maintainer_email': None, + 'name': 'sampleproject', + 'package_url': 'https://pypi.org/project/sampleproject/', + 'platform': 'UNKNOWN', + 'project_url': 'https://pypi.org/project/sampleproject/', + 'project_urls': { + 'Download': 'UNKNOWN', + 'Homepage': 'https://github.com/pypa/sampleproject', + }, + 'provides_extra': None, + 'release_url': 'https://pypi.org/project/sampleproject/1.2.0/', + 'requires_dist': None, + 'requires_python': None, + 'summary': 'A sample Python project', + 'version': '1.2.0', + 'yanked': False, + 'yanked_reason': None, + } diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index d1d4b92bcf4..68e2911deeb 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1507,6 +1507,16 @@ platform (Contributed by Alexey Makridenko in :gh:`133604`.) +pprint +------ + +* Add an *expand* keyword argument for :func:`pprint.pprint`, + :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be + formatted similar to pretty-printed :func:`json.dumps` when + *indent* is supplied. + (Contributed by Stefan Todoran and Semyon Moroz in :gh:`112632`.) + + sre_* ----- diff --git a/Lib/pprint.py b/Lib/pprint.py index a0e484b1c09..f197d7d17cd 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -44,20 +44,22 @@ def pprint(object, stream=None, indent=1, width=80, depth=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): + compact=False, expand=False, sort_dicts=True, + underscore_numbers=False): """Pretty-print a Python object to a stream [default is sys.stdout].""" printer = PrettyPrinter( stream=stream, indent=indent, width=width, depth=depth, - compact=compact, sort_dicts=sort_dicts, + compact=compact, expand=expand, sort_dicts=sort_dicts, underscore_numbers=underscore_numbers) printer.pprint(object) def pformat(object, indent=1, width=80, depth=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): + compact=False, expand=False, sort_dicts=True, + underscore_numbers=False): """Format a Python object into a pretty-printed representation.""" return PrettyPrinter(indent=indent, width=width, depth=depth, - compact=compact, sort_dicts=sort_dicts, + compact=compact, expand=expand, sort_dicts=sort_dicts, underscore_numbers=underscore_numbers).pformat(object) @@ -111,7 +113,8 @@ def _safe_tuple(t): class PrettyPrinter: def __init__(self, indent=1, width=80, depth=None, stream=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): + compact=False, expand=False, sort_dicts=True, + underscore_numbers=False): """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -130,6 +133,12 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, compact If true, several items will be combined in one line. + Incompatible with expand mode. + + expand + If true, the output will be formatted similar to + pretty-printed json.dumps() when ``indent`` is supplied. + Incompatible with compact mode. sort_dicts If true, dict keys are sorted. @@ -146,6 +155,8 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, raise ValueError('depth must be > 0') if not width: raise ValueError('width must be != 0') + if compact and expand: + raise ValueError('compact and expand are incompatible') self._depth = depth self._indent_per_level = indent self._width = width @@ -154,6 +165,7 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, else: self._stream = _sys.stdout self._compact = bool(compact) + self._expand = bool(expand) self._sort_dicts = sort_dicts self._underscore_numbers = underscore_numbers @@ -205,24 +217,48 @@ def _format(self, object, stream, indent, allowance, context, level): return stream.write(rep) + def _format_block_start(self, start_str, indent): + if self._expand: + return f"{start_str}\n{' ' * indent}" + return start_str + + def _format_block_end(self, end_str, indent): + if self._expand: + return f"\n{' ' * indent}{end_str}" + return end_str + + def _child_indent(self, indent, prefix_len): + if self._expand: + return indent + return indent + prefix_len + + def _write_indent_padding(self, write): + if self._expand: + if self._indent_per_level > 0: + write(self._indent_per_level * " ") + elif self._indent_per_level > 1: + write((self._indent_per_level - 1) * " ") + def _pprint_dataclass(self, object, stream, indent, allowance, context, level): # Lazy import to improve module import time from dataclasses import fields as dataclass_fields cls_name = object.__class__.__name__ - indent += len(cls_name) + 1 + if self._expand: + indent += self._indent_per_level + else: + indent += len(cls_name) + 1 items = [(f.name, getattr(object, f.name)) for f in dataclass_fields(object) if f.repr] - stream.write(cls_name + '(') + stream.write(self._format_block_start(cls_name + '(', indent)) self._format_namespace_items(items, stream, indent, allowance, context, level) - stream.write(')') + stream.write(self._format_block_end(')', indent - self._indent_per_level)) _dispatch = {} def _pprint_dict(self, object, stream, indent, allowance, context, level): write = stream.write - write('{') - if self._indent_per_level > 1: - write((self._indent_per_level - 1) * ' ') + write(self._format_block_start('{', indent)) + self._write_indent_padding(write) length = len(object) if length: if self._sort_dicts: @@ -231,21 +267,33 @@ def _pprint_dict(self, object, stream, indent, allowance, context, level): items = object.items() self._format_dict_items(items, stream, indent, allowance + 1, context, level) - write('}') + write(self._format_block_end('}', indent)) _dispatch[dict.__repr__] = _pprint_dict def _pprint_frozendict(self, object, stream, indent, allowance, context, level): write = stream.write cls = object.__class__ - write(cls.__name__ + '(') - length = len(object) - if length: - self._pprint_dict(object, stream, - indent + len(cls.__name__) + 1, - allowance + 1, - context, level) - write(')') + if not len(object): + write(repr(object)) + return + + write(self._format_block_start(cls.__name__ + "({", indent)) + self._write_indent_padding(write) + + if self._sort_dicts: + items = sorted(object.items(), key=_safe_tuple) + else: + items = object.items() + self._format_dict_items( + items, + stream, + self._child_indent(indent, len(cls.__name__) + 1), + allowance + 2, + context, + level, + ) + write(self._format_block_end("})", indent)) _dispatch[frozendict.__repr__] = _pprint_frozendict @@ -255,9 +303,14 @@ def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level return cls = object.__class__ stream.write(cls.__name__ + '(') - self._format(list(object.items()), stream, - indent + len(cls.__name__) + 1, allowance + 1, - context, level) + self._format( + list(object.items()), + stream, + self._child_indent(indent, len(cls.__name__) + 1), + allowance + 1, + context, + level, + ) stream.write(')') _dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict @@ -268,19 +321,21 @@ def _pprint_dict_view(self, object, stream, indent, allowance, context, level): key = _safe_tuple else: key = _safe_key + write = stream.write - write(object.__class__.__name__ + '([') - if self._indent_per_level > 1: - write((self._indent_per_level - 1) * ' ') - length = len(object) - if length: + write( + self._format_block_start(object.__class__.__name__ + "([", indent) + ) + + if len(object): if self._sort_dicts: entries = sorted(object, key=key) else: entries = object - self._format_items(entries, stream, indent, allowance + 1, - context, level) - write('])') + self._format_items( + entries, stream, indent, allowance + 2, context, level + ) + write(self._format_block_end("])", indent)) def _pprint_mapping_abc_view(self, object, stream, indent, allowance, context, level): """Pretty print mapping views from collections.abc.""" @@ -306,19 +361,22 @@ def _pprint_mapping_abc_view(self, object, stream, indent, allowance, context, l _collections.abc.MappingView)} def _pprint_list(self, object, stream, indent, allowance, context, level): - stream.write('[') + stream.write(self._format_block_start('[', indent)) self._format_items(object, stream, indent, allowance + 1, context, level) - stream.write(']') + stream.write(self._format_block_end(']', indent)) _dispatch[list.__repr__] = _pprint_list def _pprint_tuple(self, object, stream, indent, allowance, context, level): - stream.write('(') - endchar = ',)' if len(object) == 1 else ')' + stream.write(self._format_block_start('(', indent)) + if len(object) == 1 and not self._expand: + endchar = ',)' + else: + endchar = ')' self._format_items(object, stream, indent, allowance + len(endchar), context, level) - stream.write(endchar) + stream.write(self._format_block_end(endchar, indent)) _dispatch[tuple.__repr__] = _pprint_tuple @@ -328,16 +386,17 @@ def _pprint_set(self, object, stream, indent, allowance, context, level): return typ = object.__class__ if typ is set: - stream.write('{') + stream.write(self._format_block_start('{', indent)) endchar = '}' else: - stream.write(typ.__name__ + '({') + stream.write(self._format_block_start(typ.__name__ + '({', indent)) endchar = '})' - indent += len(typ.__name__) + 1 + if not self._expand: + indent += len(typ.__name__) + 1 object = sorted(object, key=_safe_key) self._format_items(object, stream, indent, allowance + len(endchar), context, level) - stream.write(endchar) + stream.write(self._format_block_end(endchar, indent)) _dispatch[set.__repr__] = _pprint_set _dispatch[frozenset.__repr__] = _pprint_set @@ -350,7 +409,10 @@ def _pprint_str(self, object, stream, indent, allowance, context, level): chunks = [] lines = object.splitlines(True) if level == 1: - indent += 1 + if self._expand: + indent += self._indent_per_level + else: + indent += 1 allowance += 1 max_width1 = max_width = self._width - indent for i, line in enumerate(lines): @@ -386,13 +448,13 @@ def _pprint_str(self, object, stream, indent, allowance, context, level): write(rep) return if level == 1: - write('(') + write(self._format_block_start("(", indent)) for i, rep in enumerate(chunks): if i > 0: write('\n' + ' '*indent) write(rep) if level == 1: - write(')') + write(self._format_block_end(")", indent - self._indent_per_level)) _dispatch[str.__repr__] = _pprint_str @@ -403,9 +465,12 @@ def _pprint_bytes(self, object, stream, indent, allowance, context, level): return parens = level == 1 if parens: - indent += 1 + if self._expand: + indent += self._indent_per_level + else: + indent += 1 allowance += 1 - write('(') + write(self._format_block_start('(', indent)) delim = '' for rep in _wrap_bytes_repr(object, self._width - indent, allowance): write(delim) @@ -413,23 +478,34 @@ def _pprint_bytes(self, object, stream, indent, allowance, context, level): if not delim: delim = '\n' + ' '*indent if parens: - write(')') + write(self._format_block_end(')', indent - self._indent_per_level)) _dispatch[bytes.__repr__] = _pprint_bytes def _pprint_bytearray(self, object, stream, indent, allowance, context, level): write = stream.write - write('bytearray(') - self._pprint_bytes(bytes(object), stream, indent + 10, + write(self._format_block_start('bytearray(', indent)) + if self._expand: + write(' ' * self._indent_per_level) + recursive_indent = indent + self._indent_per_level + else: + recursive_indent = indent + 10 + self._pprint_bytes(bytes(object), stream, recursive_indent, allowance + 1, context, level + 1) - write(')') + write(self._format_block_end(')', indent)) _dispatch[bytearray.__repr__] = _pprint_bytearray def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level): stream.write('mappingproxy(') - self._format(object.copy(), stream, indent + 13, allowance + 1, - context, level) + self._format( + object.copy(), + stream, + self._child_indent(indent, 13), + allowance + 1, + context, + level, + ) stream.write(')') _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy @@ -441,11 +517,15 @@ def _pprint_simplenamespace(self, object, stream, indent, allowance, context, le cls_name = 'namespace' else: cls_name = object.__class__.__name__ - indent += len(cls_name) + 1 + if self._expand: + indent += self._indent_per_level + else: + indent += len(cls_name) + 1 items = object.__dict__.items() - stream.write(cls_name + '(') - self._format_namespace_items(items, stream, indent, allowance, context, level) - stream.write(')') + stream.write(self._format_block_start(cls_name + '(', indent)) + self._format_namespace_items(items, stream, indent, allowance, context, + level) + stream.write(self._format_block_end(')', indent - self._indent_per_level)) _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace @@ -460,11 +540,18 @@ def _format_dict_items(self, items, stream, indent, allowance, context, rep = self._repr(key, context, level) write(rep) write(': ') - self._format(ent, stream, indent + len(rep) + 2, - allowance if last else 1, - context, level) + self._format( + ent, + stream, + self._child_indent(indent, len(rep) + 2), + allowance if last else 1, + context, + level, + ) if not last: write(delimnl) + elif self._expand: + write(',') def _format_namespace_items(self, items, stream, indent, allowance, context, level): write = stream.write @@ -479,17 +566,23 @@ def _format_namespace_items(self, items, stream, indent, allowance, context, lev # recursive dataclass repr. write("...") else: - self._format(ent, stream, indent + len(key) + 1, - allowance if last else 1, - context, level) + self._format( + ent, + stream, + self._child_indent(indent, len(key) + 1), + allowance if last else 1, + context, + level, + ) if not last: write(delimnl) + elif self._expand: + write(',') def _format_items(self, items, stream, indent, allowance, context, level): write = stream.write indent += self._indent_per_level - if self._indent_per_level > 1: - write((self._indent_per_level - 1) * ' ') + self._write_indent_padding(write) delimnl = ',\n' + ' ' * indent delim = '' width = max_width = self._width - indent + 1 @@ -525,6 +618,8 @@ def _format_items(self, items, stream, indent, allowance, context, level): self._format(ent, stream, indent, allowance if last else 1, context, level) + if last and self._expand: + write(',') def _repr(self, object, context, level): repr, readable, recursive = self.format(object, context.copy(), @@ -548,9 +643,13 @@ def _pprint_default_dict(self, object, stream, indent, allowance, context, level return rdf = self._repr(object.default_factory, context, level) cls = object.__class__ - indent += len(cls.__name__) + 1 - stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent)) - self._pprint_dict(object, stream, indent, allowance + 1, context, level) + if self._expand: + stream.write('%s(%s, ' % (cls.__name__, rdf)) + else: + indent += len(cls.__name__) + 1 + stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent)) + self._pprint_dict(object, stream, indent, allowance + 1, context, + level) stream.write(')') _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict @@ -560,14 +659,18 @@ def _pprint_counter(self, object, stream, indent, allowance, context, level): stream.write(repr(object)) return cls = object.__class__ - stream.write(cls.__name__ + '({') - if self._indent_per_level > 1: - stream.write((self._indent_per_level - 1) * ' ') + stream.write(self._format_block_start(cls.__name__ + '({', indent)) + self._write_indent_padding(stream.write) items = object.most_common() - self._format_dict_items(items, stream, - indent + len(cls.__name__) + 1, allowance + 2, - context, level) - stream.write('})') + self._format_dict_items( + items, + stream, + self._child_indent(indent, len(cls.__name__) + 1), + allowance + 2, + context, + level, + ) + stream.write(self._format_block_end('})', indent)) _dispatch[_collections.Counter.__repr__] = _pprint_counter @@ -576,12 +679,18 @@ def _pprint_chain_map(self, object, stream, indent, allowance, context, level): stream.write(repr(object)) return cls = object.__class__ - stream.write(cls.__name__ + '(') - indent += len(cls.__name__) + 1 + stream.write(self._format_block_start(cls.__name__ + '(', + indent + self._indent_per_level)) + if self._expand: + indent += self._indent_per_level + else: + indent += len(cls.__name__) + 1 for i, m in enumerate(object.maps): if i == len(object.maps) - 1: self._format(m, stream, indent, allowance + 1, context, level) - stream.write(')') + if self._expand: + stream.write(',') + stream.write(self._format_block_end(')', indent - self._indent_per_level)) else: self._format(m, stream, indent, 1, context, level) stream.write(',\n' + ' ' * indent) @@ -593,18 +702,21 @@ def _pprint_deque(self, object, stream, indent, allowance, context, level): stream.write(repr(object)) return cls = object.__class__ - stream.write(cls.__name__ + '(') - indent += len(cls.__name__) + 1 - stream.write('[') + stream.write(self._format_block_start(cls.__name__ + '([', indent)) + if not self._expand: + indent += len(cls.__name__) + 1 if object.maxlen is None: self._format_items(object, stream, indent, allowance + 2, context, level) - stream.write('])') + stream.write(self._format_block_end('])', indent)) else: self._format_items(object, stream, indent, 2, context, level) rml = self._repr(object.maxlen, context, level) - stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml)) + if self._expand: + stream.write('%s], maxlen=%s)' % ('\n' + ' ' * indent, rml)) + else: + stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml)) _dispatch[_collections.deque.__repr__] = _pprint_deque diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index f3860a5d511..45e081c233f 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -164,6 +164,7 @@ def test_init(self): self.assertRaises(ValueError, pprint.PrettyPrinter, depth=0) self.assertRaises(ValueError, pprint.PrettyPrinter, depth=-1) self.assertRaises(ValueError, pprint.PrettyPrinter, width=0) + self.assertRaises(ValueError, pprint.PrettyPrinter, compact=True, expand=True) def test_basic(self): # Verify .isrecursive() and .isreadable() w/o recursion @@ -1298,6 +1299,12 @@ def test_counter(self): 'e': 4, 'n': 2, 'l': 1})""") + self.assertEqual(pprint.pformat(d, indent=2, width=1), +"""\ +Counter({ 's': 6, + 'e': 4, + 'n': 2, + 'l': 1})""") def test_chainmap(self): d = collections.ChainMap() @@ -1508,6 +1515,457 @@ def test_user_string(self): 'jumped over a ' 'lazy dog'}""") + def test_expand_dataclass(self): + @dataclasses.dataclass + class DummyDataclass: + foo: str + bar: float + baz: bool + qux: dict = dataclasses.field(default_factory=dict) + quux: list = dataclasses.field(default_factory=list) + corge: int = 1 + garply: tuple = (1, 2, 3, 4) + dummy_dataclass = DummyDataclass( + foo="foo", + bar=1.2, + baz=False, + qux={"foo": "bar", "baz": 123}, + quux=["foo", "bar", "baz"], + corge=7, + garply=(1, 2, 3, 4), + ) + self.assertEqual(pprint.pformat(dummy_dataclass, width=40, indent=4, + expand=True), +"""\ +DummyDataclass( + foo='foo', + bar=1.2, + baz=False, + qux={'baz': 123, 'foo': 'bar'}, + quux=['foo', 'bar', 'baz'], + corge=7, + garply=(1, 2, 3, 4), +)""") + + def test_expand_dict(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + self.assertEqual(pprint.pformat(dummy_dict, width=40, indent=4, + expand=True, sort_dicts=False), +"""\ +{ + 'foo': 'bar', + 'baz': 123, + 'qux': {'foo': 'bar', 'baz': 123}, + 'quux': ['foo', 'bar', 'baz'], + 'corge': 7, +}""") + + def test_expand_ordered_dict(self): + dummy_ordered_dict = collections.OrderedDict( + [ + ("foo", 1), + ("bar", 12), + ("baz", 123), + ] + ) + self.assertEqual(pprint.pformat(dummy_ordered_dict, width=20, indent=4, + expand=True), +"""\ +OrderedDict([ + ('foo', 1), + ('bar', 12), + ('baz', 123), +])""") + + def test_expand_list(self): + dummy_list = [ + "foo", + "bar", + "baz", + "qux", + ] + self.assertEqual(pprint.pformat(dummy_list, width=20, indent=4, + expand=True), +"""\ +[ + 'foo', + 'bar', + 'baz', + 'qux', +]""") + + def test_expand_tuple(self): + dummy_tuple = ( + "foo", + "bar", + "baz", + 4, + 5, + 6, + ) + self.assertEqual(pprint.pformat(dummy_tuple, width=20, indent=4, + expand=True), +"""\ +( + 'foo', + 'bar', + 'baz', + 4, + 5, + 6, +)""") + + def test_expand_single_element_tuple(self): + self.assertEqual( + pprint.pformat((1,), width=1, indent=4, expand=True), + """\ +( + 1, +)""") + + def test_expand_set(self): + dummy_set = { + "foo", + "bar", + "baz", + "qux", + (1, 2, 3), + } + self.assertEqual(pprint.pformat(dummy_set, width=20, indent=4, + expand=True), +"""\ +{ + 'bar', + 'baz', + 'foo', + 'qux', + (1, 2, 3), +}""") + + def test_expand_frozenset(self): + dummy_set = { + (1, 2, 3), + } + dummy_frozenset = frozenset( + { + "foo", + "bar", + "baz", + (1, 2, 3), + frozenset(dummy_set), + } + ) + self.assertEqual(pprint.pformat(dummy_frozenset, width=40, indent=4, + expand=True), +"""\ +frozenset({ + frozenset({(1, 2, 3)}), + 'bar', + 'baz', + 'foo', + (1, 2, 3), +})""") + + def test_expand_frozendict(self): + dummy_frozendict = frozendict( + {"foo": "bar", "baz": 123, "qux": [1, 2]} + ) + self.assertEqual( + pprint.pformat(dummy_frozendict, width=20, indent=4, expand=True), + """\ +frozendict({ + 'baz': 123, + 'foo': 'bar', + 'qux': [1, 2], +})""", + ) + + def test_expand_bytes(self): + dummy_bytes = b"Hello world! foo bar baz 123 456 789" + self.assertEqual(pprint.pformat(dummy_bytes, width=20, indent=4, + expand=True), +"""\ +( + b'Hello world!' + b' foo bar baz' + b' 123 456 789' +)""") + + def test_expand_bytearray(self): + dummy_bytes = b"Hello world! foo bar baz 123 456 789" + dummy_byte_array = bytearray(dummy_bytes) + self.assertEqual(pprint.pformat(dummy_byte_array, width=40, indent=4, + expand=True), +"""\ +bytearray( + b'Hello world! foo bar baz 123 456' + b' 789' +)""") + + def test_expand_mappingproxy(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + dummy_mappingproxy = types.MappingProxyType(dummy_dict) + self.assertEqual(pprint.pformat(dummy_mappingproxy, width=40, indent=4, + expand=True), +"""\ +mappingproxy({ + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': {'baz': 123, 'foo': 'bar'}, +})""") + + def test_expand_namespace(self): + dummy_namespace = types.SimpleNamespace( + foo="bar", + bar=42, + baz=types.SimpleNamespace( + x=321, + y="string", + d={"foo": True, "bar": "baz"}, + ), + ) + + self.assertEqual(pprint.pformat(dummy_namespace, width=40, indent=4, + expand=True), +"""\ +namespace( + foo='bar', + bar=42, + baz=namespace( + x=321, + y='string', + d={'bar': 'baz', 'foo': True}, + ), +)""") + + def test_expand_defaultdict(self): + dummy_defaultdict = collections.defaultdict(list) + dummy_defaultdict["foo"].append("bar") + dummy_defaultdict["foo"].append("baz") + dummy_defaultdict["foo"].append("qux") + dummy_defaultdict["bar"] = {"foo": "bar", "baz": None} + self.assertEqual(pprint.pformat(dummy_defaultdict, width=40, indent=4, + expand=True), +"""\ +defaultdict(, { + 'bar': {'baz': None, 'foo': 'bar'}, + 'foo': ['bar', 'baz', 'qux'], +})""") + + def test_expand_counter(self): + dummy_counter = collections.Counter("abcdeabcdabcaba") + expected = """\ +Counter({ + 'a': 5, + 'b': 4, + 'c': 3, + 'd': 2, + 'e': 1, +})""" + self.assertEqual(pprint.pformat(dummy_counter, width=40, indent=4, + expand=True), expected) + + expected2 = """\ +Counter({ + 'a': 5, + 'b': 4, + 'c': 3, + 'd': 2, + 'e': 1, +})""" + self.assertEqual(pprint.pformat(dummy_counter, width=20, indent=2, + expand=True), expected2) + + def test_expand_chainmap(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + dummy_chainmap = collections.ChainMap( + {"foo": "bar"}, + {"baz": "qux"}, + {"corge": dummy_dict}, + ) + dummy_chainmap.maps.append({"garply": "waldo"}) + self.assertEqual(pprint.pformat(dummy_chainmap, width=40, indent=4, + expand=True), +"""\ +ChainMap( + {'foo': 'bar'}, + {'baz': 'qux'}, + { + 'corge': { + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': { + 'baz': 123, + 'foo': 'bar', + }, + }, + }, + {'garply': 'waldo'}, +)""") + + def test_expand_deque(self): + dummy_dict = { + "foo": "bar", + "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7, + } + dummy_list = [ + "foo", + "bar", + "baz", + ] + dummy_set = { + (1, 2, 3), + } + dummy_deque = collections.deque(maxlen=10) + dummy_deque.append("foo") + dummy_deque.append(123) + dummy_deque.append(dummy_dict) + dummy_deque.extend(dummy_list) + dummy_deque.appendleft(dummy_set) + self.assertEqual(pprint.pformat(dummy_deque, width=40, indent=4, + expand=True), +"""\ +deque([ + {(1, 2, 3)}, + 'foo', + 123, + { + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': {'baz': 123, 'foo': 'bar'}, + }, + 'foo', + 'bar', + 'baz', +], maxlen=10)""") + + def test_expand_userdict(self): + class DummyUserDict(collections.UserDict): + """A custom UserDict with some extra attributes""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.access_count = 0 + dummy_userdict = DummyUserDict({ "foo": "bar", "baz": 123, + "qux": {"foo": "bar", "baz": 123}, + "quux": ["foo", "bar", "baz"], + "corge": 7 }) + dummy_userdict.access_count = 5 + + self.assertEqual(pprint.pformat(dummy_userdict, width=40, indent=4, + expand=True), +"""\ +{ + 'baz': 123, + 'corge': 7, + 'foo': 'bar', + 'quux': ['foo', 'bar', 'baz'], + 'qux': {'baz': 123, 'foo': 'bar'}, +}""") + + def test_expand_userlist(self): + class DummyUserList(collections.UserList): + """A custom UserList with some extra attributes""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.description = "foo" + dummy_userlist = DummyUserList(["first", 2, {"key": "value"}, + [4, 5, 6]]) + + self.assertEqual(pprint.pformat(dummy_userlist, width=40, indent=4, + expand=True), +"""\ +[ + 'first', + 2, + {'key': 'value'}, + [4, 5, 6], +]""") + + def test_expand_dict_keys(self): + d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5} + self.assertEqual( + pprint.pformat(d.keys(), width=20, indent=4, expand=True), + """\ +dict_keys([ + 'bar', + 'baz', + 'foo', + 'quux', + 'qux', +])""", + ) + + def test_expand_dict_values(self): + d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5} + self.assertEqual( + pprint.pformat(d.values(), width=20, indent=4, expand=True), + """\ +dict_values([ + 1, + 2, + 3, + 4, + 5, +])""", + ) + + def test_expand_dict_items(self): + d = {"foo": 1, "bar": 2, "baz": 3, "qux": 4, "quux": 5} + self.assertEqual( + pprint.pformat(d.items(), width=20, indent=4, expand=True), + """\ +dict_items([ + ('bar', 2), + ('baz', 3), + ('foo', 1), + ('quux', 5), + ('qux', 4), +])""", + ) + + def test_expand_str(self): + s = "The quick brown fox jumped over the lazy dog " * 3 + self.assertEqual( + pprint.pformat(s, width=40, indent=4, expand=True), + """\ +( + 'The quick brown fox jumped over ' + 'the lazy dog The quick brown fox ' + 'jumped over the lazy dog The ' + 'quick brown fox jumped over the ' + 'lazy dog ' +)""", + ) + class DottedPrettyPrinter(pprint.PrettyPrinter): diff --git a/Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst b/Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst new file mode 100644 index 00000000000..0842c8e3a04 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst @@ -0,0 +1,3 @@ +Add an *expand* keyword argument for :func:`pprint.pprint`, +:func:`pprint.pformat`, :func:`pprint.pp` by passing on all *kwargs* and +:class:`pprint.PrettyPrinter`. Contributed by Stefan Todoran and Semyon Moroz. From 6bb7b33e8f8e1640e284aeb24bf90292df6a8187 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 6 Apr 2026 21:52:59 -0700 Subject: [PATCH 440/775] GH-146128: Remove the buggy AArch64 "33rx" relocation (#146263) --- ...-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst | 3 + Python/jit.c | 73 ------------------- Tools/jit/_stencils.py | 40 ++-------- Tools/jit/_writer.py | 10 +-- 4 files changed, 10 insertions(+), 116 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst new file mode 100644 index 00000000000..931e1ac92ce --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst @@ -0,0 +1,3 @@ +Fix a bug which could cause constant values to be partially corrupted in +AArch64 JIT code. This issue is theoretical, and hasn't actually been +observed in unmodified Python interpreters. diff --git a/Python/jit.c b/Python/jit.c index 4990c743224..d56ff6ad156 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -355,18 +355,6 @@ patch_aarch64_12(unsigned char *location, uint64_t value) set_bits(loc32, 10, value, shift, 12); } -// Relaxable 12-bit low part of an absolute address. Pairs nicely with -// patch_aarch64_21rx (below). -void -patch_aarch64_12x(unsigned char *location, uint64_t value) -{ - // This can *only* be relaxed if it occurs immediately before a matching - // patch_aarch64_21rx. If that happens, the JIT build step will replace both - // calls with a single call to patch_aarch64_33rx. Otherwise, we end up - // here, and the instruction is patched normally: - patch_aarch64_12(location, value); -} - // 16-bit low part of an absolute address. void patch_aarch64_16a(unsigned char *location, uint64_t value) @@ -427,18 +415,6 @@ patch_aarch64_21r(unsigned char *location, uint64_t value) set_bits(loc32, 5, value, 2, 19); } -// Relaxable 21-bit count of pages between this page and an absolute address's -// page. Pairs nicely with patch_aarch64_12x (above). -void -patch_aarch64_21rx(unsigned char *location, uint64_t value) -{ - // This can *only* be relaxed if it occurs immediately before a matching - // patch_aarch64_12x. If that happens, the JIT build step will replace both - // calls with a single call to patch_aarch64_33rx. Otherwise, we end up - // here, and the instruction is patched normally: - patch_aarch64_21r(location, value); -} - // 21-bit relative branch. void patch_aarch64_19r(unsigned char *location, uint64_t value) @@ -469,55 +445,6 @@ patch_aarch64_26r(unsigned char *location, uint64_t value) set_bits(loc32, 0, value, 2, 26); } -// A pair of patch_aarch64_21rx and patch_aarch64_12x. -void -patch_aarch64_33rx(unsigned char *location, uint64_t value) -{ - uint32_t *loc32 = (uint32_t *)location; - // Try to relax the pair of GOT loads into an immediate value: - assert(IS_AARCH64_ADRP(*loc32)); - unsigned char reg = get_bits(loc32[0], 0, 5); - assert(IS_AARCH64_LDR_OR_STR(loc32[1])); - // There should be only one register involved: - assert(reg == get_bits(loc32[1], 0, 5)); // ldr's output register. - assert(reg == get_bits(loc32[1], 5, 5)); // ldr's input register. - uint64_t relaxed = *(uint64_t *)value; - if (relaxed < (1UL << 16)) { - // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; nop - loc32[0] = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; - loc32[1] = 0xD503201F; - return; - } - if (relaxed < (1ULL << 32)) { - // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; movk reg, YYY - loc32[0] = 0xD2800000 | (get_bits(relaxed, 0, 16) << 5) | reg; - loc32[1] = 0xF2A00000 | (get_bits(relaxed, 16, 16) << 5) | reg; - return; - } - int64_t page_delta = (relaxed >> 12) - ((uintptr_t)location >> 12); - if (page_delta >= -(1L << 20) && - page_delta < (1L << 20)) - { - // adrp reg, AAA; ldr reg, [reg + BBB] -> adrp reg, AAA; add reg, reg, BBB - patch_aarch64_21rx(location, relaxed); - loc32[1] = 0x91000000 | get_bits(relaxed, 0, 12) << 10 | reg << 5 | reg; - return; - } - relaxed = value - (uintptr_t)location; - if ((relaxed & 0x3) == 0 && - (int64_t)relaxed >= -(1L << 19) && - (int64_t)relaxed < (1L << 19)) - { - // adrp reg, AAA; ldr reg, [reg + BBB] -> ldr reg, XXX; nop - loc32[0] = 0x58000000 | (get_bits(relaxed, 2, 19) << 5) | reg; - loc32[1] = 0xD503201F; - return; - } - // Couldn't do it. Just patch the two instructions normally: - patch_aarch64_21rx(location, value); - patch_aarch64_12x(location + 4, value); -} - // Relaxable 32-bit relative address. void patch_x86_64_32rx(unsigned char *location, uint64_t value) diff --git a/Tools/jit/_stencils.py b/Tools/jit/_stencils.py index 258de8ab313..55a4aece542 100644 --- a/Tools/jit/_stencils.py +++ b/Tools/jit/_stencils.py @@ -57,8 +57,8 @@ class HoleValue(enum.Enum): _PATCH_FUNCS = { # aarch64-apple-darwin: "ARM64_RELOC_BRANCH26": "patch_aarch64_26r", - "ARM64_RELOC_GOT_LOAD_PAGE21": "patch_aarch64_21rx", - "ARM64_RELOC_GOT_LOAD_PAGEOFF12": "patch_aarch64_12x", + "ARM64_RELOC_GOT_LOAD_PAGE21": "patch_aarch64_21r", + "ARM64_RELOC_GOT_LOAD_PAGEOFF12": "patch_aarch64_12", "ARM64_RELOC_PAGE21": "patch_aarch64_21r", "ARM64_RELOC_PAGEOFF12": "patch_aarch64_12", "ARM64_RELOC_UNSIGNED": "patch_64", @@ -70,21 +70,21 @@ class HoleValue(enum.Enum): # aarch64-pc-windows-msvc: "IMAGE_REL_ARM64_BRANCH19": "patch_aarch64_19r", "IMAGE_REL_ARM64_BRANCH26": "patch_aarch64_26r", - "IMAGE_REL_ARM64_PAGEBASE_REL21": "patch_aarch64_21rx", + "IMAGE_REL_ARM64_PAGEBASE_REL21": "patch_aarch64_21r", "IMAGE_REL_ARM64_PAGEOFFSET_12A": "patch_aarch64_12", - "IMAGE_REL_ARM64_PAGEOFFSET_12L": "patch_aarch64_12x", + "IMAGE_REL_ARM64_PAGEOFFSET_12L": "patch_aarch64_12", # i686-pc-windows-msvc: "IMAGE_REL_I386_DIR32": "patch_32", "IMAGE_REL_I386_REL32": "patch_x86_64_32rx", # aarch64-unknown-linux-gnu: "R_AARCH64_ABS64": "patch_64", "R_AARCH64_ADD_ABS_LO12_NC": "patch_aarch64_12", - "R_AARCH64_ADR_GOT_PAGE": "patch_aarch64_21rx", + "R_AARCH64_ADR_GOT_PAGE": "patch_aarch64_21r", "R_AARCH64_ADR_PREL_PG_HI21": "patch_aarch64_21r", "R_AARCH64_CALL26": "patch_aarch64_26r", "R_AARCH64_CONDBR19": "patch_aarch64_19r", "R_AARCH64_JUMP26": "patch_aarch64_26r", - "R_AARCH64_LD64_GOT_LO12_NC": "patch_aarch64_12x", + "R_AARCH64_LD64_GOT_LO12_NC": "patch_aarch64_12", "R_AARCH64_MOVW_UABS_G0_NC": "patch_aarch64_16a", "R_AARCH64_MOVW_UABS_G1_NC": "patch_aarch64_16b", "R_AARCH64_MOVW_UABS_G2_NC": "patch_aarch64_16c", @@ -171,34 +171,6 @@ class Hole: def __post_init__(self) -> None: self.func = _PATCH_FUNCS[self.kind] - def fold(self, other: typing.Self, body: bytearray) -> typing.Self | None: - """Combine two holes into a single hole, if possible.""" - instruction_a = int.from_bytes( - body[self.offset : self.offset + 4], byteorder=sys.byteorder - ) - instruction_b = int.from_bytes( - body[other.offset : other.offset + 4], byteorder=sys.byteorder - ) - reg_a = instruction_a & 0b11111 - reg_b1 = instruction_b & 0b11111 - reg_b2 = (instruction_b >> 5) & 0b11111 - - if ( - self.offset + 4 == other.offset - and self.value == other.value - and self.symbol == other.symbol - and self.addend == other.addend - and self.func == "patch_aarch64_21rx" - and other.func == "patch_aarch64_12x" - and reg_a == reg_b1 == reg_b2 - ): - # These can *only* be properly relaxed when they appear together and - # patch the same value: - folded = self.replace() - folded.func = "patch_aarch64_33rx" - return folded - return None - def as_c(self, where: str) -> str: """Dump this hole as a call to a patch_* function.""" if self.custom_location: diff --git a/Tools/jit/_writer.py b/Tools/jit/_writer.py index 5fd9a2ee2d6..20209450d0d 100644 --- a/Tools/jit/_writer.py +++ b/Tools/jit/_writer.py @@ -1,6 +1,5 @@ """Utilities for writing StencilGroups out to a C header file.""" -import itertools import typing import math @@ -61,15 +60,8 @@ def _dump_stencil(opname: str, group: _stencils.StencilGroup) -> typing.Iterator for part, stencil in [("data", group.data), ("code", group.code)]: if stencil.body.rstrip(b"\x00"): yield f" memcpy({part}, {part}_body, sizeof({part}_body));" - skip = False stencil.holes.sort(key=lambda hole: hole.offset) - for hole, pair in itertools.zip_longest(stencil.holes, stencil.holes[1:]): - if skip: - skip = False - continue - if pair and (folded := hole.fold(pair, stencil.body)): - skip = True - hole = folded + for hole in stencil.holes: yield f" {hole.as_c(part)}" yield "}" yield "" From 5e9d90b615b94469081b39a7b0808fea86c417be Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Mon, 6 Apr 2026 22:41:02 -0700 Subject: [PATCH 441/775] gh-144503: Pass sys.argv to forkserver as real argv elements (GH-148194) Avoid embedding the parent's sys.argv into the forkserver -c command string via repr(). When sys.argv is large (e.g. thousands of file paths from a pre-commit hook), the resulting single argument could exceed the OS per-argument length limit (MAX_ARG_STRLEN on Linux, typically 128 KiB), causing posix_spawn to fail and the parent to observe a BrokenPipeError. Instead, append the argv entries as separate command-line arguments after -c; the forkserver child reads them back as sys.argv[1:]. This cannot exceed any limit the parent itself did not already satisfy. Regression introduced by gh-143706 / 298d5440eb8. --- Lib/multiprocessing/forkserver.py | 15 +++- Lib/test/_test_multiprocessing.py | 71 ++++++++++++++++++- Lib/test/mp_preload_large_sysargv.py | 30 ++++++++ ...-04-07-01-04-00.gh-issue-144503.argvfs.rst | 6 ++ 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 Lib/test/mp_preload_large_sysargv.py create mode 100644 Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst diff --git a/Lib/multiprocessing/forkserver.py b/Lib/multiprocessing/forkserver.py index d89b24ac59b..b204a3ad0f1 100644 --- a/Lib/multiprocessing/forkserver.py +++ b/Lib/multiprocessing/forkserver.py @@ -162,10 +162,17 @@ def ensure_running(self): self._forkserver_alive_fd = None self._forkserver_pid = None - cmd = ('from multiprocessing.forkserver import main; ' + - 'main(%d, %d, %r, **%r)') + # gh-144503: sys_argv is passed as real argv elements after the + # ``-c cmd`` rather than repr'd into main_kws so that a large + # parent sys.argv cannot push the single ``-c`` command string + # over the OS per-argument length limit (MAX_ARG_STRLEN on Linux). + # The child sees them as sys.argv[1:]. + cmd = ('import sys; ' + 'from multiprocessing.forkserver import main; ' + 'main(%d, %d, %r, sys_argv=sys.argv[1:], **%r)') main_kws = {} + sys_argv = None if self._preload_modules: data = spawn.get_preparation_data('ignore') if 'sys_path' in data: @@ -173,7 +180,7 @@ def ensure_running(self): if 'init_main_from_path' in data: main_kws['main_path'] = data['init_main_from_path'] if 'sys_argv' in data: - main_kws['sys_argv'] = data['sys_argv'] + sys_argv = data['sys_argv'] if self._preload_on_error != 'ignore': main_kws['on_error'] = self._preload_on_error @@ -197,6 +204,8 @@ def ensure_running(self): exe = spawn.get_executable() args = [exe] + util._args_from_interpreter_flags() args += ['-c', cmd] + if sys_argv is not None: + args += sys_argv pid = util.spawnv_passfds(exe, args, fds_to_pass) except: os.close(alive_w) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 490c7ae5e80..69174cff699 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -207,10 +207,38 @@ def spawn_check_wrapper(*args, **kwargs): return decorator +def only_run_in_forkserver_testsuite(reason): + """Returns a decorator: raises SkipTest unless fork is supported + and the current start method is forkserver. + + Combines @support.requires_fork() with the single-run semantics of + only_run_in_spawn_testsuite(), but uses the forkserver testsuite as + the single-run target. Appropriate for tests that exercise + os.fork() directly (raw fork or mp.set_start_method("fork") in a + subprocess) and don't vary by start method, since forkserver is + only available on platforms that support fork. + """ + + def decorator(test_item): + + @functools.wraps(test_item) + def forkserver_check_wrapper(*args, **kwargs): + if not support.has_fork_support: + raise unittest.SkipTest("requires working os.fork()") + if (start_method := multiprocessing.get_start_method()) != "forkserver": + raise unittest.SkipTest( + f"{start_method=}, not 'forkserver'; {reason}") + return test_item(*args, **kwargs) + + return forkserver_check_wrapper + + return decorator + + class TestInternalDecorators(unittest.TestCase): """Logic within a test suite that could errantly skip tests? Test it!""" - @unittest.skipIf(sys.platform == "win32", "test requires that fork exists.") + @support.requires_fork() def test_only_run_in_spawn_testsuite(self): if multiprocessing.get_start_method() != "spawn": raise unittest.SkipTest("only run in test_multiprocessing_spawn.") @@ -234,6 +262,30 @@ def return_four_if_spawn(): finally: multiprocessing.set_start_method(orig_start_method, force=True) + @support.requires_fork() + def test_only_run_in_forkserver_testsuite(self): + if multiprocessing.get_start_method() != "forkserver": + raise unittest.SkipTest("only run in test_multiprocessing_forkserver.") + + try: + @only_run_in_forkserver_testsuite("testing this decorator") + def return_four_if_forkserver(): + return 4 + except Exception as err: + self.fail(f"expected decorated `def` not to raise; caught {err}") + + orig_start_method = multiprocessing.get_start_method(allow_none=True) + try: + multiprocessing.set_start_method("forkserver", force=True) + self.assertEqual(return_four_if_forkserver(), 4) + multiprocessing.set_start_method("spawn", force=True) + with self.assertRaises(unittest.SkipTest) as ctx: + return_four_if_forkserver() + self.assertIn("testing this decorator", str(ctx.exception)) + self.assertIn("start_method=", str(ctx.exception)) + finally: + multiprocessing.set_start_method(orig_start_method, force=True) + # # Creates a wrapper for a function which records the time it takes to finish @@ -7133,6 +7185,23 @@ def test_preload_main_sys_argv(self): '', ]) + @only_run_in_forkserver_testsuite("forkserver specific test.") + def test_preload_main_large_sys_argv(self): + # gh-144503: a very large parent sys.argv must not prevent the + # forkserver from starting (it previously overflowed the OS + # per-argument length limit when repr'd into the -c command string). + name = os.path.join(os.path.dirname(__file__), + 'mp_preload_large_sysargv.py') + _, out, err = test.support.script_helper.assert_python_ok(name) + self.assertEqual(err, b'') + + out = out.decode().split("\n") + self.assertEqual(out, [ + 'preload:5002:sentinel', + 'worker:5002:sentinel', + '', + ]) + # # Mixins # diff --git a/Lib/test/mp_preload_large_sysargv.py b/Lib/test/mp_preload_large_sysargv.py new file mode 100644 index 00000000000..790fcd76ead --- /dev/null +++ b/Lib/test/mp_preload_large_sysargv.py @@ -0,0 +1,30 @@ +# gh-144503: Test that the forkserver can start when the parent process has +# a very large sys.argv. Prior to the fix, sys.argv was repr'd into the +# forkserver ``-c`` command string which could exceed the OS limit on the +# length of a single argv element (MAX_ARG_STRLEN on Linux, ~128 KiB), +# causing posix_spawn to fail and the parent to see a BrokenPipeError. + +import multiprocessing +import sys + +EXPECTED_LEN = 5002 # argv[0] + 5000 padding entries + sentinel + + +def fun(): + print(f"worker:{len(sys.argv)}:{sys.argv[-1]}") + + +if __name__ == "__main__": + # Inflate sys.argv well past 128 KiB before the forkserver is started. + sys.argv[1:] = ["x" * 50] * 5000 + ["sentinel"] + assert len(sys.argv) == EXPECTED_LEN + + ctx = multiprocessing.get_context("forkserver") + p = ctx.Process(target=fun) + p.start() + p.join() + sys.exit(p.exitcode) +else: + # This branch runs when the forkserver preloads this module as + # __mp_main__; confirm the large argv was propagated intact. + print(f"preload:{len(sys.argv)}:{sys.argv[-1]}") diff --git a/Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst b/Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst new file mode 100644 index 00000000000..fc73d1902ea --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst @@ -0,0 +1,6 @@ +Fix a regression introduced in 3.14.3 and 3.13.12 where the +:mod:`multiprocessing` ``forkserver`` start method would fail with +:exc:`BrokenPipeError` when the parent process had a very large +:data:`sys.argv`. The argv is now passed to the forkserver as separate +command-line arguments rather than being embedded in the ``-c`` command +string, avoiding the operating system's per-argument length limit. From fbc1a5b0761f4331c7070201fefd5b5deb75ebdd Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 7 Apr 2026 09:06:17 +0200 Subject: [PATCH 442/775] gh-146636: abi3t: Define Py_GIL_DISABLED but do not use it (GH-148142) When compiling for abi3t, define Py_GIL_DISABLED, so that users who check it to enable additional locking aren't broken. But also avoid using Py_GIL_DISABLED in Python headers themselves -- abi3 and abi3t ought to be the same except the _Py_OPAQUE_PYOBJECT differences. A check for this is coming in a later PR. It will require rewriting some preprocessor conditions, some of these changes are included in this PR. For _Py_IsOwnedByCurrentThread & supporting functions I opted to move them to a cpython/ header, as they're rather self-contained. --- Include/cpython/object.h | 79 +++++++++++++++++++++++++++++++++++++ Include/moduleobject.h | 4 +- Include/object.h | 85 ++-------------------------------------- Include/pyport.h | 8 ++++ Include/refcount.h | 35 ++++++++++------- 5 files changed, 115 insertions(+), 96 deletions(-) diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 61cdb93d1d5..acee45fc31b 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -495,3 +495,82 @@ PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(PyObject *); PyAPI_FUNC(int) PyUnstable_Object_IsUniquelyReferenced(PyObject *); PyAPI_FUNC(int) PyUnstable_SetImmortal(PyObject *op); + +#if defined(Py_GIL_DISABLED) +PyAPI_FUNC(uintptr_t) _Py_GetThreadLocal_Addr(void); + +static inline uintptr_t +_Py_ThreadId(void) +{ + uintptr_t tid; +#if defined(_MSC_VER) && defined(_M_X64) + tid = __readgsqword(48); +#elif defined(_MSC_VER) && defined(_M_IX86) + tid = __readfsdword(24); +#elif defined(_MSC_VER) && defined(_M_ARM64) + tid = __getReg(18); +#elif defined(__MINGW32__) && defined(_M_X64) + tid = __readgsqword(48); +#elif defined(__MINGW32__) && defined(_M_IX86) + tid = __readfsdword(24); +#elif defined(__MINGW32__) && defined(_M_ARM64) + tid = __getReg(18); +#elif defined(__i386__) + __asm__("{movl %%gs:0, %0|mov %0, dword ptr gs:[0]}" : "=r" (tid)); // 32-bit always uses GS +#elif defined(__MACH__) && defined(__x86_64__) + __asm__("{movq %%gs:0, %0|mov %0, qword ptr gs:[0]}" : "=r" (tid)); // x86_64 macOSX uses GS +#elif defined(__x86_64__) + __asm__("{movq %%fs:0, %0|mov %0, qword ptr fs:[0]}" : "=r" (tid)); // x86_64 Linux, BSD uses FS +#elif defined(__arm__) && __ARM_ARCH >= 7 + __asm__ ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tid)); +#elif defined(__aarch64__) && defined(__APPLE__) + __asm__ ("mrs %0, tpidrro_el0" : "=r" (tid)); +#elif defined(__aarch64__) + __asm__ ("mrs %0, tpidr_el0" : "=r" (tid)); +#elif defined(__powerpc64__) + #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) + tid = (uintptr_t)__builtin_thread_pointer(); + #else + // r13 is reserved for use as system thread ID by the Power 64-bit ABI. + register uintptr_t tp __asm__ ("r13"); + __asm__("" : "=r" (tp)); + tid = tp; + #endif +#elif defined(__powerpc__) + #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) + tid = (uintptr_t)__builtin_thread_pointer(); + #else + // r2 is reserved for use as system thread ID by the Power 32-bit ABI. + register uintptr_t tp __asm__ ("r2"); + __asm__ ("" : "=r" (tp)); + tid = tp; + #endif +#elif defined(__s390__) && defined(__GNUC__) + // Both GCC and Clang have supported __builtin_thread_pointer + // for s390 from long time ago. + tid = (uintptr_t)__builtin_thread_pointer(); +#elif defined(__riscv) + #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) + tid = (uintptr_t)__builtin_thread_pointer(); + #else + // tp is Thread Pointer provided by the RISC-V ABI. + __asm__ ("mv %0, tp" : "=r" (tid)); + #endif +#else + // Fallback to a portable implementation if we do not have a faster + // platform-specific implementation. + tid = _Py_GetThreadLocal_Addr(); +#endif + return tid; +} + +static inline Py_ALWAYS_INLINE int +_Py_IsOwnedByCurrentThread(PyObject *ob) +{ +#ifdef _Py_THREAD_SANITIZER + return _Py_atomic_load_uintptr_relaxed(&ob->ob_tid) == _Py_ThreadId(); +#else + return ob->ob_tid == _Py_ThreadId(); +#endif +} +#endif diff --git a/Include/moduleobject.h b/Include/moduleobject.h index d1dde7982ad..90462f183ac 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -113,8 +113,10 @@ struct PyModuleDef_Slot { # define Py_MOD_GIL_NOT_USED ((void *)1) #endif -#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) +#if !defined(Py_LIMITED_API) +# if defined(Py_GIL_DISABLED) PyAPI_FUNC(int) PyUnstable_Module_SetGIL(PyObject *module, void *gil); +# endif #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= _Py_PACK_VERSION(3, 15) diff --git a/Include/object.h b/Include/object.h index 10d9d76d934..cfa9d6cdece 100644 --- a/Include/object.h +++ b/Include/object.h @@ -186,85 +186,6 @@ typedef struct PyVarObject PyVarObject; PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y); #define Py_Is(x, y) ((x) == (y)) -#if defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API) -PyAPI_FUNC(uintptr_t) _Py_GetThreadLocal_Addr(void); - -static inline uintptr_t -_Py_ThreadId(void) -{ - uintptr_t tid; -#if defined(_MSC_VER) && defined(_M_X64) - tid = __readgsqword(48); -#elif defined(_MSC_VER) && defined(_M_IX86) - tid = __readfsdword(24); -#elif defined(_MSC_VER) && defined(_M_ARM64) - tid = __getReg(18); -#elif defined(__MINGW32__) && defined(_M_X64) - tid = __readgsqword(48); -#elif defined(__MINGW32__) && defined(_M_IX86) - tid = __readfsdword(24); -#elif defined(__MINGW32__) && defined(_M_ARM64) - tid = __getReg(18); -#elif defined(__i386__) - __asm__("{movl %%gs:0, %0|mov %0, dword ptr gs:[0]}" : "=r" (tid)); // 32-bit always uses GS -#elif defined(__MACH__) && defined(__x86_64__) - __asm__("{movq %%gs:0, %0|mov %0, qword ptr gs:[0]}" : "=r" (tid)); // x86_64 macOSX uses GS -#elif defined(__x86_64__) - __asm__("{movq %%fs:0, %0|mov %0, qword ptr fs:[0]}" : "=r" (tid)); // x86_64 Linux, BSD uses FS -#elif defined(__arm__) && __ARM_ARCH >= 7 - __asm__ ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tid)); -#elif defined(__aarch64__) && defined(__APPLE__) - __asm__ ("mrs %0, tpidrro_el0" : "=r" (tid)); -#elif defined(__aarch64__) - __asm__ ("mrs %0, tpidr_el0" : "=r" (tid)); -#elif defined(__powerpc64__) - #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) - tid = (uintptr_t)__builtin_thread_pointer(); - #else - // r13 is reserved for use as system thread ID by the Power 64-bit ABI. - register uintptr_t tp __asm__ ("r13"); - __asm__("" : "=r" (tp)); - tid = tp; - #endif -#elif defined(__powerpc__) - #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) - tid = (uintptr_t)__builtin_thread_pointer(); - #else - // r2 is reserved for use as system thread ID by the Power 32-bit ABI. - register uintptr_t tp __asm__ ("r2"); - __asm__ ("" : "=r" (tp)); - tid = tp; - #endif -#elif defined(__s390__) && defined(__GNUC__) - // Both GCC and Clang have supported __builtin_thread_pointer - // for s390 from long time ago. - tid = (uintptr_t)__builtin_thread_pointer(); -#elif defined(__riscv) - #if defined(__clang__) && _Py__has_builtin(__builtin_thread_pointer) - tid = (uintptr_t)__builtin_thread_pointer(); - #else - // tp is Thread Pointer provided by the RISC-V ABI. - __asm__ ("mv %0, tp" : "=r" (tid)); - #endif -#else - // Fallback to a portable implementation if we do not have a faster - // platform-specific implementation. - tid = _Py_GetThreadLocal_Addr(); -#endif - return tid; -} - -static inline Py_ALWAYS_INLINE int -_Py_IsOwnedByCurrentThread(PyObject *ob) -{ -#ifdef _Py_THREAD_SANITIZER - return _Py_atomic_load_uintptr_relaxed(&ob->ob_tid) == _Py_ThreadId(); -#else - return ob->ob_tid == _Py_ThreadId(); -#endif -} -#endif - PyAPI_DATA(PyTypeObject) PyLong_Type; PyAPI_DATA(PyTypeObject) PyBool_Type; @@ -652,8 +573,10 @@ given type object has a specified feature. #define _Py_IMMORTAL_FLAGS (1 << 0) #define _Py_LEGACY_ABI_CHECK_FLAG (1 << 1) /* see PyModuleDef_Init() */ #define _Py_STATICALLY_ALLOCATED_FLAG (1 << 2) -#if defined(Py_GIL_DISABLED) && defined(Py_DEBUG) -#define _Py_TYPE_REVEALED_FLAG (1 << 3) +#if !defined(Py_LIMITED_API) +# if defined(Py_GIL_DISABLED) && defined(Py_DEBUG) +# define _Py_TYPE_REVEALED_FLAG (1 << 3) +# endif #endif #define Py_CONSTANT_NONE 0 diff --git a/Include/pyport.h b/Include/pyport.h index f7bb5d513b9..62cba4c1421 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -77,6 +77,14 @@ # define Py_BUILD_CORE #endif +#if defined(Py_TARGET_ABI3T) +# if !defined(Py_GIL_DISABLED) +// Define Py_GIL_DISABLED for users' needs. This macro is used to enable +// locking needed in for free-threaded interpreters builds. +# define Py_GIL_DISABLED +# endif +#endif + /************************************************************************** Symbols and macros to supply platform-independent interfaces to basic diff --git a/Include/refcount.h b/Include/refcount.h index bcdabad3dcb..80fe7ff70a1 100644 --- a/Include/refcount.h +++ b/Include/refcount.h @@ -5,6 +5,7 @@ extern "C" { #endif +#if !defined(_Py_OPAQUE_PYOBJECT) /* Immortalization: @@ -90,14 +91,16 @@ check by comparing the reference count field to the minimum immortality refcount # define _Py_REF_SHARED(refcnt, flags) \ (((refcnt) << _Py_REF_SHARED_SHIFT) + (flags)) #endif // Py_GIL_DISABLED - +#endif // _Py_OPAQUE_PYOBJECT // Py_REFCNT() implementation for the stable ABI PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob); #if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030e0000 // Stable ABI implements Py_REFCNT() as a function call - // on limited C API version 3.14 and newer. + // on limited C API version 3.14 and newer, and on abi3t. +#elif defined(_Py_OPAQUE_PYOBJECT) + // Py_REFCNT() is also a function call in abi3t. #else static inline Py_ssize_t _Py_REFCNT(PyObject *ob) { #if !defined(Py_GIL_DISABLED) @@ -150,9 +153,10 @@ PyAPI_FUNC(void) _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt); static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { assert(refcnt >= 0); -#if defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000 +#if (defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030d0000) \ + || defined(_Py_OPAQUE_PYOBJECT) // Stable ABI implements Py_SET_REFCNT() as a function call - // on limited C API version 3.13 and newer. + // on limited C API version 3.13 and newer, and abi3t. _Py_SetRefcnt(ob, refcnt); #else // This immortal check is for code that is unaware of immortal objects. @@ -191,7 +195,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_ref_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED); } #endif // Py_GIL_DISABLED -#endif // Py_LIMITED_API+0 < 0x030d0000 +#endif // Py_LIMITED_API } #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 # define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt)) @@ -250,10 +254,11 @@ PyAPI_FUNC(void) _Py_DecRef(PyObject *); static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op) { -#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG)) +#if (defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))) \ + || defined(_Py_OPAQUE_PYOBJECT) // Stable ABI implements Py_INCREF() as a function call on limited C API - // version 3.12 and newer, and on Python built in debug mode. _Py_IncRef() - // was added to Python 3.10.0a7, use Py_IncRef() on older Python versions. + // version 3.12 and newer, abi3t, and on Python built in debug mode. + // _Py_IncRef() was added to Python 3.10.0a7, use Py_IncRef() on older versions. // Py_IncRef() accepts NULL whereas _Py_IncRef() doesn't. # if Py_LIMITED_API+0 >= 0x030a00A7 _Py_IncRef(op); @@ -305,8 +310,8 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op) # define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op)) #endif - -#if !defined(Py_LIMITED_API) && defined(Py_GIL_DISABLED) +#if !defined(Py_LIMITED_API) +#if defined(Py_GIL_DISABLED) // Implements Py_DECREF on objects not owned by the current thread. PyAPI_FUNC(void) _Py_DecRefShared(PyObject *); PyAPI_FUNC(void) _Py_DecRefSharedDebug(PyObject *, const char *, int); @@ -316,12 +321,14 @@ PyAPI_FUNC(void) _Py_DecRefSharedDebug(PyObject *, const char *, int); // zero. Otherwise, the thread gives up ownership and merges the reference // count fields. PyAPI_FUNC(void) _Py_MergeZeroLocalRefcount(PyObject *); -#endif +#endif // Py_GIL_DISABLED +#endif // Py_LIMITED_API -#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG)) +#if (defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))) \ + || defined(_Py_OPAQUE_PYOBJECT) // Stable ABI implements Py_DECREF() as a function call on limited C API -// version 3.12 and newer, and on Python built in debug mode. _Py_DecRef() was -// added to Python 3.10.0a7, use Py_DecRef() on older Python versions. +// version 3.12 and newer, abi3t, and on Python built in debug mode. +// _Py_DecRef() was added to Python 3.10.0a7, use Py_DecRef() on older versions. // Py_DecRef() accepts NULL whereas _Py_DecRef() doesn't. static inline void Py_DECREF(PyObject *op) { # if Py_LIMITED_API+0 >= 0x030a00A7 From 63d3c490d4ebb38104dd5b42ab3117c35ee9c743 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 7 Apr 2026 08:44:03 +0100 Subject: [PATCH 443/775] gh-101178: Fix UB in `binascii.b2a_ascii85` (#148166) --- Modules/binascii.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/binascii.c b/Modules/binascii.c index 9193137877a..b80bfbfffe4 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -1240,7 +1240,7 @@ binascii_b2a_ascii85_impl(PyObject *module, Py_buffer *data, int foldspaces, /* Encode all full-length chunks. */ for (; bin_len >= 4; bin_len -= 4, bin_data += 4) { - uint32_t leftchar = (bin_data[0] << 24) | (bin_data[1] << 16) | + uint32_t leftchar = ((uint32_t)bin_data[0] << 24) | (bin_data[1] << 16) | (bin_data[2] << 8) | bin_data[3]; if (leftchar == BASE85_A85_Z) { *ascii_data++ = 'z'; @@ -1481,7 +1481,7 @@ binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad, /* Encode all full-length chunks. */ for (; bin_len >= 4; bin_len -= 4, bin_data += 4) { - uint32_t leftchar = (bin_data[0] << 24) | (bin_data[1] << 16) | + uint32_t leftchar = ((uint32_t)bin_data[0] << 24) | (bin_data[1] << 16) | (bin_data[2] << 8) | bin_data[3]; ascii_data[4] = table_b2a[leftchar % 85]; From a4d9d6483fba5582a0dd44f600c36b02cdc171f7 Mon Sep 17 00:00:00 2001 From: Chris Eibl <138194463+chris-eibl@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:02:15 +0200 Subject: [PATCH 444/775] GH-145762: Fix test_ci_fuzz_stdlib for source archive builds (#145778) Co-authored-by: Stan Ulbrych Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Lib/test/test_tools/test_compute_changes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_tools/test_compute_changes.py b/Lib/test/test_tools/test_compute_changes.py index 351fb06a885..eb1ecd447a7 100644 --- a/Lib/test/test_tools/test_compute_changes.py +++ b/Lib/test/test_tools/test_compute_changes.py @@ -55,7 +55,7 @@ def test_ci_fuzz_stdlib(self): elif p.is_file(): f = p else: - self.fail(f"LIBRARY_FUZZER_PATHS contains an invalid entry: {p!r}") + continue result = process_changed_files({f}) self.assertTrue(result.run_ci_fuzz_stdlib) self.assertTrue(is_fuzzable_library_file(f)) From cf59bf76470f3d75ad47d80ffb8ce76b64b5e943 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 7 Apr 2026 11:39:50 +0200 Subject: [PATCH 445/775] gh-146121: Clarify security model of pkgutil.getdata; revert checks (GH-148197) This reverts commit bcdf231946b1da8bdfbab4c05539bb0cc964a1c7, and clarifies get_data's security model. Co-authored-by: Stan Ulbrych --- Doc/library/pkgutil.rst | 28 +++++++++++++++++-- Lib/pkgutil.py | 3 -- Lib/test/test_pkgutil.py | 19 ------------- ...-03-16-18-07-00.gh-issue-146121.vRbdro.rst | 3 -- 4 files changed, 26 insertions(+), 27 deletions(-) delete mode 100644 Misc/NEWS.d/next/Security/2026-03-16-18-07-00.gh-issue-146121.vRbdro.rst diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst index 47d24b6f7d0..aa7dd71c132 100644 --- a/Doc/library/pkgutil.rst +++ b/Doc/library/pkgutil.rst @@ -151,24 +151,48 @@ support. :meth:`get_data ` API. The *package* argument should be the name of a package, in standard module format (``foo.bar``). The *resource* argument should be in the form of a relative - filename, using ``/`` as the path separator. The parent directory name - ``..`` is not allowed, and nor is a rooted name (starting with a ``/``). + filename, using ``/`` as the path separator. The function returns a binary string that is the contents of the specified resource. + This function uses the :term:`loader` method + :func:`~importlib.abc.FileLoader.get_data` + to support modules installed in the filesystem, but also in zip files, + databases, or elsewhere. + For packages located in the filesystem, which have already been imported, this is the rough equivalent of:: d = os.path.dirname(sys.modules[package].__file__) data = open(os.path.join(d, resource), 'rb').read() + Like the :func:`open` function, :func:`!get_data` can follow parent + directories (``../``) and absolute paths (starting with ``/`` or ``C:/``, + for example). + It can open compilation/installation artifacts like ``.py`` and ``.pyc`` + files or files with :func:`reserved filenames `. + To be compatible with non-filesystem loaders, avoid using these features. + + .. warning:: + + This function is intended for trusted input. + It does not verify that *resource* "belongs" to *package*. + + If you use a user-provided *resource* path, consider verifying it. + For example, require an alphanumeric filename with a known extension, or + install and check a list of known resources. + If the package cannot be located or loaded, or it uses a :term:`loader` which does not support :meth:`get_data `, then ``None`` is returned. In particular, the :term:`loader` for :term:`namespace packages ` does not support :meth:`get_data `. + .. seealso:: + + The :mod:`importlib.resources` module provides structured access to + module resources. .. function:: resolve_name(name) diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index c3109a3a4cd..8772a66791a 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -393,9 +393,6 @@ def get_data(package, resource): # signature - an os.path format "filename" starting with the dirname of # the package's __file__ parts = resource.split('/') - if os.path.isabs(resource) or '..' in parts: - raise ValueError("resource must be a relative path with no " - "parent directory components") parts.insert(0, os.path.dirname(mod.__file__)) resource_name = os.path.join(*parts) return loader.get_data(resource_name) diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 948afb8c18c..d4faaaeca00 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -61,25 +61,6 @@ def test_getdata_filesys(self): del sys.modules[pkg] - def test_getdata_path_traversal(self): - pkg = 'test_getdata_traversal' - - # Make a package with some resources - package_dir = os.path.join(self.dirname, pkg) - os.mkdir(package_dir) - # Empty init.py - f = open(os.path.join(package_dir, '__init__.py'), "wb") - f.close() - - with self.assertRaises(ValueError): - pkgutil.get_data(pkg, '../../../etc/passwd') - with self.assertRaises(ValueError): - pkgutil.get_data(pkg, 'sub/../../../etc/passwd') - with self.assertRaises(ValueError): - pkgutil.get_data(pkg, os.path.abspath('/etc/passwd')) - - del sys.modules[pkg] - def test_getdata_zipfile(self): zip = 'test_getdata_zipfile.zip' pkg = 'test_getdata_zipfile' diff --git a/Misc/NEWS.d/next/Security/2026-03-16-18-07-00.gh-issue-146121.vRbdro.rst b/Misc/NEWS.d/next/Security/2026-03-16-18-07-00.gh-issue-146121.vRbdro.rst deleted file mode 100644 index c0ee07dcf60..00000000000 --- a/Misc/NEWS.d/next/Security/2026-03-16-18-07-00.gh-issue-146121.vRbdro.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`pkgutil.get_data` now raises rejects *resource* arguments containing the -parent directory components or that is an absolute path. -This addresses :cve:`2026-3479`. From 55ea59e7dc35e1363b203ae4dd9cfc3a0ac0a844 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 7 Apr 2026 14:20:51 +0300 Subject: [PATCH 446/775] Python 3.15.0a8 --- Doc/c-api/dict.rst | 28 +- Doc/c-api/intro.rst | 16 +- Doc/c-api/stable.rst | 2 +- Doc/library/array.rst | 2 +- Doc/library/base64.rst | 24 +- Doc/library/binascii.rst | 26 +- Doc/library/ctypes.rst | 2 +- Doc/library/getpass.rst | 2 +- Doc/library/json.rst | 4 +- Doc/library/pprint.rst | 2 +- Doc/library/select.rst | 2 +- Doc/library/stdtypes.rst | 2 +- Doc/library/timeit.rst | 4 +- Doc/library/wave.rst | 2 +- Doc/library/xml.etree.elementtree.rst | 4 +- Doc/using/configure.rst | 2 +- Include/patchlevel.h | 4 +- Lib/pydoc_data/module_docs.py | 2 +- Lib/pydoc_data/topics.py | 147 +- Misc/NEWS.d/3.15.0a8.rst | 1593 +++++++++++++++++ ...6-01-08-22-27-07.gh-issue-85277.TotySi.rst | 1 - ...-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst | 3 - ...-03-10-16-58-55.gh-issue-138850.CkqTw6.rst | 1 - ...-03-11-11-58-42.gh-issue-145801.iCXa3v.rst | 4 - ...-03-12-12-30-24.gh-issue-145844.VOPeCU.rst | 1 - ...-03-23-20-06-35.gh-issue-146210.C01Rmq.rst | 2 - ...-03-26-12-27-42.gh-issue-146444.JKJuEa.rst | 1 - ...-03-26-12-48-42.gh-issue-146446.0GyMu4.rst | 2 - ...-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst | 2 - ...-03-27-06-55-10.gh-issue-146498.uOiCab.rst | 3 - ...-03-28-02-48-51.gh-issue-146541.k-zlM6.rst | 1 - ...-02-19-18-39-11.gh-issue-145010.mKzjci.rst | 2 - ...-03-18-20-18-59.gh-issue-146056.nnZIgp.rst | 1 - ...-03-18-23-44-29.gh-issue-146143.pwIrJq.rst | 2 - ...-03-19-16-50-27.gh-issue-146175.pISQGX.rst | 12 - ...-03-31-13-33-41.gh-issue-146636.5do3wt.rst | 3 - ...-11-01-01-49-52.gh-issue-140870.iknc12.rst | 2 - ...-11-02-16-23-17.gh-issue-140594.YIWUpl.rst | 2 - ...-01-07-23-07-17.gh-issue-126910.d8zdm-.rst | 2 - ...-01-10-12-59-58.gh-issue-143636.dzr26e.rst | 2 - ...-01-31-15-15-43.gh-issue-143414.Jgl4xu.rst | 1 - ...-02-08-01-19-50.gh-issue-131798.PaWDNH.rst | 1 - ...6-02-14-13-07-08.gh-issue-69605.4aL4hn.rst | 1 - ...-02-14-15-51-16.gh-issue-134584.6WFSuB.rst | 1 - ...-02-28-18-42-36.gh-issue-145036.70Kbfz.rst | 1 - ...3-09-00-00-00.gh-issue-145713.KR6azvzI.rst | 3 - ...-03-10-12-52-06.gh-issue-145685.80B7gK.rst | 2 - ...-03-10-19-00-39.gh-issue-145783.dS5TM9.rst | 2 - ...10-22-38-40.gh-issue-145779.5375381d80.rst | 2 - ...-03-11-00-13-59.gh-issue-142183.2iVhJH.rst | 1 - ...-03-11-19-09-47.gh-issue-145792.X5KUhc.rst | 2 - ...-03-11-21-27-28.gh-issue-145376.LfDvyw.rst | 1 - ...-03-13-09-48-57.gh-issue-127958.U-znTv.rst | 1 - ...-03-13-12-24-17.gh-issue-145876.LWFO2K.rst | 3 - ...-03-15-20-47-34.gh-issue-145990.14BUzw.rst | 1 - ...-03-15-21-45-35.gh-issue-145990.tmXwRB.rst | 1 - ...-03-17-00-00-00.gh-issue-146041.7799bb.rst | 3 - ...-03-17-14-20-56.gh-issue-145059.aB3xKm.rst | 1 - ...-03-18-18-52-00.gh-issue-146056.r1tVSo.rst | 1 - ...-03-19-01-19-34.gh-issue-146096.R9tkJX.rst | 2 - ...-03-19-16-16-40.gh-issue-135871.jSExZ3.rst | 1 - ...-03-20-00-39-25.gh-issue-146192.8aQ6sC.rst | 2 - ...-03-20-11-34-17.gh-issue-145667._Agp9o.rst | 2 - ...-03-20-12-26-24.gh-issue-146199.vV8V9s.rst | 1 - ...-03-20-12-52-55.gh-issue-146205.M4yKdf.rst | 2 - ...-03-20-13-07-33.gh-issue-146227.MqBPEo.rst | 3 - ...-03-20-13-55-14.gh-issue-146196.Zg70Kb.rst | 2 - ...-03-21-08-11-58.gh-issue-146151.4-lhim.rst | 3 - ...-03-21-08-48-25.gh-issue-146245.cqM3_4.rst | 1 - ...-03-21-11-55-16.gh-issue-146250.ahl3O2.rst | 1 - ...-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst | 3 - ...-03-22-12-00-00.gh-issue-146306.870ef4.rst | 3 - ...-03-22-19-30-00.gh-issue-146308.AxnRVA.rst | 5 - ...-03-24-13-06-52.gh-issue-146369.6wDI6S.rst | 2 - ...-03-26-11-18-45.gh-issue-146388.O0u1c3.rst | 1 - ...-03-27-17-14-18.gh-issue-126910.hooVFQ.rst | 1 - ...-03-29-11-39-05.gh-issue-146587.YJicXt.rst | 1 - ...-03-30-20-00-00.gh-issue-146306.C45609.rst | 3 - ...1-06-35.gh-issue-146615.fix-method-get.rst | 3 - ...-03-31-18-07-53.gh-issue-147856.62Dwee.rst | 1 - ...-04-01-12-35-55.gh-issue-147985.YVirHJ.rst | 3 - ...-04-01-12-52-31.gh-issue-144319.iZk4hs.rst | 3 - ...-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst | 1 - ...-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst | 2 - ...-04-05-00-00-00.gh-issue-148072.xid9Pe.rst | 4 - ...-04-05-15-20-00.gh-issue-148144.f7qA0x.rst | 3 - ...04-06-00-00-00.gh-issue-100239.binopxt.rst | 3 - ...-04-06-11-15-46.gh-issue-148157.JFnZDn.rst | 2 - ...-03-09-00-00-00.gh-issue-145649.8BcbAB.rst | 2 - ...-03-25-00-00-00.gh-issue-126676.052336.rst | 2 - .../2019-04-25-21-11-37.bpo-36461.TO5YyP.rst | 3 - ...3-03-10-13-10-06.gh-issue-60729.KCCHTe.rst | 1 - ...4-09-25-12-47-50.gh-issue-66419.DVSukU.rst | 2 - ...-02-07-00-48-07.gh-issue-112632.95MM0C.rst | 3 - ...-09-19-13-54-54.gh-issue-130472.LODfdk.rst | 1 - ...-10-05-15-38-02.gh-issue-139633.l3P839.rst | 2 - ...-10-11-11-50-59.gh-issue-139933.05MHlx.rst | 3 - ...-10-13-16-43-36.gh-issue-140049.VvmAzN.rst | 1 - ...-11-15-23-14-30.gh-issue-138577.KbShrt.rst | 4 - ...-11-18-06-35-53.gh-issue-141707.DBmQIy.rst | 2 - ...2-18-00-00-00.gh-issue-142763.AJpZPVG5.rst | 2 - ...-01-10-16-23-21.gh-issue-143715.HZrfSA.rst | 3 - ...-02-04-20-30-59.gh-issue-123471.1dnPvs.rst | 1 - ...-02-08-22-04-06.gh-issue-140814.frzSpn.rst | 3 - ...-02-11-21-01-30.gh-issue-144259.OAhOR8.rst | 1 - ...-02-17-03-43-07.gh-issue-140715.twmcM_.rst | 1 - ...-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst | 3 - ...19-12-00-00.gh-issue-144984.b93995c982.rst | 3 - ...-02-19-16-34-18.gh-issue-144270.wJRtSr.rst | 3 - ...-02-23-21-28-12.gh-issue-145035.J5UjS6.rst | 3 - ...-02-26-20-13-16.gh-issue-145264.4pggX_.rst | 4 - ...-03-03-23-21-40.gh-issue-145446.0c-TJX.rst | 1 - ...-03-05-14-13-10.gh-issue-145546.3tnlxx.rst | 2 - ...-03-07-02-44-52.gh-issue-145616.x8Mf23.rst | 1 - ...-03-07-14-34-39.gh-issue-145587.flFQ5-.rst | 1 - ...-03-08-00-00-00.gh-issue-145650.LgRepr.rst | 3 - ...-03-09-00-00-00.gh-issue-145492.457Afc.rst | 3 - ...-03-09-18-33-16.gh-issue-145697.d6hFmm.rst | 1 - ...-03-09-19-59-05.gh-issue-145703.4EEP7J.rst | 3 - ...-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst | 1 - ...-03-10-01-54-34.gh-issue-145719.okJRoK.rst | 1 - ...-03-10-14-13-12.gh-issue-145750.iQsTeX.rst | 3 - ...-03-10-14-57-15.gh-issue-145754.YBL5Ko.rst | 2 - ...-03-10-19-50-59.gh-issue-138122.CsoBEo.rst | 4 - ...-03-11-10-25-32.gh-issue-123720.TauFRx.rst | 5 - ...-03-12-12-17-39.gh-issue-145850.uW3stt.rst | 6 - ...-03-12-21-01-48.gh-issue-145883.lUvXcc.rst | 2 - ...3-15-00-00-00.gh-issue-145966.tCI0uD4I.rst | 2 - ...-03-15-10-17-51.gh-issue-145968.gZexry.rst | 2 - ...-03-15-16-38-48.gh-issue-145980.mRze5H.rst | 5 - ...3-16-00-00-00.gh-issue-146004.xOptProp.rst | 9 - ...-03-17-11-46-20.gh-issue-146054.udYcqn.rst | 2 - ...-03-17-19-30-45.gh-issue-146075.85sCSh.rst | 1 - ...-03-17-19-51-05.gh-issue-123471.oY4UR5.rst | 1 - ...-03-17-20-41-27.gh-issue-146076.yoBNnB.rst | 2 - ...-03-17-20-52-24.gh-issue-146083.NxZa_c.rst | 1 - ...-03-18-16-58-17.gh-issue-146091.lBbo1L.rst | 3 - ...-03-18-23-54-36.gh-issue-145410.NvLWj5.rst | 3 - ...3-20-00-28-00.gh-issue-146171.P5Jk2R7v.rst | 2 - ...-03-20-14-53-00.gh-issue-146228.OJVEDL.rst | 2 - ...-03-20-16-17-31.gh-issue-143387.9Waopa.rst | 7 - ...-03-21-06-21-38.gh-issue-146151.yNpgml.rst | 3 - ...-03-21-08-23-26.gh-issue-140947.owZ4r_.rst | 1 - ...-03-21-10-02-20.gh-issue-146238.2WpMOj.rst | 2 - ...-03-21-16-03-16.gh-issue-141510.tKptA7.rst | 2 - ...-03-24-03-49-50.gh-issue-146310.WhlDir.rst | 2 - ...-03-25-21-08-51.gh-issue-146431.zERPwe.rst | 11 - ...-03-26-02-06-52.gh-issue-146440.HXjhQO.rst | 6 - ...-03-26-11-04-42.gh-issue-145633.RWjlaX.rst | 2 - ...-03-26-14-44-07.gh-issue-145056.L9KPC3.rst | 1 - ...-03-26-14-51-55.gh-issue-145056.QS-6l1.rst | 1 - ...-03-27-12-00-00.gh-issue-146507.1D95A7.rst | 3 - ...-03-28-12-01-48.gh-issue-146090.wh1qJR.rst | 2 - ...-03-28-12-05-34.gh-issue-146090.wf9_ef.rst | 3 - ...-03-28-12-20-19.gh-issue-146556.Y8Eson.rst | 5 - ...-03-28-13-19-20.gh-issue-146080.srN12a.rst | 2 - ...-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst | 4 - ...-04-01-11-05-36.gh-issue-146613.GzjUFK.rst | 2 - ...6-04-01-18-17-55.gh-issue-73613.PLEebm.rst | 7 - ...-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst | 2 - ...-04-07-01-04-00.gh-issue-144503.argvfs.rst | 6 - ...-01-16-12-04-49.gh-issue-143930.zYC5x3.rst | 1 - ...-03-06-17-03-38.gh-issue-145599.kchwZV.rst | 4 - ...-03-14-17-31-39.gh-issue-145986.ifSSr8.rst | 4 - ...-03-24-00-15-58.gh-issue-146202.LgH6Bj.rst | 3 - ...-04-03-21-37-18.gh-issue-144418.PusC0S.rst | 1 - ...-03-15-11-32-35.gh-issue-145976.mqhzmB.rst | 1 - ...-03-15-20-59-29.gh-issue-145976.rEdUI-.rst | 2 - ...-03-22-00-00-00.gh-issue-135953.IptOwg.rst | 3 - ...-10-19-23-44-46.gh-issue-140131.AABF2k.rst | 2 - ...-10-17-01-07-03.gh-issue-137586.kVzxvp.rst | 1 - README.rst | 2 +- 172 files changed, 1755 insertions(+), 482 deletions(-) create mode 100644 Misc/NEWS.d/3.15.0a8.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-10-16-58-55.gh-issue-138850.CkqTw6.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-26-12-27-42.gh-issue-146444.JKJuEa.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-27-06-55-10.gh-issue-146498.uOiCab.rst delete mode 100644 Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-03-18-20-18-59.gh-issue-146056.nnZIgp.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-03-18-23-44-29.gh-issue-146143.pwIrJq.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-03-19-16-50-27.gh-issue-146175.pISQGX.rst delete mode 100644 Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-07-23-07-17.gh-issue-126910.d8zdm-.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-31-15-15-43.gh-issue-143414.Jgl4xu.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-01-19-50.gh-issue-131798.PaWDNH.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-22-38-40.gh-issue-145779.5375381d80.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-12-24-17.gh-issue-145876.LWFO2K.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-00-00-00.gh-issue-146041.7799bb.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-14-20-56.gh-issue-145059.aB3xKm.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-18-18-52-00.gh-issue-146056.r1tVSo.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-16-16-40.gh-issue-135871.jSExZ3.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-00-39-25.gh-issue-146192.8aQ6sC.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-11-34-17.gh-issue-145667._Agp9o.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-26-24.gh-issue-146199.vV8V9s.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-52-55.gh-issue-146205.M4yKdf.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-07-33.gh-issue-146227.MqBPEo.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-55-14.gh-issue-146196.Zg70Kb.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-11-58.gh-issue-146151.4-lhim.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-48-25.gh-issue-146245.cqM3_4.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-11-55-16.gh-issue-146250.ahl3O2.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-12-00-00.gh-issue-146306.870ef4.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-19-30-00.gh-issue-146308.AxnRVA.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-24-13-06-52.gh-issue-146369.6wDI6S.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-11-18-45.gh-issue-146388.O0u1c3.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-27-17-14-18.gh-issue-126910.hooVFQ.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst delete mode 100644 Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst delete mode 100644 Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst delete mode 100644 Misc/NEWS.d/next/Library/2023-03-10-13-10-06.gh-issue-60729.KCCHTe.rst delete mode 100644 Misc/NEWS.d/next/Library/2024-09-25-12-47-50.gh-issue-66419.DVSukU.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-10-13-16-43-36.gh-issue-140049.VvmAzN.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-11-15-23-14-30.gh-issue-138577.KbShrt.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst delete mode 100644 Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-07-02-44-52.gh-issue-145616.x8Mf23.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-10-01-54-34.gh-issue-145719.okJRoK.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-10-14-57-15.gh-issue-145754.YBL5Ko.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-15-16-38-48.gh-issue-145980.mRze5H.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-16-00-00-00.gh-issue-146004.xOptProp.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-17-11-46-20.gh-issue-146054.udYcqn.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-17-20-41-27.gh-issue-146076.yoBNnB.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-18-16-58-17.gh-issue-146091.lBbo1L.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-18-23-54-36.gh-issue-145410.NvLWj5.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-20-00-28-00.gh-issue-146171.P5Jk2R7v.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-20-14-53-00.gh-issue-146228.OJVEDL.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-20-16-17-31.gh-issue-143387.9Waopa.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-21-06-21-38.gh-issue-146151.yNpgml.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-21-08-23-26.gh-issue-140947.owZ4r_.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-24-03-49-50.gh-issue-146310.WhlDir.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-26-02-06-52.gh-issue-146440.HXjhQO.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-27-12-00-00.gh-issue-146507.1D95A7.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-28-12-01-48.gh-issue-146090.wh1qJR.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-28-12-05-34.gh-issue-146090.wf9_ef.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-28-12-20-19.gh-issue-146556.Y8Eson.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-28-13-19-20.gh-issue-146080.srN12a.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst delete mode 100644 Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst delete mode 100644 Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst delete mode 100644 Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst delete mode 100644 Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst delete mode 100644 Misc/NEWS.d/next/Tests/2026-03-24-00-15-58.gh-issue-146202.LgH6Bj.rst delete mode 100644 Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst delete mode 100644 Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst delete mode 100644 Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst delete mode 100644 Misc/NEWS.d/next/Tools-Demos/2026-03-22-00-00-00.gh-issue-135953.IptOwg.rst delete mode 100644 Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst delete mode 100644 Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index f44c18e8075..7a925870a62 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -45,7 +45,7 @@ Dictionary objects The first argument can be a :class:`dict`, a :class:`frozendict`, or a mapping. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -76,7 +76,7 @@ Dictionary objects The first argument can be a :class:`dict` or a :class:`frozendict`. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -90,7 +90,7 @@ Dictionary objects .. versionadded:: 3.13 - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -142,7 +142,7 @@ Dictionary objects .. versionadded:: 3.13 - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. See also the :c:func:`PyObject_GetItem` function. @@ -166,7 +166,7 @@ Dictionary objects Calling this API without an :term:`attached thread state` had been allowed for historical reason. It is no longer allowed. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -177,7 +177,7 @@ Dictionary objects occurred. Return ``NULL`` **without** an exception set if the key wasn't present. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -195,7 +195,7 @@ Dictionary objects Prefer using the :c:func:`PyDict_GetItemWithError` function with your own :c:func:`PyUnicode_FromString` *key* instead. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -207,7 +207,7 @@ Dictionary objects .. versionadded:: 3.13 - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -275,7 +275,7 @@ Dictionary objects The first argument can be a :class:`dict` or a :class:`frozendict`. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -285,7 +285,7 @@ Dictionary objects The first argument can be a :class:`dict` or a :class:`frozendict`. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -296,7 +296,7 @@ Dictionary objects The first argument can be a :class:`dict` or a :class:`frozendict`. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -309,7 +309,7 @@ Dictionary objects The argument can be a :class:`dict` or a :class:`frozendict`. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -317,7 +317,7 @@ Dictionary objects Similar to :c:func:`PyDict_Size`, but without error checking. - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. @@ -391,7 +391,7 @@ Dictionary objects :term:`strong reference ` (for example, using :c:func:`Py_NewRef`). - .. versionchanged:: next + .. versionchanged:: 3.15 Also accept :class:`frozendict`. .. c:function:: int PyDict_Merge(PyObject *a, PyObject *b, int override) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index e42c1dbf420..2a22a023bda 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -536,7 +536,7 @@ have been standardized in C11 (or previous standards). Use the standard ``alignas`` specifier rather than this macro. - .. deprecated:: next + .. deprecated:: 3.15 The macro is :term:`soft deprecated`. .. c:macro:: PY_FORMAT_SIZE_T @@ -544,7 +544,7 @@ have been standardized in C11 (or previous standards). The :c:func:`printf` formatting modifier for :c:type:`size_t`. Use ``"z"`` directly instead. - .. deprecated:: next + .. deprecated:: 3.15 The macro is :term:`soft deprecated`. .. c:macro:: Py_LL(number) @@ -558,7 +558,7 @@ have been standardized in C11 (or previous standards). Consider using the C99 standard suffixes ``LL`` and ``LLU`` directly. - .. deprecated:: next + .. deprecated:: 3.15 The macro is :term:`soft deprecated`. .. c:macro:: PY_LONG_LONG @@ -572,7 +572,7 @@ have been standardized in C11 (or previous standards). respectively. Historically, these types needed compiler-specific extensions. - .. deprecated:: next + .. deprecated:: 3.15 These macros are :term:`soft deprecated`. .. c:macro:: PY_LLONG_MIN @@ -587,7 +587,7 @@ have been standardized in C11 (or previous standards). The required header, ````, :ref:`is included ` in ``Python.h``. - .. deprecated:: next + .. deprecated:: 3.15 These macros are :term:`soft deprecated`. .. c:macro:: Py_MEMCPY(dest, src, n) @@ -606,7 +606,7 @@ have been standardized in C11 (or previous standards). The required header for the latter, ````, :ref:`is included ` in ``Python.h``. - .. deprecated:: next + .. deprecated:: 3.15 The macro is :term:`soft deprecated`. .. c:macro:: Py_UNICODE_WIDE @@ -614,7 +614,7 @@ have been standardized in C11 (or previous standards). Defined if ``wchar_t`` can hold a Unicode character (UCS-4). Use ``sizeof(wchar_t) >= 4`` instead - .. deprecated:: next + .. deprecated:: 3.15 The macro is :term:`soft deprecated`. .. c:macro:: Py_VA_COPY @@ -627,7 +627,7 @@ have been standardized in C11 (or previous standards). .. versionchanged:: 3.6 This is now an alias to ``va_copy``. - .. deprecated:: next + .. deprecated:: 3.15 The macro is :term:`soft deprecated`. diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst index f8b41f6d87f..fe2cb89f999 100644 --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -96,7 +96,7 @@ Contents of the Limited API are :ref:`listed below `. .. seealso:: :pep:`803` - .. versionadded:: next + .. versionadded:: 3.15 .. _stable-abi: diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 8b0a0c84548..4468edb6efa 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -77,7 +77,7 @@ Notes: as :c:expr:`_Float16` type, if the compiler supports the Annex H of the C23 standard. - .. versionadded:: next + .. versionadded:: 3.15 (4) Complex types (``F`` and ``D``) are available unconditionally, diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 40edd60abea..5e08d56fd66 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -142,7 +142,7 @@ POST request. standard Base64 alphabet, and return the encoded :class:`bytes`. The result can still contain ``=`` if *padded* is true (default). - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *padded* parameter. @@ -154,7 +154,7 @@ POST request. ``/`` in the standard Base64 alphabet, and return the decoded :class:`bytes`. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *padded* parameter. Padding of input is no longer required by default. @@ -175,7 +175,7 @@ POST request. after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not add any newlines. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *padded* and *wrapcol* parameters. @@ -209,7 +209,7 @@ POST request. incorrectly padded or if there are non-alphabet characters present in the input. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *ignorechars* and *padded* parameters. @@ -220,7 +220,7 @@ POST request. .. versionadded:: 3.10 - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *padded* and *wrapcol* parameters. @@ -236,7 +236,7 @@ POST request. .. versionadded:: 3.10 - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *ignorechars* and *padded* parameters. @@ -249,7 +249,7 @@ POST request. after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not add any newlines. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *wrapcol* parameter. @@ -269,7 +269,7 @@ POST request. incorrectly padded or if there are non-alphabet characters present in the input. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *ignorechars* parameter. @@ -351,7 +351,7 @@ Refer to the documentation of the individual functions for more information. .. versionadded:: 3.4 - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *wrapcol* parameter. @@ -366,7 +366,7 @@ Refer to the documentation of the individual functions for more information. .. versionadded:: 3.4 - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *ignorechars* parameter. @@ -388,7 +388,7 @@ Refer to the documentation of the individual functions for more information. .. versionchanged:: 3.15 The *pad* parameter was added. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *wrapcol* parameter. @@ -403,7 +403,7 @@ Refer to the documentation of the individual functions for more information. .. versionadded:: 3.13 - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *ignorechars* parameter. diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index de5e5766779..08a82cc4b5f 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -233,7 +233,7 @@ The :mod:`!binascii` module defines the following functions: Invalid base32 data will raise :exc:`binascii.Error`. - .. versionadded:: next + .. versionadded:: 3.15 .. function:: b2a_base32(data, /, *, padded=True, alphabet=BASE32_ALPHABET, wrapcol=0) @@ -251,7 +251,7 @@ The :mod:`!binascii` module defines the following functions: after at most every *wrapcol* characters. If *wrapcol* is zero (default), do not insert any newlines. - .. versionadded:: next + .. versionadded:: 3.15 .. function:: a2b_qp(data, header=False) @@ -341,7 +341,7 @@ The :mod:`!binascii` module defines the following functions: liberal towards whitespace) is also accessible using the :meth:`bytes.fromhex` class method. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *ignorechars* parameter. @@ -360,55 +360,55 @@ The :mod:`!binascii` module defines the following functions: The Base 64 alphabet according to :rfc:`4648`. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: URLSAFE_BASE64_ALPHABET The "URL and filename safe" Base 64 alphabet according to :rfc:`4648`. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: UU_ALPHABET The uuencoding alphabet. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: CRYPT_ALPHABET The Base 64 alphabet used in the :manpage:`crypt(3)` routine and in the GEDCOM format. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: BINHEX_ALPHABET The Base 64 alphabet used in BinHex 4 (HQX) within the classic Mac OS. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: BASE85_ALPHABET The Base85 alphabet. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: ASCII85_ALPHABET The Ascii85 alphabet. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: Z85_ALPHABET The `Z85 `_ alphabet. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: BASE32_ALPHABET The Base 32 alphabet according to :rfc:`4648`. - .. versionadded:: next + .. versionadded:: 3.15 .. data:: BASE32HEX_ALPHABET @@ -416,7 +416,7 @@ The :mod:`!binascii` module defines the following functions: Data encoded with this alphabet maintains its sort order during bitwise comparisons. - .. versionadded:: next + .. versionadded:: 3.15 .. seealso:: diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 0b3ad4573f5..571975d4674 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1756,7 +1756,7 @@ as a default or fallback. (or by) Python. It is recommended to only use this function as a default or fallback, - .. deprecated:: next + .. deprecated:: 3.15 This function is :term:`soft deprecated`. It is kept for use in cases where it works, but not expected to be diff --git a/Doc/library/getpass.rst b/Doc/library/getpass.rst index a6ca230d5e8..fd96f3bbf6a 100644 --- a/Doc/library/getpass.rst +++ b/Doc/library/getpass.rst @@ -55,7 +55,7 @@ The :mod:`!getpass` module provides two functions: .. versionchanged:: 3.14 Added the *echo_char* parameter for keyboard feedback. - .. versionchanged:: next + .. versionchanged:: 3.15 When using non-empty *echo_char* on Unix, keyboard shortcuts (including cursor movement and line editing) are now properly handled using the terminal's control character configuration. diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 72632a8ef53..b354e7ba534 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -358,7 +358,7 @@ Basic Usage conversion length limitation ` to help avoid denial of service attacks. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the optional *array_hook* parameter. .. function:: loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, array_hook=None, **kw) @@ -429,7 +429,7 @@ Encoders and Decoders *array_hook* will be used instead of the :class:`list`. This feature can be used to implement custom decoders. - .. versionchanged:: next + .. versionchanged:: 3.15 Added support for *array_hook*. *parse_float* is an optional function that will be called with the string of diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 77ed44c2bb7..4f043fbb3a4 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -220,7 +220,7 @@ PrettyPrinter Objects .. versionchanged:: 3.11 No longer attempts to write to :data:`!sys.stdout` if it is ``None``. - .. versionchanged:: next + .. versionchanged:: 3.15 Added the *expand* parameter. diff --git a/Doc/library/select.rst b/Doc/library/select.rst index 6c4a5561218..09563af14d0 100644 --- a/Doc/library/select.rst +++ b/Doc/library/select.rst @@ -89,7 +89,7 @@ The module defines the following: The *flags* parameter. ``select.EPOLL_CLOEXEC`` is used by default now. Use :func:`os.set_inheritable` to make the file descriptor inheritable. - .. versionchanged:: next + .. versionchanged:: 3.15 When CPython is built, this function may be disabled using :option:`--disable-epoll`. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 2099ef56169..a10551975ed 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3751,7 +3751,7 @@ arbitrary binary data. The bytearray version of this method does *not* operate in place - it always produces a new object, even if no changes were made. - .. versionchanged:: next + .. versionchanged:: 3.15 *count* is now supported as a keyword argument. diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst index aed7e7556f6..fd67c5c0a0f 100644 --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -158,7 +158,7 @@ The module defines three convenience functions and a public class: .. versionadded:: 3.6 - .. versionchanged:: next + .. versionchanged:: 3.15 The optional *target_time* parameter was added. @@ -247,7 +247,7 @@ Where the following options are understood: if :option:`--number` is 0, the code will run until it takes at least this many seconds (default: 0.2) - .. versionadded:: next + .. versionadded:: 3.15 .. option:: -v, --verbose diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 9d30a14f112..d320975708c 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -18,7 +18,7 @@ The module supports uncompressed PCM and IEEE floating-point WAV formats. Support for ``WAVE_FORMAT_EXTENSIBLE`` headers was added, provided that the extended format is ``KSDATAFORMAT_SUBTYPE_PCM``. -.. versionchanged:: next +.. versionchanged:: 3.15 Support for reading and writing ``WAVE_FORMAT_IEEE_FLOAT`` files was added. diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index bbb15ce5e75..310ccd651e1 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -705,7 +705,7 @@ Functions .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. - .. versionchanged:: next + .. versionchanged:: 3.15 *parent* and *tag* are now positional-only parameters. @@ -896,7 +896,7 @@ Element Objects .. versionchanged:: 3.15 *attrib* can now be a :class:`frozendict`. - .. versionchanged:: next + .. versionchanged:: 3.15 *tag* is now a positional-only parameter. diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index cc6aafe80f8..82409ac0cdc 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -472,7 +472,7 @@ General Options :manpage:`epoll_create1 ` is available but incompatible with Linux semantics. - .. versionadded:: next + .. versionadded:: 3.15 C compiler options diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 154bdb0721d..2761f0dcbdc 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -24,10 +24,10 @@ #define PY_MINOR_VERSION 15 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 7 +#define PY_RELEASE_SERIAL 8 /* Version as a string */ -#define PY_VERSION "3.15.0a7+" +#define PY_VERSION "3.15.0a8" /*--end constants--*/ diff --git a/Lib/pydoc_data/module_docs.py b/Lib/pydoc_data/module_docs.py index 314bef547f3..9e33c6765bb 100644 --- a/Lib/pydoc_data/module_docs.py +++ b/Lib/pydoc_data/module_docs.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Tue Mar 10 14:31:07 2026 +# Autogenerated by Sphinx on Tue Apr 7 14:21:08 2026 # as part of the release process. module_docs = { diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 7dd9cfe2ff5..68f6771d4ce 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Tue Mar 10 14:31:07 2026 +# Autogenerated by Sphinx on Tue Apr 7 14:21:08 2026 # as part of the release process. topics = { @@ -3972,7 +3972,7 @@ object.__format__(self, format_spec) formatting to one of the built-in types, or use a similar formatting option syntax. - See Format Specification Mini-Language for a description of the + See Format specification mini-language for a description of the standard formatting syntax. The return value must be a string object. @@ -5769,7 +5769,7 @@ immutable arithmetic sequences of integers. For instance, iterating Changed in version 3.11: Starred elements are now allowed in the expression list. ''', - 'formatstrings': r'''Format String Syntax + 'formatstrings': r'''Format string syntax ******************** The "str.format()" method and the "Formatter" class share the same @@ -5804,7 +5804,7 @@ preceded by an exclamation point "'!'", and a *format_spec*, which is preceded by a colon "':'". These specify a non-default format for the replacement value. -See also the Format Specification Mini-Language section. +See also the Format specification mini-language section. The *field_name* itself begins with an *arg_name* that is either a number or a keyword. If it’s a number, it refers to a positional @@ -5872,12 +5872,12 @@ allows the formatting of a value to be dynamically specified. See the Format examples section for some examples. -Format Specification Mini-Language +Format specification mini-language ================================== “Format specifications” are used within replacement fields contained within a format string to define how individual values are presented -(see Format String Syntax, f-strings, and t-strings). They can also be +(see Format string syntax, f-strings, and t-strings). They can also be passed directly to the built-in "format()" function. Each formattable type may define how the format specification is to be interpreted. @@ -6284,8 +6284,8 @@ Expressing a percentage: Using type-specific formatting: - >>> import datetime - >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58) + >>> import datetime as dt + >>> d = dt.datetime(2010, 7, 4, 12, 15, 58) >>> '{:%Y-%m-%d %H:%M:%S}'.format(d) '2010-07-04 12:15:58' @@ -6616,8 +6616,7 @@ identifier names. Changed in version 3.12: "type" is now a soft keyword. -Changed in version 3.15.0a6 (unreleased): "lazy" is now a soft -keyword. +Changed in version 3.15: "lazy" is now a soft keyword. Reserved classes of identifiers @@ -6698,8 +6697,8 @@ start with a character in the “letter-like” set "xid_start", and the remaining characters must be in the “letter- and digit-like” set "xid_continue". -These sets based on the *XID_Start* and *XID_Continue* sets as defined -by the Unicode standard annex UAX-31. Python’s "xid_start" +These sets are based on the *XID_Start* and *XID_Continue* sets as +defined by the Unicode standard annex UAX-31. Python’s "xid_start" additionally includes the underscore ("_"). Note that Python does not necessarily conform to UAX-31. @@ -6982,7 +6981,7 @@ first used, not at the import statement itself. See **PEP 810** for the full specification of lazy imports. -Added in version 3.15.0a6 (unreleased). +Added in version 3.15. Future statements @@ -8282,19 +8281,6 @@ object.__length_hint__(self) Added in version 3.4. -Note: - - Slicing is done exclusively with the following three methods. A - call like - - a[1:2] = b - - is translated to - - a[slice(1, 2, None)] = b - - and so forth. Missing slice items are always filled in with "None". - object.__getitem__(self, subscript) Called to implement *subscription*, that is, "self[subscript]". See @@ -8316,6 +8302,20 @@ object.__getitem__(self, subscript) "__getitem__()" should raise an "LookupError" or one of its subclasses ("IndexError" for sequences; "KeyError" for mappings). + Note: + + Slicing is handled by "__getitem__()", "__setitem__()", and + "__delitem__()". A call like + + a[1:2] = b + + is translated to + + a[slice(1, 2, None)] = b + + and so forth. Missing slice items are always filled in with + "None". + Note: The sequence iteration protocol (used, for example, in "for" @@ -8664,7 +8664,7 @@ object.__format__(self, format_spec) formatting to one of the built-in types, or use a similar formatting option syntax. - See Format Specification Mini-Language for a description of the + See Format specification mini-language for a description of the standard formatting syntax. The return value must be a string object. @@ -9665,19 +9665,6 @@ object.__length_hint__(self) Added in version 3.4. -Note: - - Slicing is done exclusively with the following three methods. A - call like - - a[1:2] = b - - is translated to - - a[slice(1, 2, None)] = b - - and so forth. Missing slice items are always filled in with "None". - object.__getitem__(self, subscript) Called to implement *subscription*, that is, "self[subscript]". See @@ -9699,6 +9686,20 @@ object.__getitem__(self, subscript) "__getitem__()" should raise an "LookupError" or one of its subclasses ("IndexError" for sequences; "KeyError" for mappings). + Note: + + Slicing is handled by "__getitem__()", "__setitem__()", and + "__delitem__()". A call like + + a[1:2] = b + + is translated to + + a[slice(1, 2, None)] = b + + and so forth. Missing slice items are always filled in with + "None". + Note: The sequence iteration protocol (used, for example, in "for" @@ -10021,14 +10022,27 @@ object.__buffer__(self, flags) "inspect.BufferFlags" provides a convenient way to interpret the flags. The method must return a "memoryview" object. + **Thread safety:** In *free-threaded* Python, implementations must + manage any internal export counter using atomic operations. The + method must be safe to call concurrently from multiple threads, and + the returned buffer’s underlying data must remain valid until the + corresponding "__release_buffer__()" call completes. See Thread + safety for memoryview objects for details. + object.__release_buffer__(self, buffer) Called when a buffer is no longer needed. The *buffer* argument is a "memoryview" object that was previously returned by "__buffer__()". The method must release any resources associated - with the buffer. This method should return "None". Buffer objects - that do not need to perform any cleanup are not required to - implement this method. + with the buffer. This method should return "None". + + **Thread safety:** In *free-threaded* Python, any export counter + decrement must use atomic operations. Resource cleanup must be + thread-safe, as the final release may race with concurrent releases + from other threads. + + Buffer objects that do not need to perform any cleanup are not + required to implement this method. Added in version 3.12. @@ -10169,7 +10183,7 @@ the additional methods described below. Strings also support two styles of string formatting, one providing a large degree of flexibility and customization (see "str.format()", -Format String Syntax and Custom String Formatting) and the other based +Format string syntax and Custom string formatting) and the other based on C "printf" style formatting that handles a narrower range of types and is slightly harder to use correctly, but is often faster for the cases it can handle (printf-style String Formatting). @@ -10355,7 +10369,7 @@ str.format(*args, **kwargs) >>> "{1} expects the {0} Inquisition!".format("Spanish", "Nobody") 'Nobody expects the Spanish Inquisition!' - See Format String Syntax for a description of the various + See Format string syntax for a description of the various formatting options that can be specified in format strings. Note: @@ -10548,16 +10562,31 @@ str.isprintable() >>> '\t'.isprintable(), '\n'.isprintable() (False, False) + See also "isspace()". + str.isspace() Return "True" if there are only whitespace characters in the string and there is at least one character, "False" otherwise. + For example: + + >>> ''.isspace() + False + >>> ' '.isspace() + True + >>> '\t\n'.isspace() # TAB and BREAK LINE + True + >>> '\u3000'.isspace() # IDEOGRAPHIC SPACE + True + A character is *whitespace* if in the Unicode character database (see "unicodedata"), either its general category is "Zs" (“Separator, space”), or its bidirectional class is one of "WS", "B", or "S". + See also "isprintable()". + str.istitle() Return "True" if the string is a titlecased string and there is at @@ -10673,8 +10702,7 @@ static str.maketrans(from, to, remove='', /) a third argument, it must be a string, whose characters will be mapped to "None" in the result. - Changed in version 3.15.0a6 (unreleased): *dict* can now be a - "frozendict". + Changed in version 3.15: *dict* can now be a "frozendict". str.partition(sep, /) @@ -13041,11 +13069,28 @@ also "os.popen()", "os.fdopen()", and the "makefile()" method of socket objects (and perhaps by other functions or methods provided by extension modules). +File objects implement common methods, listed below, to simplify usage +in generic code. They are expected to be With Statement Context +Managers. + The objects "sys.stdin", "sys.stdout" and "sys.stderr" are initialized to file objects corresponding to the interpreter’s standard input, output and error streams; they are all open in text mode and therefore follow the interface defined by the "io.TextIOBase" abstract class. +file.read(size=-1, /) + + Retrieve up to *size* data from the file. As a convenience if + *size* is unspecified or -1 retrieve all data available. + +file.write(data, /) + + Store *data* to the file. + +file.close() + + Flush any buffers and close the underlying file. + Internal types ============== @@ -13885,7 +13930,7 @@ class frozendict(iterable, /, **kwargs) "frozendict" is not a "dict" subclass but inherits directly from "object". - Added in version 3.15.0a6 (unreleased). + Added in version 3.15. ''', 'typesmethods': r'''Methods ******* @@ -14116,7 +14161,7 @@ sequence.count(value, /) Return the total number of occurrences of *value* in *sequence*. -sequence.index(value[, start[, stop]) +sequence.index(value[, start[, stop]]) Return the index of the first occurrence of *value* in *sequence*. @@ -14206,7 +14251,7 @@ Mutable sequence types also support the following methods: sequence.append(value, /) - Append *value* to the end of the sequence This is equivalent to + Append *value* to the end of the sequence. This is equivalent to writing "seq[len(seq):len(seq)] = [value]". sequence.clear() @@ -14559,7 +14604,7 @@ Mutable sequence types also support the following methods: sequence.append(value, /) - Append *value* to the end of the sequence This is equivalent to + Append *value* to the end of the sequence. This is equivalent to writing "seq[len(seq):len(seq)] = [value]". sequence.clear() diff --git a/Misc/NEWS.d/3.15.0a8.rst b/Misc/NEWS.d/3.15.0a8.rst new file mode 100644 index 00000000000..ed37988f6ab --- /dev/null +++ b/Misc/NEWS.d/3.15.0a8.rst @@ -0,0 +1,1593 @@ +.. date: 2026-03-14-17-31-39 +.. gh-issue: 145986 +.. nonce: ifSSr8 +.. release date: 2026-04-07 +.. section: Security + +:mod:`xml.parsers.expat`: Fixed a crash caused by unbounded C recursion when +converting deeply nested XML content models with +:meth:`~xml.parsers.expat.xmlparser.ElementDeclHandler`. This addresses +:cve:`2026-4224`. + +.. + +.. date: 2026-03-06-17-03-38 +.. gh-issue: 145599 +.. nonce: kchwZV +.. section: Security + +Reject control characters in :class:`http.cookies.Morsel` +:meth:`~http.cookies.Morsel.update` and +:meth:`~http.cookies.BaseCookie.js_output`. This addresses :cve:`2026-3644`. + +.. + +.. date: 2026-01-16-12-04-49 +.. gh-issue: 143930 +.. nonce: zYC5x3 +.. section: Security + +Reject leading dashes in URLs passed to :func:`webbrowser.open`. + +.. + +.. date: 2026-04-06-11-15-46 +.. gh-issue: 148157 +.. nonce: JFnZDn +.. section: Core and Builtins + +Fix an unlikely crash when parsing an invalid type comments for function +parameters. Found by OSS Fuzz in :oss-fuzz:`492782951`. + +.. + +.. date: 2026-04-06-00-00-00 +.. gh-issue: 100239 +.. nonce: binopxt +.. section: Core and Builtins + +Propagate result type and uniqueness information through +``_BINARY_OP_EXTEND`` in the tier 2 optimizer, enabling elimination of +downstream type guards and selection of inplace float operations. + +.. + +.. date: 2026-04-05-15-20-00 +.. gh-issue: 148144 +.. nonce: f7qA0x +.. section: Core and Builtins + +Initialize ``_PyInterpreterFrame.visited`` when copying interpreter frames +so incremental GC does not read an uninitialized byte from generator and +frame-object copies. + +.. + +.. date: 2026-04-05-00-00-00 +.. gh-issue: 148072 +.. nonce: xid9Pe +.. section: Core and Builtins + +Cache ``pickle.dumps`` and ``pickle.loads`` per interpreter in the XIData +framework, avoiding repeated module lookups on every cross-interpreter data +transfer. This speeds up +:class:`~concurrent.futures.InterpreterPoolExecutor` for mutable types +(``list``, ``dict``) by 1.7x--3.3x. + +.. + +.. date: 2026-04-04-22-20-00 +.. gh-issue: 148110 +.. nonce: cL5x2Q +.. section: Core and Builtins + +Fix :func:`sys.set_lazy_imports_filter` so relative lazy imports pass the +resolved imported module name to the filter callback. Patch by Pablo +Galindo. + +.. + +.. date: 2026-04-04-20-59-12 +.. gh-issue: 148083 +.. nonce: 9ZHNBN +.. section: Core and Builtins + +Constant-fold ``_CONTAINS_OP_SET`` for :class:`frozenset`. Patch by Donghee +Na. + +.. + +.. date: 2026-04-01-12-52-31 +.. gh-issue: 144319 +.. nonce: iZk4hs +.. section: Core and Builtins + +Fix a bug that could cause applications with specific allocation patterns to +leak memory via Huge Pages if compiled with Huge Page support. Patch by +Pablo Galindo + +.. + +.. date: 2026-04-01-12-35-55 +.. gh-issue: 147985 +.. nonce: YVirHJ +.. section: Core and Builtins + +Make :c:func:`PySet_Contains` attempt a lock-free lookup, similar to +:meth:`!set.__contains__`. This avoids acquiring the set object mutex in +the normal case. + +.. + +.. date: 2026-03-31-18-07-53 +.. gh-issue: 147856 +.. nonce: 62Dwee +.. section: Core and Builtins + +Allow the *count* argument of :meth:`bytes.replace` to be a keyword. + +.. + +.. date: 2026-03-31-01-06-35 +.. gh-issue: 146615 +.. nonce: fix-method-get +.. section: Core and Builtins + +Fix a crash in :meth:`~object.__get__` for :c:expr:`METH_METHOD` descriptors +when an invalid (non-type) object is passed as the second argument. Patch by +Steven Sun. + +.. + +.. date: 2026-03-30-20-00-00 +.. gh-issue: 146306 +.. nonce: C45609 +.. section: Core and Builtins + +Optimize compact integer arithmetic in the JIT by mutating +uniquely-referenced operands in place, avoiding allocation of a new int +object. Speeds up the pyperformance ``spectral_norm`` benchmark by ~10%. + +.. + +.. date: 2026-03-29-11-39-05 +.. gh-issue: 146587 +.. nonce: YJicXt +.. section: Core and Builtins + +Fix type slot assignment incase of multiple slots for same name in type +object implementation. Patch by Kumar Aditya. + +.. + +.. date: 2026-03-27-17-14-18 +.. gh-issue: 126910 +.. nonce: hooVFQ +.. section: Core and Builtins + +Set frame pointers in ``aarch64-unknown-linux-gnu`` JIT code, allowing most +native profilers and debuggers to unwind through them. Patch by Diego Russo + +.. + +.. date: 2026-03-26-11-18-45 +.. gh-issue: 146388 +.. nonce: O0u1c3 +.. section: Core and Builtins + +Adds a null check to handle when the JIT optimizer runs out of space when +dealing with contradictions in ``make_bottom``. + +.. + +.. date: 2026-03-24-13-06-52 +.. gh-issue: 146369 +.. nonce: 6wDI6S +.. section: Core and Builtins + +Ensure ``-X lazy_imports=none``` and ``PYTHON_LAZY_IMPORTS=none``` override +``__lazy_modules__``. Patch by Hugo van Kemenade. + +.. + +.. date: 2026-03-22-19-30-00 +.. gh-issue: 146308 +.. nonce: AxnRVA +.. section: Core and Builtins + +Fixed multiple error handling issues in the :mod:`!_remote_debugging` module +including a double-free in code object caching, memory leaks on allocation +failure, missing exception checks in binary format varint decoding, +reference leaks on error paths in frame chain processing, and inconsistent +thread status error reporting across platforms. Patch by Pablo Galindo. + +.. + +.. date: 2026-03-22-12-00-00 +.. gh-issue: 146306 +.. nonce: 870ef4 +.. section: Core and Builtins + +Optimize float arithmetic in the JIT by mutating uniquely-referenced +operands in place, avoiding allocation of a new float object. Speeds up the +pyperformance ``nbody`` benchmark by ~19%. + +.. + +.. date: 2026-03-21-15-05-14 +.. gh-issue: 146128 +.. nonce: DG1Hfa +.. section: Core and Builtins + +Fix a bug which could cause constant values to be partially corrupted in +AArch64 JIT code. This issue is theoretical, and hasn't actually been +observed in unmodified Python interpreters. + +.. + +.. date: 2026-03-21-11-55-16 +.. gh-issue: 146250 +.. nonce: ahl3O2 +.. section: Core and Builtins + +Fixed a memory leak in :exc:`SyntaxError` when re-initializing it. + +.. + +.. date: 2026-03-21-08-48-25 +.. gh-issue: 146245 +.. nonce: cqM3_4 +.. section: Core and Builtins + +Fixed reference leaks in :mod:`socket` when audit hooks raise exceptions in +:func:`socket.getaddrinfo` and :meth:`!socket.sendto`. + +.. + +.. date: 2026-03-21-08-11-58 +.. gh-issue: 146151 +.. nonce: 4-lhim +.. section: Core and Builtins + +:class:`memoryview` now supports the :c:expr:`float complex` and +:c:expr:`double complex` C types: formatting characters ``'F'`` and ``'D'`` +respectively. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-03-20-13-55-14 +.. gh-issue: 146196 +.. nonce: Zg70Kb +.. section: Core and Builtins + +Fix potential Undefined Behavior in :c:func:`PyUnicodeWriter_WriteASCII` by +adding a zero-length check. Patch by Shamil Abdulaev. + +.. + +.. date: 2026-03-20-13-07-33 +.. gh-issue: 146227 +.. nonce: MqBPEo +.. section: Core and Builtins + +Fix wrong type in ``_Py_atomic_load_uint16`` in the C11 atomics backend +(``pyatomic_std.h``), which used a 32-bit atomic load instead of 16-bit. +Found by Mohammed Zuhaib. + +.. + +.. date: 2026-03-20-12-52-55 +.. gh-issue: 146205 +.. nonce: M4yKdf +.. section: Core and Builtins + +Fixed a bug where :meth:`select.epoll.close`, :meth:`select.kqueue.close`, +and :meth:`select.devpoll.close` silently ignored errors. + +.. + +.. date: 2026-03-20-12-26-24 +.. gh-issue: 146199 +.. nonce: vV8V9s +.. section: Core and Builtins + +Comparison of code objects now handles errors correctly. + +.. + +.. date: 2026-03-20-11-34-17 +.. gh-issue: 145667 +.. nonce: _Agp9o +.. section: Core and Builtins + +Remove the ``GET_ITER_YIELD_FROM`` instruction, modifying ``SEND`` to pair +with ``GET_ITER`` when compiling ``yield from`` expressions. + +.. + +.. date: 2026-03-20-00-39-25 +.. gh-issue: 146192 +.. nonce: 8aQ6sC +.. section: Core and Builtins + +Add Base32 support to :mod:`binascii` and improve the performance of the +Base32 converters in :mod:`base64`. Patch by James Seo. + +.. + +.. date: 2026-03-19-16-16-40 +.. gh-issue: 135871 +.. nonce: jSExZ3 +.. section: Core and Builtins + +Improve multithreaded scaling of PyMutex in low-contention scenarios by +reloading the lock's internal state, without slowing down high-contention +scenarios. + +.. + +.. date: 2026-03-19-01-19-34 +.. gh-issue: 146096 +.. nonce: R9tkJX +.. section: Core and Builtins + +Fixed segmentation fault when called repr for BaseExceptionGroup with empty +or 1-size tuple args. + +.. + +.. date: 2026-03-18-18-52-00 +.. gh-issue: 146056 +.. nonce: r1tVSo +.. section: Core and Builtins + +Fix :func:`repr` for lists and tuples containing ``NULL``\ s. + +.. + +.. date: 2026-03-17-14-20-56 +.. gh-issue: 145059 +.. nonce: aB3xKm +.. section: Core and Builtins + +Fixed ``sys.lazy_modules`` to include lazy modules without submodules. Patch +by Bartosz Sławecki. + +.. + +.. date: 2026-03-17-00-00-00 +.. gh-issue: 146041 +.. nonce: 7799bb +.. section: Core and Builtins + +Fix free-threading scaling bottleneck in :func:`sys.intern` and +:c:func:`PyObject_SetAttr` by avoiding the interpreter-wide lock when the +string is already interned and immortalized. + +.. + +.. date: 2026-03-15-21-45-35 +.. gh-issue: 145990 +.. nonce: tmXwRB +.. section: Core and Builtins + +``python --help-env`` sections are now sorted by environment variable name. + +.. + +.. date: 2026-03-15-20-47-34 +.. gh-issue: 145990 +.. nonce: 14BUzw +.. section: Core and Builtins + +``python --help-xoptions`` is now sorted by ``-X`` option name. + +.. + +.. date: 2026-03-13-12-24-17 +.. gh-issue: 145876 +.. nonce: LWFO2K +.. section: Core and Builtins + +:exc:`AttributeError`\ s and :exc:`KeyError`\ s raised in :meth:`!keys` or +:meth:`!__getitem__` during dictionary unpacking (``{**mymapping}`` or +``func(**mymapping)``) are no longer masked by :exc:`TypeError`. + +.. + +.. date: 2026-03-13-09-48-57 +.. gh-issue: 127958 +.. nonce: U-znTv +.. section: Core and Builtins + +Support tracing from function entrypoints in the JIT. Patch by Ken Jin. + +.. + +.. date: 2026-03-11-21-27-28 +.. gh-issue: 145376 +.. nonce: LfDvyw +.. section: Core and Builtins + +Fix GC tracking in ``structseq.__replace__()``. + +.. + +.. date: 2026-03-11-19-09-47 +.. gh-issue: 145792 +.. nonce: X5KUhc +.. section: Core and Builtins + +Fix out-of-bounds access when invoking faulthandler on a CPython build +compiled without support for VLAs. + +.. + +.. date: 2026-03-11-00-13-59 +.. gh-issue: 142183 +.. nonce: 2iVhJH +.. section: Core and Builtins + +Avoid a pathological case where repeated calls at a specific stack depth +could be significantly slower. + +.. + +.. date: 2026-03-10-22-38-40 +.. gh-issue: 145779 +.. nonce: 5375381d80 +.. section: Core and Builtins + +Improve scaling of :func:`classmethod` and :func:`staticmethod` calls in the +free-threaded build by avoiding the descriptor ``__get__`` call. + +.. + +.. date: 2026-03-10-19-00-39 +.. gh-issue: 145783 +.. nonce: dS5TM9 +.. section: Core and Builtins + +Fix an unlikely crash in the parser when certain errors were erroneously not +propagated. Found by OSS Fuzz in :oss-fuzz:`491369109`. + +.. + +.. date: 2026-03-10-12-52-06 +.. gh-issue: 145685 +.. nonce: 80B7gK +.. section: Core and Builtins + +Improve scaling of type attribute lookups in the :term:`free-threaded build` +by avoiding contention on the internal type lock. + +.. + +.. date: 2026-03-09-00-00-00 +.. gh-issue: 145713 +.. nonce: KR6azvzI +.. section: Core and Builtins + +Make :meth:`bytearray.resize` thread-safe in the free-threaded build by +using a critical section and calling the lock-held variant of the resize +function. + +.. + +.. date: 2026-02-28-18-42-36 +.. gh-issue: 145036 +.. nonce: 70Kbfz +.. section: Core and Builtins + +In free-threaded build, fix race condition when calling :meth:`!__sizeof__` +on a :class:`list` + +.. + +.. date: 2026-02-14-15-51-16 +.. gh-issue: 134584 +.. nonce: 6WFSuB +.. section: Core and Builtins + +Eliminate redundant refcounting for ``MATCH_CLASS`` in the JIT. + +.. + +.. date: 2026-02-14-13-07-08 +.. gh-issue: 69605 +.. nonce: 4aL4hn +.. section: Core and Builtins + +Add :mod:`math.integer` to :term:`REPL` auto-completion of imports. + +.. + +.. date: 2026-02-08-01-19-50 +.. gh-issue: 131798 +.. nonce: PaWDNH +.. section: Core and Builtins + +Optimize ``_ITER_CHECK_RANGE`` and ``_ITER_CHECK_LIST`` in the JIT + +.. + +.. date: 2026-01-31-15-15-43 +.. gh-issue: 143414 +.. nonce: Jgl4xu +.. section: Core and Builtins + +Add tracking to the JIT optimizer to determine whether a reference is +uniquely owned or shared + +.. + +.. date: 2026-01-10-12-59-58 +.. gh-issue: 143636 +.. nonce: dzr26e +.. section: Core and Builtins + +Fix a crash when calling :class:`SimpleNamespace.__replace__() +` on non-namespace instances. Patch by Bénédikt Tran. + +.. + +.. date: 2026-01-07-23-07-17 +.. gh-issue: 126910 +.. nonce: d8zdm- +.. section: Core and Builtins + +Set frame pointers in ``x86_64-unknown-linux-gnu`` JIT code, allowing most +native profilers and debuggers to unwind through them. + +.. + +.. date: 2025-11-02-16-23-17 +.. gh-issue: 140594 +.. nonce: YIWUpl +.. section: Core and Builtins + +Fix an out of bounds read when a single NUL character is read from the +standard input. Patch by Shamil Abdulaev. + +.. + +.. date: 2025-11-01-01-49-52 +.. gh-issue: 140870 +.. nonce: iknc12 +.. section: Core and Builtins + +Add support for module attributes in the :term:`REPL` auto-completion of +imports. + +.. + +.. date: 2026-04-07-01-04-00 +.. gh-issue: 144503 +.. nonce: argvfs +.. section: Library + +Fix a regression introduced in 3.14.3 and 3.13.12 where the +:mod:`multiprocessing` ``forkserver`` start method would fail with +:exc:`BrokenPipeError` when the parent process had a very large +:data:`sys.argv`. The argv is now passed to the forkserver as separate +command-line arguments rather than being embedded in the ``-c`` command +string, avoiding the operating system's per-argument length limit. + +.. + +.. date: 2026-04-06-11-20-24 +.. gh-issue: 148153 +.. nonce: ZtsuTl +.. section: Library + +:func:`base64.b32encode` now always raises :exc:`ValueError` instead of +:exc:`AssertionError` for the value of *map01* with invalid length. + +.. + +.. date: 2026-04-01-18-17-55 +.. gh-issue: 73613 +.. nonce: PLEebm +.. section: Library + +Add the *padded* parameter in functions related to Base32 and Base64 codecs +in the :mod:`binascii` and :mod:`base64` modules. In the encoding functions +it controls whether the pad character can be added in the output, in the +decoding functions it controls whether padding is required in input. Padding +of input no longer required in :func:`base64.urlsafe_b64decode` by default. + +.. + +.. date: 2026-04-01-11-05-36 +.. gh-issue: 146613 +.. nonce: GzjUFK +.. section: Library + +:mod:`itertools`: Fix a crash in :func:`itertools.groupby` when the grouper +iterator is concurrently mutated. + +.. + +.. date: 2026-03-31-19-54-32 +.. gh-issue: 147944 +.. nonce: 3dn8GZ +.. section: Library + +Accepted range for the *bytes_per_sep* argument of :meth:`bytes.hex`, +:meth:`bytearray.hex`, :meth:`memoryview.hex`, and :func:`binascii.b2a_hex` +is now increased, so passing ``sys.maxsize`` and ``-sys.maxsize`` is now +valid. + +.. + +.. date: 2026-03-28-13-19-20 +.. gh-issue: 146080 +.. nonce: srN12a +.. section: Library + +:mod:`ssl`: fix a crash when an SNI callback tries to use an SSL object that +has already been garbage-collected. Patch by Bénédikt Tran. + +.. + +.. date: 2026-03-28-12-20-19 +.. gh-issue: 146556 +.. nonce: Y8Eson +.. section: Library + +Fix :func:`annotationlib.get_annotations` hanging indefinitely when called +with ``eval_str=True`` on a callable that has a circular ``__wrapped__`` +chain (e.g. ``f.__wrapped__ = f``). Cycle detection using an id-based +visited set now stops the traversal and falls back to the globals found so +far, mirroring the approach of :func:`inspect.unwrap`. + +.. + +.. date: 2026-03-28-12-05-34 +.. gh-issue: 146090 +.. nonce: wf9_ef +.. section: Library + +:mod:`sqlite3`: fix a crash when :meth:`sqlite3.Connection.create_collation` +fails with `SQLITE_BUSY `__. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-03-28-12-01-48 +.. gh-issue: 146090 +.. nonce: wh1qJR +.. section: Library + +:mod:`sqlite3`: properly raise :exc:`MemoryError` instead of +:exc:`SystemError` when a context callback fails to be allocated. Patch by +Bénédikt Tran. + +.. + +.. date: 2026-03-27-12-00-00 +.. gh-issue: 146507 +.. nonce: 1D95A7 +.. section: Library + +Make :meth:`asyncio.SelectorEventLoop` stream transport's +:meth:`~asyncio.WriteTransport.get_write_buffer_size` O(1) by maintaining a +running byte counter instead of iterating the buffer on every call. + +.. + +.. date: 2026-03-26-14-51-55 +.. gh-issue: 145056 +.. nonce: QS-6l1 +.. section: Library + +Fix merging of :class:`collections.OrderedDict` and :class:`frozendict`. + +.. + +.. date: 2026-03-26-14-44-07 +.. gh-issue: 145056 +.. nonce: L9KPC3 +.. section: Library + +Add support for merging :class:`collections.UserDict` and +:class:`frozendict`. + +.. + +.. date: 2026-03-26-11-04-42 +.. gh-issue: 145633 +.. nonce: RWjlaX +.. section: Library + +Fix ``struct.pack('f', float)``: use :c:func:`PyFloat_Pack4` to raise +:exc:`OverflowError`. Patch by Sergey B Kirpichev and Victor Stinner. + +.. + +.. date: 2026-03-26-02-06-52 +.. gh-issue: 146440 +.. nonce: HXjhQO +.. section: Library + +:mod:`json`: Add the *array_hook* parameter to :func:`~json.load` and +:func:`~json.loads` functions: allow a callback for JSON literal array types +to customize Python lists in the resulting decoded object. Passing combined +:class:`frozendict` to *object_pairs_hook* param and :class:`tuple` to +``array_hook`` will yield a deeply nested immutable Python structure +representing the JSON data. + +.. + +.. date: 2026-03-25-21-08-51 +.. gh-issue: 146431 +.. nonce: zERPwe +.. section: Library + +Add the *wrapcol* parameter to :mod:`base64` functions +:func:`~base64.b16encode`, :func:`~base64.b32encode`, +:func:`~base64.b32hexencode`, :func:`~base64.b85encode` and +:func:`~base64.z85encode`, and :mod:`binascii` functions +:func:`~binascii.b2a_base32` and :func:`~binascii.b2a_base85`. Add the +*ignorechars* parameter to :mod:`base64` functions +:func:`~base64.b16decode`, :func:`~base64.b32decode`, +:func:`~base64.b32hexdecode`, :func:`~base64.b85decode` and +:func:`~base64.z85decode`, and :mod:`binascii` functions +:func:`~binascii.a2b_hex`, :func:`~binascii.unhexlify`, +:func:`~binascii.a2b_base32` and :func:`~binascii.a2b_base85`. + +.. + +.. date: 2026-03-24-03-49-50 +.. gh-issue: 146310 +.. nonce: WhlDir +.. section: Library + +The :mod:`ensurepip` module no longer looks for ``pip-*.whl`` wheel packages +in the current directory. + +.. + +.. date: 2026-03-21-16-03-16 +.. gh-issue: 141510 +.. nonce: tKptA7 +.. section: Library + +Support :class:`frozendict` in :mod:`plistlib`, for serialization only. +Patch by Hugo van Kemenade. + +.. + +.. date: 2026-03-21-10-02-20 +.. gh-issue: 146238 +.. nonce: 2WpMOj +.. section: Library + +Support half-floats (type code ``'e'`` of the :mod:`struct` module) in the +:mod:`array` module. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-03-21-08-23-26 +.. gh-issue: 140947 +.. nonce: owZ4r_ +.. section: Library + +Fix incorrect contextvars handling in server tasks created by +:mod:`asyncio`. Patch by Kumar Aditya. + +.. + +.. date: 2026-03-21-06-21-38 +.. gh-issue: 146151 +.. nonce: yNpgml +.. section: Library + +Support the :c:expr:`float complex` and :c:expr:`double complex` C types in +the :mod:`array` module: formatting characters ``'F'`` and ``'D'`` +respectively. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-03-20-16-17-31 +.. gh-issue: 143387 +.. nonce: 9Waopa +.. section: Library + +In importlib.metadata, when a distribution file is corrupt and there is no +metadata file, calls to ``Distribution.metadata()`` (including implicit +calls from other properties like ``.name`` and ``.requires``) will now raise +a ``MetadataNotFound`` Exception. This allows callers to distinguish between +missing metadata and a degenerate (empty) metadata. Previously, if the file +was missing, an empty ``PackageMetadata`` would be returned and would be +indistinguishable from the presence of an empty file. + +.. + +.. date: 2026-03-20-14-53-00 +.. gh-issue: 146228 +.. nonce: OJVEDL +.. section: Library + +Cached FastPath objects in importlib.metadata are now cleared on fork, +avoiding broken references to zip files during fork. + +.. + +.. date: 2026-03-20-00-28-00 +.. gh-issue: 146171 +.. nonce: P5Jk2R7v +.. section: Library + +Nested :exc:`AttributeError` suggestions now include property-backed +attributes on nested objects without executing the property getter. + +.. + +.. date: 2026-03-18-23-54-36 +.. gh-issue: 145410 +.. nonce: NvLWj5 +.. section: Library + +On Windows, :func:`sysconfig.get_platform` now gets the platform from the +``_sysconfig`` module instead of parsing :data:`sys.version` string. Patch +by Victor Stinner. + +.. + +.. date: 2026-03-18-16-58-17 +.. gh-issue: 146091 +.. nonce: lBbo1L +.. section: Library + +Fix a bug in :func:`termios.tcsetwinsize` where passing a sequence that +raises an exception in ``__getitem__`` would cause a :exc:`SystemError` +instead of propagating the original exception. + +.. + +.. date: 2026-03-17-20-52-24 +.. gh-issue: 146083 +.. nonce: NxZa_c +.. section: Library + +Update bundled `libexpat `_ to version 2.7.5. + +.. + +.. date: 2026-03-17-20-41-27 +.. gh-issue: 146076 +.. nonce: yoBNnB +.. section: Library + +:mod:`zoneinfo`: fix crashes when deleting ``_weak_cache`` from a +:class:`zoneinfo.ZoneInfo` subclass. + +.. + +.. date: 2026-03-17-19-51-05 +.. gh-issue: 123471 +.. nonce: oY4UR5 +.. section: Library + +Make concurrent iteration over :class:`itertools.zip_longest` safe under +free-threading. + +.. + +.. date: 2026-03-17-19-30-45 +.. gh-issue: 146075 +.. nonce: 85sCSh +.. section: Library + +Errors when calling :func:`functools.partial` with a malformed keyword will +no longer crash the interpreter. + +.. + +.. date: 2026-03-17-11-46-20 +.. gh-issue: 146054 +.. nonce: udYcqn +.. section: Library + +Limit the size of :func:`encodings.search_function` cache. Found by OSS Fuzz +in :oss-fuzz:`493449985`. + +.. + +.. date: 2026-03-16-00-00-00 +.. gh-issue: 146004 +.. nonce: xOptProp +.. section: Library + +All :option:`-X` options from the Python command line are now propagated to +child processes spawned by :mod:`multiprocessing`, not just a hard-coded +subset. This makes the behavior consistent between default "spawn" and +"forkserver" start methods and the old "fork" start method. The options +that were previously not propagated are: ``context_aware_warnings``, +``cpu_count``, ``disable-remote-debug``, ``int_max_str_digits``, +``lazy_imports``, ``no_debug_ranges``, ``pathconfig_warnings``, ``perf``, +``perf_jit``, ``presite``, ``pycache_prefix``, ``thread_inherit_context``, +and ``warn_default_encoding``. + +.. + +.. date: 2026-03-15-16-38-48 +.. gh-issue: 145980 +.. nonce: mRze5H +.. section: Library + +Added the *alphabet* parameter in :func:`~binascii.b2a_base64`, +:func:`~binascii.a2b_base64`, :func:`~binascii.b2a_base85` and +:func:`~binascii.a2b_base85` and a number of ``*_ALPHABET`` constants in the +:mod:`binascii` module. Removed :func:`!b2a_z85` and :func:`!a2b_z85`. + +.. + +.. date: 2026-03-15-10-17-51 +.. gh-issue: 145968 +.. nonce: gZexry +.. section: Library + +Fix translation in :func:`base64.b64decode` when altchars overlaps with the +standard ones. + +.. + +.. date: 2026-03-15-00-00-00 +.. gh-issue: 145966 +.. nonce: tCI0uD4I +.. section: Library + +Non-:exc:`AttributeError` exceptions raised during dialect attribute lookup +in :mod:`csv` are no longer silently suppressed. + +.. + +.. date: 2026-03-12-21-01-48 +.. gh-issue: 145883 +.. nonce: lUvXcc +.. section: Library + +:mod:`zoneinfo`: Fix heap buffer overflow reads from malformed TZif data. +Found by OSS Fuzz, issues :oss-fuzz:`492245058` and :oss-fuzz:`492230068`. + +.. + +.. date: 2026-03-12-12-17-39 +.. gh-issue: 145850 +.. nonce: uW3stt +.. section: Library + +Changed some implementation details in :class:`struct.Struct`: calling it +with non-ASCII string format will now raise a :exc:`ValueError` instead of +:exc:`UnicodeEncodeError`, calling it with non-ASCII bytes format will now +raise a :exc:`ValueError` instead of :exc:`struct.error`, getting the +:attr:`!format` attribute of uninitialized object will now raise an +:exc:`AttributeError` instead of :exc:`RuntimeError`. + +.. + +.. date: 2026-03-11-10-25-32 +.. gh-issue: 123720 +.. nonce: TauFRx +.. section: Library + +asyncio: Fix :func:`asyncio.Server.serve_forever` shutdown regression. Since +3.12, cancelling ``serve_forever()`` could hang waiting for a handler +blocked on a read from a client that never closed (effectively requiring two +interrupts to stop); the shutdown sequence now ensures client streams are +closed so ``serve_forever()`` exits promptly and handlers observe EOF. + +.. + +.. date: 2026-03-10-19-50-59 +.. gh-issue: 138122 +.. nonce: CsoBEo +.. section: Library + +The ``profiling.sampling`` module now supports differential flamegraph +visualization via ``--diff-flamegraph`` to compare two profiling runs. +Functions are colored red (regressions), blue (improvements), gray +(neutral), or purple (new). Elided stacks show code paths that disappeared +between runs. + +.. + +.. date: 2026-03-10-14-57-15 +.. gh-issue: 145754 +.. nonce: YBL5Ko +.. section: Library + +Request signature during mock autospec with ``FORWARDREF`` annotation +format. This prevents runtime errors when an annotation uses a name that is +not defined at runtime. + +.. + +.. date: 2026-03-10-14-13-12 +.. gh-issue: 145750 +.. nonce: iQsTeX +.. section: Library + +Avoid undefined behaviour from signed integer overflow when parsing format +strings in the :mod:`struct` module. Found by OSS Fuzz in +:oss-fuzz:`488466741`. + +.. + +.. date: 2026-03-10-01-54-34 +.. gh-issue: 145719 +.. nonce: okJRoK +.. section: Library + +Add ``application/efi`` MIME type to :mod:`mimetypes`. + +.. + +.. date: 2026-03-10-01-48-12 +.. gh-issue: 145717 +.. nonce: dPc0Rt +.. section: Library + +Add a few Microsoft-specific MIME types. + +.. + +.. date: 2026-03-09-19-59-05 +.. gh-issue: 145703 +.. nonce: 4EEP7J +.. section: Library + +:mod:`asyncio`: Make sure that :meth:`loop.call_at ` +and :meth:`loop.call_later ` trigger scheduled +events on time when the clock resolution becomes too small. + +.. + +.. date: 2026-03-09-18-33-16 +.. gh-issue: 145697 +.. nonce: d6hFmm +.. section: Library + +Add ``application/sql`` and ``application/vnd.sqlite3`` into ``mimetypes``. + +.. + +.. date: 2026-03-09-00-00-00 +.. gh-issue: 145492 +.. nonce: 457Afc +.. section: Library + +Fix infinite recursion in :class:`collections.defaultdict` ``__repr__`` when +a ``defaultdict`` contains itself. Based on analysis by KowalskiThomas in +:gh:`145492`. + +.. + +.. date: 2026-03-08-00-00-00 +.. gh-issue: 145650 +.. nonce: LgRepr +.. section: Library + +Add :meth:`~object.__repr__` support to :class:`logging.Formatter` and +:class:`logging.Filter`, showing the format string and filter name +respectively. + +.. + +.. date: 2026-03-07-14-34-39 +.. gh-issue: 145587 +.. nonce: flFQ5- +.. section: Library + +Resolved a performance regression in ``multiprocessing.connection.wait`` on +Windows that caused infinite busy loops when called with no objects. The +function now properly yields control to the OS to conserve CPU resources. +Patch By Shrey Naithani + +.. + +.. date: 2026-03-07-02-44-52 +.. gh-issue: 145616 +.. nonce: x8Mf23 +.. section: Library + +Detect Android sysconfig ABI correctly on 32-bit ARM Android on 64-bit ARM +kernel + +.. + +.. date: 2026-03-05-14-13-10 +.. gh-issue: 145546 +.. nonce: 3tnlxx +.. section: Library + +Fix ``unittest.util.sorted_list_difference()`` to deduplicate remaining +elements when one input list is exhausted before the other. + +.. + +.. date: 2026-03-03-23-21-40 +.. gh-issue: 145446 +.. nonce: 0c-TJX +.. section: Library + +Now :mod:`functools` is safer in free-threaded build when using keywords in +:func:`functools.partial` + +.. + +.. date: 2026-02-26-20-13-16 +.. gh-issue: 145264 +.. nonce: 4pggX_ +.. section: Library + +Base64 decoder (see :func:`binascii.a2b_base64`, :func:`base64.b64decode`, +etc) no longer ignores excess data after the first padded quad in non-strict +(default) mode. Instead, in conformance with :rfc:`4648`, section 3.3, it +now ignores the pad character, "=", if it is present before the end of the +encoded data. + +.. + +.. date: 2026-02-23-21-28-12 +.. gh-issue: 145035 +.. nonce: J5UjS6 +.. section: Library + +Allows omitting the internal library ``_pyrepl`` with limited loss of +functionality. This allows complete removal of the modern REPL, which is an +unsupported configuration, but still desirable for some distributions. + +.. + +.. date: 2026-02-19-16-34-18 +.. gh-issue: 144270 +.. nonce: wJRtSr +.. section: Library + +Made the *tag* parameter of :class:`xml.etree.ElementTree.Element` and the +*parent* and *tag* parameters of :func:`xml.etree.ElementTree.SubElement` +positional-only, matching the behavior of the C accelerator. + +.. + +.. date: 2026-02-19-12-00-00 +.. gh-issue: 144984 +.. nonce: b93995c982 +.. section: Library + +Fix crash in :meth:`xml.parsers.expat.xmlparser.ExternalEntityParserCreate` +when an allocation fails. The error paths could dereference NULL +``handlers`` and double-decrement the parent parser's reference count. + +.. + +.. date: 2026-02-18-21-45-00 +.. gh-issue: 144975 +.. nonce: Ab3XyZ +.. section: Library + +:meth:`wave.Wave_write.setframerate` now validates the frame rate after +rounding to an integer, preventing values like ``0.5`` from being accepted +and causing confusing errors later. Patch by Michiel Beijen. + +.. + +.. date: 2026-02-17-03-43-07 +.. gh-issue: 140715 +.. nonce: twmcM_ +.. section: Library + +Add ``%n`` and ``%t`` support to :meth:`~datetime.datetime.strptime`. + +.. + +.. date: 2026-02-11-21-01-30 +.. gh-issue: 144259 +.. nonce: OAhOR8 +.. section: Library + +Fix inconsistent display of long multiline pasted content in the REPL. + +.. + +.. date: 2026-02-08-22-04-06 +.. gh-issue: 140814 +.. nonce: frzSpn +.. section: Library + +:func:`multiprocessing.freeze_support` no longer sets the default start +method as a side effect, which previously caused a subsequent +:func:`multiprocessing.set_start_method` call to raise :exc:`RuntimeError`. + +.. + +.. date: 2026-02-04-20-30-59 +.. gh-issue: 123471 +.. nonce: 1dnPvs +.. section: Library + +Make concurrent iteration over :class:`itertools.accumulate` safe under +free-threading. + +.. + +.. date: 2026-01-10-16-23-21 +.. gh-issue: 143715 +.. nonce: HZrfSA +.. section: Library + +Calling the ``Struct.__new__()`` without required argument now is +deprecated. Calling :meth:`~object.__init__` method on initialized +:class:`~struct.Struct` objects is deprecated. + +.. + +.. date: 2025-12-18-00-00-00 +.. gh-issue: 142763 +.. nonce: AJpZPVG5 +.. section: Library + +Fix a race condition between :class:`zoneinfo.ZoneInfo` creation and +:func:`zoneinfo.ZoneInfo.clear_cache` that could raise :exc:`KeyError`. + +.. + +.. date: 2025-11-18-06-35-53 +.. gh-issue: 141707 +.. nonce: DBmQIy +.. section: Library + +Don't change :class:`tarfile.TarInfo` type from ``AREGTYPE`` to ``DIRTYPE`` +when parsing GNU long name or link headers. + +.. + +.. date: 2025-11-15-23-14-30 +.. gh-issue: 138577 +.. nonce: KbShrt +.. section: Library + +:func:`getpass.getpass` with non-empty ``echo_char`` now handles keyboard +shortcuts including Ctrl+A/E (cursor movement), Ctrl+K/U (kill line), Ctrl+W +(erase word), and Ctrl+V (literal next) by reading the terminal's control +character settings and processing them appropriately in non-canonical mode. +Patch by Sanyam Khurana. + +.. + +.. date: 2025-10-13-16-43-36 +.. gh-issue: 140049 +.. nonce: VvmAzN +.. section: Library + +:func:`traceback.format_exception_only` now colorizes exception notes. + +.. + +.. date: 2025-10-11-11-50-59 +.. gh-issue: 139933 +.. nonce: 05MHlx +.. section: Library + +Improve :exc:`AttributeError` suggestions for classes with a custom +:meth:`~object.__dir__` method returning a list of unsortable values. Patch +by Bénédikt Tran. + +.. + +.. date: 2025-10-05-15-38-02 +.. gh-issue: 139633 +.. nonce: l3P839 +.. section: Library + +The :mod:`netrc` security check is now run once per parse rather than once +per entry. + +.. + +.. date: 2025-09-19-13-54-54 +.. gh-issue: 130472 +.. nonce: LODfdk +.. section: Library + +Add fancycompleter and enable it by default when using pyrepl. This gives +colored tab completion. + +.. + +.. date: 2025-02-07-00-48-07 +.. gh-issue: 112632 +.. nonce: 95MM0C +.. section: Library + +Add an *expand* keyword argument for :func:`pprint.pprint`, +:func:`pprint.pformat`, :func:`pprint.pp` by passing on all *kwargs* and +:class:`pprint.PrettyPrinter`. Contributed by Stefan Todoran and Semyon +Moroz. + +.. + +.. date: 2024-09-25-12-47-50 +.. gh-issue: 66419 +.. nonce: DVSukU +.. section: Library + +Optional argument with :ref:`nargs` equals to ``argparse.REMAINDER`` now +consumes all remaining arguments including ``'--'``. + +.. + +.. date: 2023-03-10-13-10-06 +.. gh-issue: 60729 +.. nonce: KCCHTe +.. section: Library + +Add support for floating point audio wave files in :mod:`wave`. + +.. + +.. bpo: 36461 +.. date: 2019-04-25-21-11-37 +.. nonce: TO5YyP +.. section: Library + +Make the target time of :meth:`timeit.Timer.autorange` configurable and add +``--target-time`` option to the command-line interface of :mod:`timeit`. + +.. + +.. date: 2026-03-25-00-00-00 +.. gh-issue: 126676 +.. nonce: 052336 +.. section: Documentation + +Expand :mod:`argparse` documentation for ``type=bool`` with a demonstration +of the surprising behavior and pointers to common alternatives. + +.. + +.. date: 2026-03-09-00-00-00 +.. gh-issue: 145649 +.. nonce: 8BcbAB +.. section: Documentation + +Fix text wrapping and formatting of ``-X`` option descriptions in the +:manpage:`python(1)` man page by using proper roff markup. + +.. + +.. date: 2026-04-03-21-37-18 +.. gh-issue: 144418 +.. nonce: PusC0S +.. section: Tests + +The Android testbed's emulator RAM has been increased from 2 GB to 4 GB. + +.. + +.. date: 2026-03-24-00-15-58 +.. gh-issue: 146202 +.. nonce: LgH6Bj +.. section: Tests + +Fix a race condition in regrtest: make sure that the temporary directory is +created in the worker process. Previously, temp_cwd() could fail on Windows +if the "build" directory was not created. Patch by Victor Stinner. + +.. + +.. date: 2026-03-28-02-48-51 +.. gh-issue: 146541 +.. nonce: k-zlM6 +.. section: Build + +The Android testbed can now be built for 32-bit ARM and x86 targets. + +.. + +.. date: 2026-03-27-06-55-10 +.. gh-issue: 146498 +.. nonce: uOiCab +.. section: Build + +The iOS XCframework build script now ensures libpython isn't included in +installed app content, and is more robust in identifying standard library +binary content that requires processing. + +.. + +.. date: 2026-03-26-14-35-29 +.. gh-issue: 146450 +.. nonce: 9Kmp5Q +.. section: Build + +The Android build script was modified to improve parity with other platform +build scripts. + +.. + +.. date: 2026-03-26-12-48-42 +.. gh-issue: 146446 +.. nonce: 0GyMu4 +.. section: Build + +The clean target for the Apple/iOS XCframework build script is now more +selective when targeting a single architecture. + +.. + +.. date: 2026-03-26-12-27-42 +.. gh-issue: 146444 +.. nonce: JKJuEa +.. section: Build + +The Apple/iOS build script has been moved to the Platforms directory. + +.. + +.. date: 2026-03-23-20-06-35 +.. gh-issue: 146210 +.. nonce: C01Rmq +.. section: Build + +Fix building the jit stencils on Windows when the interpreter is built with +a different clang version. Patch by Chris Eibl. + +.. + +.. date: 2026-03-12-12-30-24 +.. gh-issue: 145844 +.. nonce: VOPeCU +.. section: Build + +Update to WASI SDK 32. + +.. + +.. date: 2026-03-11-11-58-42 +.. gh-issue: 145801 +.. nonce: iCXa3v +.. section: Build + +When Python build is optimized with GCC using PGO, use +``-fprofile-update=atomic`` option to use atomic operations when updating +profile information. This option reduces the risk of gcov Data Files (.gcda) +corruption which can cause random GCC crashes. Patch by Victor Stinner. + +.. + +.. date: 2026-03-10-16-58-55 +.. gh-issue: 138850 +.. nonce: CkqTw6 +.. section: Build + +Add :option:`--disable-epoll` to ``configure`` + +.. + +.. date: 2026-03-08-06-18-26 +.. gh-issue: 145633 +.. nonce: Ogu-RF +.. section: Build + +Remove support for ancient ARM platforms (ARMv4L and ARMv5L OABI boards), +using mixed-endian representation for doubles. Patch by Sergey B Kirpichev. + +.. + +.. date: 2026-01-08-22-27-07 +.. gh-issue: 85277 +.. nonce: TotySi +.. section: Build + +Fix building without ``stropts.h`` or empty ``stropts.h`` + +.. + +.. date: 2025-10-19-23-44-46 +.. gh-issue: 140131 +.. nonce: AABF2k +.. section: Windows + +Fix REPL cursor position on Windows when module completion suggestion line +hits console width. + +.. + +.. date: 2025-10-17-01-07-03 +.. gh-issue: 137586 +.. nonce: kVzxvp +.. section: macOS + +Invoke :program:`osascript` with absolute path in :mod:`webbrowser` and +:mod:`!turtledemo`. + +.. + +.. date: 2026-03-22-00-00-00 +.. gh-issue: 135953 +.. nonce: IptOwg +.. section: Tools/Demos + +Properly identify the main thread in the Gecko profiler collector by using a +status flag from the interpreter state instead of relying on +:func:`threading.main_thread` in the collector process. + +.. + +.. date: 2026-03-15-20-59-29 +.. gh-issue: 145976 +.. nonce: rEdUI- +.. section: Tools/Demos + +Remove :file:`Misc/indent.pro`, a configuration file for GNU +:manpage:`indent(1)`. + +.. + +.. date: 2026-03-15-11-32-35 +.. gh-issue: 145976 +.. nonce: mqhzmB +.. section: Tools/Demos + +Remove :file:`Misc/vgrindefs` and :file:`Misc/Porting`. + +.. + +.. date: 2026-03-31-13-33-41 +.. gh-issue: 146636 +.. nonce: 5do3wt +.. section: C API + +The :c:data:`Py_mod_abi` slot is now mandatory for modules created from a +slots array (using :c:func:`PyModule_FromSlotsAndSpec` or the +:c:func:`PyModExport_* ` export hook). + +.. + +.. date: 2026-03-19-16-50-27 +.. gh-issue: 146175 +.. nonce: pISQGX +.. section: C API + +The following macros are :term:`soft deprecated`: :c:macro:`Py_ALIGNED`, +:c:macro:`PY_FORMAT_SIZE_T`, :c:macro:`Py_LL`, :c:macro:`Py_ULL`, +:c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`, +:c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`, +:c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`, +:c:macro:`Py_UNICODE_SIZE`, :c:macro:`Py_VA_COPY`. + +The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal, is +:term:`soft deprecated` instead. + +.. + +.. date: 2026-03-18-23-44-29 +.. gh-issue: 146143 +.. nonce: pwIrJq +.. section: C API + +:c:func:`PyUnicodeWriter_WriteUCS4` now accepts a pointer to a constant +buffer of ``Py_UCS4``. + +.. + +.. date: 2026-03-18-20-18-59 +.. gh-issue: 146056 +.. nonce: nnZIgp +.. section: C API + +:c:func:`PyUnicodeWriter_WriteRepr` now supports ``NULL`` argument. + +.. + +.. date: 2026-02-19-18-39-11 +.. gh-issue: 145010 +.. nonce: mKzjci +.. section: C API + +Use GCC dialect alternatives for inline assembly in ``object.h`` so that the +Python headers compile correctly with ``-masm=intel``. diff --git a/Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst b/Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst deleted file mode 100644 index 538995538d7..00000000000 --- a/Misc/NEWS.d/next/Build/2026-01-08-22-27-07.gh-issue-85277.TotySi.rst +++ /dev/null @@ -1 +0,0 @@ -Fix building without ``stropts.h`` or empty ``stropts.h`` diff --git a/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst b/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst deleted file mode 100644 index 2c4da1b60c0..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove support for ancient ARM platforms (ARMv4L and ARMv5L OABI boards), -using mixed-endian representation -for doubles. Patch by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Build/2026-03-10-16-58-55.gh-issue-138850.CkqTw6.rst b/Misc/NEWS.d/next/Build/2026-03-10-16-58-55.gh-issue-138850.CkqTw6.rst deleted file mode 100644 index 256f13b2877..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-10-16-58-55.gh-issue-138850.CkqTw6.rst +++ /dev/null @@ -1 +0,0 @@ -Add :option:`--disable-epoll` to ``configure`` diff --git a/Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst b/Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst deleted file mode 100644 index c5f3982cc54..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-11-11-58-42.gh-issue-145801.iCXa3v.rst +++ /dev/null @@ -1,4 +0,0 @@ -When Python build is optimized with GCC using PGO, use -``-fprofile-update=atomic`` option to use atomic operations when updating -profile information. This option reduces the risk of gcov Data Files (.gcda) -corruption which can cause random GCC crashes. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst b/Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst deleted file mode 100644 index 10fac03be32..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-12-12-30-24.gh-issue-145844.VOPeCU.rst +++ /dev/null @@ -1 +0,0 @@ -Update to WASI SDK 32. diff --git a/Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst b/Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst deleted file mode 100644 index ce59a9a3a57..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-23-20-06-35.gh-issue-146210.C01Rmq.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix building the jit stencils on Windows when the interpreter is built with -a different clang version. Patch by Chris Eibl. diff --git a/Misc/NEWS.d/next/Build/2026-03-26-12-27-42.gh-issue-146444.JKJuEa.rst b/Misc/NEWS.d/next/Build/2026-03-26-12-27-42.gh-issue-146444.JKJuEa.rst deleted file mode 100644 index 40489f41a2a..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-26-12-27-42.gh-issue-146444.JKJuEa.rst +++ /dev/null @@ -1 +0,0 @@ -The Apple/iOS build script has been moved to the Platforms directory. diff --git a/Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst b/Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst deleted file mode 100644 index 40795650b53..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst +++ /dev/null @@ -1,2 +0,0 @@ -The clean target for the Apple/iOS XCframework build script is now more -selective when targeting a single architecture. diff --git a/Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst b/Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst deleted file mode 100644 index 32cb5b8221a..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-26-14-35-29.gh-issue-146450.9Kmp5Q.rst +++ /dev/null @@ -1,2 +0,0 @@ -The Android build script was modified to improve parity with other platform -build scripts. diff --git a/Misc/NEWS.d/next/Build/2026-03-27-06-55-10.gh-issue-146498.uOiCab.rst b/Misc/NEWS.d/next/Build/2026-03-27-06-55-10.gh-issue-146498.uOiCab.rst deleted file mode 100644 index 35deccd8976..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-27-06-55-10.gh-issue-146498.uOiCab.rst +++ /dev/null @@ -1,3 +0,0 @@ -The iOS XCframework build script now ensures libpython isn't included in -installed app content, and is more robust in identifying standard library -binary content that requires processing. diff --git a/Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst b/Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst deleted file mode 100644 index 351071b0bec..00000000000 --- a/Misc/NEWS.d/next/Build/2026-03-28-02-48-51.gh-issue-146541.k-zlM6.rst +++ /dev/null @@ -1 +0,0 @@ -The Android testbed can now be built for 32-bit ARM and x86 targets. diff --git a/Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst b/Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst deleted file mode 100644 index 7f5be699c63..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-02-19-18-39-11.gh-issue-145010.mKzjci.rst +++ /dev/null @@ -1,2 +0,0 @@ -Use GCC dialect alternatives for inline assembly in ``object.h`` so that the -Python headers compile correctly with ``-masm=intel``. diff --git a/Misc/NEWS.d/next/C_API/2026-03-18-20-18-59.gh-issue-146056.nnZIgp.rst b/Misc/NEWS.d/next/C_API/2026-03-18-20-18-59.gh-issue-146056.nnZIgp.rst deleted file mode 100644 index 7c5fc7a0538..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-03-18-20-18-59.gh-issue-146056.nnZIgp.rst +++ /dev/null @@ -1 +0,0 @@ -:c:func:`PyUnicodeWriter_WriteRepr` now supports ``NULL`` argument. diff --git a/Misc/NEWS.d/next/C_API/2026-03-18-23-44-29.gh-issue-146143.pwIrJq.rst b/Misc/NEWS.d/next/C_API/2026-03-18-23-44-29.gh-issue-146143.pwIrJq.rst deleted file mode 100644 index 930d90ff9a2..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-03-18-23-44-29.gh-issue-146143.pwIrJq.rst +++ /dev/null @@ -1,2 +0,0 @@ -:c:func:`PyUnicodeWriter_WriteUCS4` now accepts a pointer to a constant buffer -of ``Py_UCS4``. diff --git a/Misc/NEWS.d/next/C_API/2026-03-19-16-50-27.gh-issue-146175.pISQGX.rst b/Misc/NEWS.d/next/C_API/2026-03-19-16-50-27.gh-issue-146175.pISQGX.rst deleted file mode 100644 index 3563347141d..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-03-19-16-50-27.gh-issue-146175.pISQGX.rst +++ /dev/null @@ -1,12 +0,0 @@ -The following macros are :term:`soft deprecated`: -:c:macro:`Py_ALIGNED`, -:c:macro:`PY_FORMAT_SIZE_T`, -:c:macro:`Py_LL`, :c:macro:`Py_ULL`, -:c:macro:`PY_LONG_LONG`, :c:macro:`PY_LLONG_MIN`, :c:macro:`PY_LLONG_MAX`, -:c:macro:`PY_ULLONG_MAX`, :c:macro:`PY_INT32_T`, :c:macro:`PY_UINT32_T`, -:c:macro:`PY_INT64_T`, :c:macro:`PY_UINT64_T`, :c:macro:`PY_SIZE_MAX`, -:c:macro:`Py_UNICODE_SIZE`, -:c:macro:`Py_VA_COPY`. - -The macro :c:macro:`Py_UNICODE_WIDE`, which was scheduled for removal, is -:term:`soft deprecated` instead. diff --git a/Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst b/Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst deleted file mode 100644 index 8f8b832b8ba..00000000000 --- a/Misc/NEWS.d/next/C_API/2026-03-31-13-33-41.gh-issue-146636.5do3wt.rst +++ /dev/null @@ -1,3 +0,0 @@ -The :c:data:`Py_mod_abi` slot is now mandatory for modules created from a -slots array (using :c:func:`PyModule_FromSlotsAndSpec` or the -:c:func:`PyModExport_* ` export hook). diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst deleted file mode 100644 index aadf57622a4..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-01-01-49-52.gh-issue-140870.iknc12.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add support for module attributes in the :term:`REPL` auto-completion of -imports. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst deleted file mode 100644 index aa126e7e25b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-02-16-23-17.gh-issue-140594.YIWUpl.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an out of bounds read when a single NUL character is read from the standard input. -Patch by Shamil Abdulaev. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-07-23-07-17.gh-issue-126910.d8zdm-.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-07-23-07-17.gh-issue-126910.d8zdm-.rst deleted file mode 100644 index c86bfdb306f..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-07-23-07-17.gh-issue-126910.d8zdm-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Set frame pointers in ``x86_64-unknown-linux-gnu`` JIT code, allowing -most native profilers and debuggers to unwind through them. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst deleted file mode 100644 index 4d5249ffe3a..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash when calling :class:`SimpleNamespace.__replace__() -` on non-namespace instances. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-31-15-15-43.gh-issue-143414.Jgl4xu.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-31-15-15-43.gh-issue-143414.Jgl4xu.rst deleted file mode 100644 index 91f66e68bc9..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-31-15-15-43.gh-issue-143414.Jgl4xu.rst +++ /dev/null @@ -1 +0,0 @@ -Add tracking to the JIT optimizer to determine whether a reference is uniquely owned or shared diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-01-19-50.gh-issue-131798.PaWDNH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-01-19-50.gh-issue-131798.PaWDNH.rst deleted file mode 100644 index fe80c2d911b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-01-19-50.gh-issue-131798.PaWDNH.rst +++ /dev/null @@ -1 +0,0 @@ -Optimize ``_ITER_CHECK_RANGE`` and ``_ITER_CHECK_LIST`` in the JIT diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst deleted file mode 100644 index c00b7b99f8e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-13-07-08.gh-issue-69605.4aL4hn.rst +++ /dev/null @@ -1 +0,0 @@ -Add :mod:`math.integer` to :term:`REPL` auto-completion of imports. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst deleted file mode 100644 index 5b7293b5671..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-15-51-16.gh-issue-134584.6WFSuB.rst +++ /dev/null @@ -1 +0,0 @@ -Eliminate redundant refcounting for ``MATCH_CLASS`` in the JIT. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst deleted file mode 100644 index 2a565c1d02b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst +++ /dev/null @@ -1 +0,0 @@ -In free-threaded build, fix race condition when calling :meth:`!__sizeof__` on a :class:`list` diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst deleted file mode 100644 index 2cf83eff310..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-09-00-00-00.gh-issue-145713.KR6azvzI.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make :meth:`bytearray.resize` thread-safe in the free-threaded build by -using a critical section and calling the lock-held variant of the resize -function. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst deleted file mode 100644 index da34b67c952..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-12-52-06.gh-issue-145685.80B7gK.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve scaling of type attribute lookups in the :term:`free-threaded build` by -avoiding contention on the internal type lock. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst deleted file mode 100644 index ce9aa286068..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-19-00-39.gh-issue-145783.dS5TM9.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an unlikely crash in the parser when certain errors were erroneously not -propagated. Found by OSS Fuzz in :oss-fuzz:`491369109`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-22-38-40.gh-issue-145779.5375381d80.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-22-38-40.gh-issue-145779.5375381d80.rst deleted file mode 100644 index 9cd0263a107..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-10-22-38-40.gh-issue-145779.5375381d80.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve scaling of :func:`classmethod` and :func:`staticmethod` calls in -the free-threaded build by avoiding the descriptor ``__get__`` call. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst deleted file mode 100644 index 827224dc71e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid a pathological case where repeated calls at a specific stack depth could be significantly slower. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst deleted file mode 100644 index bd42f32d6ae..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-19-09-47.gh-issue-145792.X5KUhc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix out-of-bounds access when invoking faulthandler on a CPython build -compiled without support for VLAs. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst deleted file mode 100644 index 476be205da8..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-21-27-28.gh-issue-145376.LfDvyw.rst +++ /dev/null @@ -1 +0,0 @@ -Fix GC tracking in ``structseq.__replace__()``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst deleted file mode 100644 index 9808a27e9ea..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-09-48-57.gh-issue-127958.U-znTv.rst +++ /dev/null @@ -1 +0,0 @@ -Support tracing from function entrypoints in the JIT. Patch by Ken Jin. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-12-24-17.gh-issue-145876.LWFO2K.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-12-24-17.gh-issue-145876.LWFO2K.rst deleted file mode 100644 index 86579634fa1..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-13-12-24-17.gh-issue-145876.LWFO2K.rst +++ /dev/null @@ -1,3 +0,0 @@ -:exc:`AttributeError`\ s and :exc:`KeyError`\ s raised in :meth:`!keys` or :meth:`!__getitem__` -during dictionary unpacking (``{**mymapping}`` or ``func(**mymapping)``) are -no longer masked by :exc:`TypeError`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst deleted file mode 100644 index f66c156b4bc..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-20-47-34.gh-issue-145990.14BUzw.rst +++ /dev/null @@ -1 +0,0 @@ -``python --help-xoptions`` is now sorted by ``-X`` option name. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst deleted file mode 100644 index 21b9a524d00..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-21-45-35.gh-issue-145990.tmXwRB.rst +++ /dev/null @@ -1 +0,0 @@ -``python --help-env`` sections are now sorted by environment variable name. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-00-00-00.gh-issue-146041.7799bb.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-00-00-00.gh-issue-146041.7799bb.rst deleted file mode 100644 index 812f023266b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-00-00-00.gh-issue-146041.7799bb.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix free-threading scaling bottleneck in :func:`sys.intern` and -:c:func:`PyObject_SetAttr` by avoiding the interpreter-wide lock when the string -is already interned and immortalized. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-14-20-56.gh-issue-145059.aB3xKm.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-14-20-56.gh-issue-145059.aB3xKm.rst deleted file mode 100644 index e2db5a83a1a..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-14-20-56.gh-issue-145059.aB3xKm.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed ``sys.lazy_modules`` to include lazy modules without submodules. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-18-18-52-00.gh-issue-146056.r1tVSo.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-18-18-52-00.gh-issue-146056.r1tVSo.rst deleted file mode 100644 index ab6eab2c968..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-18-18-52-00.gh-issue-146056.r1tVSo.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`repr` for lists and tuples containing ``NULL``\ s. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst deleted file mode 100644 index 8d7e177c614..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed segmentation fault when called repr for BaseExceptionGroup with empty -or 1-size tuple args. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-16-16-40.gh-issue-135871.jSExZ3.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-16-16-40.gh-issue-135871.jSExZ3.rst deleted file mode 100644 index 29103e46906..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-16-16-40.gh-issue-135871.jSExZ3.rst +++ /dev/null @@ -1 +0,0 @@ -Improve multithreaded scaling of PyMutex in low-contention scenarios by reloading the lock's internal state, without slowing down high-contention scenarios. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-00-39-25.gh-issue-146192.8aQ6sC.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-00-39-25.gh-issue-146192.8aQ6sC.rst deleted file mode 100644 index 304a7cd6210..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-00-39-25.gh-issue-146192.8aQ6sC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add Base32 support to :mod:`binascii` and improve the performance of the -Base32 converters in :mod:`base64`. Patch by James Seo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-11-34-17.gh-issue-145667._Agp9o.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-11-34-17.gh-issue-145667._Agp9o.rst deleted file mode 100644 index cedd8bfe6ce..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-11-34-17.gh-issue-145667._Agp9o.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the ``GET_ITER_YIELD_FROM`` instruction, modifying ``SEND`` to pair -with ``GET_ITER`` when compiling ``yield from`` expressions. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-26-24.gh-issue-146199.vV8V9s.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-26-24.gh-issue-146199.vV8V9s.rst deleted file mode 100644 index 0611a0d6a6d..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-26-24.gh-issue-146199.vV8V9s.rst +++ /dev/null @@ -1 +0,0 @@ -Comparison of code objects now handles errors correctly. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-52-55.gh-issue-146205.M4yKdf.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-52-55.gh-issue-146205.M4yKdf.rst deleted file mode 100644 index e9d95cdf836..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-12-52-55.gh-issue-146205.M4yKdf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a bug where :meth:`select.epoll.close`, :meth:`select.kqueue.close`, -and :meth:`select.devpoll.close` silently ignored errors. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-07-33.gh-issue-146227.MqBPEo.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-07-33.gh-issue-146227.MqBPEo.rst deleted file mode 100644 index 11e19eb2831..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-07-33.gh-issue-146227.MqBPEo.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix wrong type in ``_Py_atomic_load_uint16`` in the C11 atomics backend -(``pyatomic_std.h``), which used a 32-bit atomic load instead of 16-bit. -Found by Mohammed Zuhaib. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-55-14.gh-issue-146196.Zg70Kb.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-55-14.gh-issue-146196.Zg70Kb.rst deleted file mode 100644 index 9e03c1bbb0e..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-20-13-55-14.gh-issue-146196.Zg70Kb.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix potential Undefined Behavior in :c:func:`PyUnicodeWriter_WriteASCII` by -adding a zero-length check. Patch by Shamil Abdulaev. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-11-58.gh-issue-146151.4-lhim.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-11-58.gh-issue-146151.4-lhim.rst deleted file mode 100644 index d4a65d31511..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-11-58.gh-issue-146151.4-lhim.rst +++ /dev/null @@ -1,3 +0,0 @@ -:class:`memoryview` now supports the :c:expr:`float complex` and -:c:expr:`double complex` C types: formatting characters ``'F'`` and ``'D'`` -respectively. Patch by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-48-25.gh-issue-146245.cqM3_4.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-48-25.gh-issue-146245.cqM3_4.rst deleted file mode 100644 index f52eaa0d6c7..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-08-48-25.gh-issue-146245.cqM3_4.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed reference leaks in :mod:`socket` when audit hooks raise exceptions in :func:`socket.getaddrinfo` and :meth:`!socket.sendto`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-11-55-16.gh-issue-146250.ahl3O2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-11-55-16.gh-issue-146250.ahl3O2.rst deleted file mode 100644 index fff07b31ec2..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-11-55-16.gh-issue-146250.ahl3O2.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a memory leak in :exc:`SyntaxError` when re-initializing it. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst deleted file mode 100644 index 931e1ac92ce..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-15-05-14.gh-issue-146128.DG1Hfa.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a bug which could cause constant values to be partially corrupted in -AArch64 JIT code. This issue is theoretical, and hasn't actually been -observed in unmodified Python interpreters. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-12-00-00.gh-issue-146306.870ef4.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-12-00-00.gh-issue-146306.870ef4.rst deleted file mode 100644 index de2c3e56ac3..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-12-00-00.gh-issue-146306.870ef4.rst +++ /dev/null @@ -1,3 +0,0 @@ -Optimize float arithmetic in the JIT by mutating uniquely-referenced -operands in place, avoiding allocation of a new float object. Speeds up -the pyperformance ``nbody`` benchmark by ~19%. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-19-30-00.gh-issue-146308.AxnRVA.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-19-30-00.gh-issue-146308.AxnRVA.rst deleted file mode 100644 index 9bc2f1c59a8..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-22-19-30-00.gh-issue-146308.AxnRVA.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fixed multiple error handling issues in the :mod:`!_remote_debugging` module -including a double-free in code object caching, memory leaks on allocation -failure, missing exception checks in binary format varint decoding, reference -leaks on error paths in frame chain processing, and inconsistent thread status -error reporting across platforms. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-24-13-06-52.gh-issue-146369.6wDI6S.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-24-13-06-52.gh-issue-146369.6wDI6S.rst deleted file mode 100644 index 191b7627ed4..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-24-13-06-52.gh-issue-146369.6wDI6S.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure ``-X lazy_imports=none``` and ``PYTHON_LAZY_IMPORTS=none``` override -``__lazy_modules__``. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-11-18-45.gh-issue-146388.O0u1c3.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-11-18-45.gh-issue-146388.O0u1c3.rst deleted file mode 100644 index 7cf5edfe8c6..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-26-11-18-45.gh-issue-146388.O0u1c3.rst +++ /dev/null @@ -1 +0,0 @@ -Adds a null check to handle when the JIT optimizer runs out of space when dealing with contradictions in ``make_bottom``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-27-17-14-18.gh-issue-126910.hooVFQ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-27-17-14-18.gh-issue-126910.hooVFQ.rst deleted file mode 100644 index e3ddf394088..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-27-17-14-18.gh-issue-126910.hooVFQ.rst +++ /dev/null @@ -1 +0,0 @@ -Set frame pointers in ``aarch64-unknown-linux-gnu`` JIT code, allowing most native profilers and debuggers to unwind through them. Patch by Diego Russo diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst deleted file mode 100644 index a33dee5c875..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-29-11-39-05.gh-issue-146587.YJicXt.rst +++ /dev/null @@ -1 +0,0 @@ -Fix type slot assignment incase of multiple slots for same name in type object implementation. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst deleted file mode 100644 index fdbdb6a285f..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-30-20-00-00.gh-issue-146306.C45609.rst +++ /dev/null @@ -1,3 +0,0 @@ -Optimize compact integer arithmetic in the JIT by mutating -uniquely-referenced operands in place, avoiding allocation of a new int -object. Speeds up the pyperformance ``spectral_norm`` benchmark by ~10%. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst deleted file mode 100644 index 7a205f1d6dd..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-01-06-35.gh-issue-146615.fix-method-get.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a crash in :meth:`~object.__get__` for :c:expr:`METH_METHOD` descriptors -when an invalid (non-type) object is passed as the second argument. -Patch by Steven Sun. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst deleted file mode 100644 index 67ebd57b3a5..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-31-18-07-53.gh-issue-147856.62Dwee.rst +++ /dev/null @@ -1 +0,0 @@ -Allow the *count* argument of :meth:`bytes.replace` to be a keyword. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst deleted file mode 100644 index a94dfca5e2a..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-35-55.gh-issue-147985.YVirHJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make :c:func:`PySet_Contains` attempt a lock-free lookup, similar to -:meth:`!set.__contains__`. This avoids acquiring the set object mutex in the -normal case. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst deleted file mode 100644 index f3f07ab35db..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-01-12-52-31.gh-issue-144319.iZk4hs.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a bug that could cause applications with specific allocation patterns to -leak memory via Huge Pages if compiled with Huge Page support. Patch by -Pablo Galindo diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst deleted file mode 100644 index fea4659d0b9..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-20-59-12.gh-issue-148083.9ZHNBN.rst +++ /dev/null @@ -1 +0,0 @@ -Constant-fold ``_CONTAINS_OP_SET`` for :class:`frozenset`. Patch by Donghee Na. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst deleted file mode 100644 index dc7df0e4a29..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-04-22-20-00.gh-issue-148110.cL5x2Q.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`sys.set_lazy_imports_filter` so relative lazy imports pass the -resolved imported module name to the filter callback. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst deleted file mode 100644 index 17c6f882f24..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-00-00-00.gh-issue-148072.xid9Pe.rst +++ /dev/null @@ -1,4 +0,0 @@ -Cache ``pickle.dumps`` and ``pickle.loads`` per interpreter in the XIData -framework, avoiding repeated module lookups on every cross-interpreter data -transfer. This speeds up :class:`~concurrent.futures.InterpreterPoolExecutor` -for mutable types (``list``, ``dict``) by 1.7x--3.3x. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst deleted file mode 100644 index beda992a95b..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-15-20-00.gh-issue-148144.f7qA0x.rst +++ /dev/null @@ -1,3 +0,0 @@ -Initialize ``_PyInterpreterFrame.visited`` when copying interpreter frames so -incremental GC does not read an uninitialized byte from generator and -frame-object copies. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst deleted file mode 100644 index 9eccef3ef9d..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-00-00-00.gh-issue-100239.binopxt.rst +++ /dev/null @@ -1,3 +0,0 @@ -Propagate result type and uniqueness information through -``_BINARY_OP_EXTEND`` in the tier 2 optimizer, enabling elimination of -downstream type guards and selection of inplace float operations. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst deleted file mode 100644 index 6565291eb99..00000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-06-11-15-46.gh-issue-148157.JFnZDn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an unlikely crash when parsing an invalid type comments for function -parameters. Found by OSS Fuzz in :oss-fuzz:`492782951`. diff --git a/Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst b/Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst deleted file mode 100644 index 33061f7dd15..00000000000 --- a/Misc/NEWS.d/next/Documentation/2026-03-09-00-00-00.gh-issue-145649.8BcbAB.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix text wrapping and formatting of ``-X`` option descriptions in the -:manpage:`python(1)` man page by using proper roff markup. diff --git a/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst b/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst deleted file mode 100644 index d2e275fdf08..00000000000 --- a/Misc/NEWS.d/next/Documentation/2026-03-25-00-00-00.gh-issue-126676.052336.rst +++ /dev/null @@ -1,2 +0,0 @@ -Expand :mod:`argparse` documentation for ``type=bool`` with a demonstration -of the surprising behavior and pointers to common alternatives. diff --git a/Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst b/Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst deleted file mode 100644 index e78f6601807..00000000000 --- a/Misc/NEWS.d/next/Library/2019-04-25-21-11-37.bpo-36461.TO5YyP.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make the target time of :meth:`timeit.Timer.autorange` configurable -and add ``--target-time`` option to the command-line interface of -:mod:`timeit`. diff --git a/Misc/NEWS.d/next/Library/2023-03-10-13-10-06.gh-issue-60729.KCCHTe.rst b/Misc/NEWS.d/next/Library/2023-03-10-13-10-06.gh-issue-60729.KCCHTe.rst deleted file mode 100644 index 82876cd81e4..00000000000 --- a/Misc/NEWS.d/next/Library/2023-03-10-13-10-06.gh-issue-60729.KCCHTe.rst +++ /dev/null @@ -1 +0,0 @@ -Add support for floating point audio wave files in :mod:`wave`. diff --git a/Misc/NEWS.d/next/Library/2024-09-25-12-47-50.gh-issue-66419.DVSukU.rst b/Misc/NEWS.d/next/Library/2024-09-25-12-47-50.gh-issue-66419.DVSukU.rst deleted file mode 100644 index ceac0616599..00000000000 --- a/Misc/NEWS.d/next/Library/2024-09-25-12-47-50.gh-issue-66419.DVSukU.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optional argument with :ref:`nargs` equals to ``argparse.REMAINDER`` now -consumes all remaining arguments including ``'--'``. diff --git a/Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst b/Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst deleted file mode 100644 index 0842c8e3a04..00000000000 --- a/Misc/NEWS.d/next/Library/2025-02-07-00-48-07.gh-issue-112632.95MM0C.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add an *expand* keyword argument for :func:`pprint.pprint`, -:func:`pprint.pformat`, :func:`pprint.pp` by passing on all *kwargs* and -:class:`pprint.PrettyPrinter`. Contributed by Stefan Todoran and Semyon Moroz. diff --git a/Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst b/Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst deleted file mode 100644 index 3d2a7f00d3e..00000000000 --- a/Misc/NEWS.d/next/Library/2025-09-19-13-54-54.gh-issue-130472.LODfdk.rst +++ /dev/null @@ -1 +0,0 @@ -Add fancycompleter and enable it by default when using pyrepl. This gives colored tab completion. diff --git a/Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst b/Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst deleted file mode 100644 index 94bd18074f8..00000000000 --- a/Misc/NEWS.d/next/Library/2025-10-05-15-38-02.gh-issue-139633.l3P839.rst +++ /dev/null @@ -1,2 +0,0 @@ -The :mod:`netrc` security check is now run once per parse rather than once -per entry. diff --git a/Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst b/Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst deleted file mode 100644 index d76f0873d77..00000000000 --- a/Misc/NEWS.d/next/Library/2025-10-11-11-50-59.gh-issue-139933.05MHlx.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improve :exc:`AttributeError` suggestions for classes with a custom -:meth:`~object.__dir__` method returning a list of unsortable values. -Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2025-10-13-16-43-36.gh-issue-140049.VvmAzN.rst b/Misc/NEWS.d/next/Library/2025-10-13-16-43-36.gh-issue-140049.VvmAzN.rst deleted file mode 100644 index d9489fd0baa..00000000000 --- a/Misc/NEWS.d/next/Library/2025-10-13-16-43-36.gh-issue-140049.VvmAzN.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`traceback.format_exception_only` now colorizes exception notes. diff --git a/Misc/NEWS.d/next/Library/2025-11-15-23-14-30.gh-issue-138577.KbShrt.rst b/Misc/NEWS.d/next/Library/2025-11-15-23-14-30.gh-issue-138577.KbShrt.rst deleted file mode 100644 index df24f62982a..00000000000 --- a/Misc/NEWS.d/next/Library/2025-11-15-23-14-30.gh-issue-138577.KbShrt.rst +++ /dev/null @@ -1,4 +0,0 @@ -:func:`getpass.getpass` with non-empty ``echo_char`` now handles keyboard shortcuts -including Ctrl+A/E (cursor movement), Ctrl+K/U (kill line), Ctrl+W (erase word), -and Ctrl+V (literal next) by reading the terminal's control character settings -and processing them appropriately in non-canonical mode. Patch by Sanyam Khurana. diff --git a/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst b/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst deleted file mode 100644 index 1f5b8ed90b8..00000000000 --- a/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst +++ /dev/null @@ -1,2 +0,0 @@ -Don't change :class:`tarfile.TarInfo` type from ``AREGTYPE`` to ``DIRTYPE`` when parsing -GNU long name or link headers. diff --git a/Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst b/Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst deleted file mode 100644 index a5330365e3e..00000000000 --- a/Misc/NEWS.d/next/Library/2025-12-18-00-00-00.gh-issue-142763.AJpZPVG5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a race condition between :class:`zoneinfo.ZoneInfo` creation and -:func:`zoneinfo.ZoneInfo.clear_cache` that could raise :exc:`KeyError`. diff --git a/Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst b/Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst deleted file mode 100644 index 90aae6bee83..00000000000 --- a/Misc/NEWS.d/next/Library/2026-01-10-16-23-21.gh-issue-143715.HZrfSA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Calling the ``Struct.__new__()`` without required argument now is deprecated. -Calling :meth:`~object.__init__` method on initialized :class:`~struct.Struct` -objects is deprecated. diff --git a/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst b/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst deleted file mode 100644 index d650103e28e..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst +++ /dev/null @@ -1 +0,0 @@ -Make concurrent iteration over :class:`itertools.accumulate` safe under free-threading. diff --git a/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst b/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst deleted file mode 100644 index 6077de8ac9a..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`multiprocessing.freeze_support` no longer sets the default start method -as a side effect, which previously caused a subsequent -:func:`multiprocessing.set_start_method` call to raise :exc:`RuntimeError`. diff --git a/Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst b/Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst deleted file mode 100644 index 280f3b742b0..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-11-21-01-30.gh-issue-144259.OAhOR8.rst +++ /dev/null @@ -1 +0,0 @@ -Fix inconsistent display of long multiline pasted content in the REPL. diff --git a/Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst b/Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst deleted file mode 100644 index 3bebc6660df..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-17-03-43-07.gh-issue-140715.twmcM_.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``%n`` and ``%t`` support to :meth:`~datetime.datetime.strptime`. diff --git a/Misc/NEWS.d/next/Library/2026-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst b/Misc/NEWS.d/next/Library/2026-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst deleted file mode 100644 index 37658064c2c..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-18-21-45-00.gh-issue-144975.Ab3XyZ.rst +++ /dev/null @@ -1,3 +0,0 @@ -:meth:`wave.Wave_write.setframerate` now validates the frame rate after -rounding to an integer, preventing values like ``0.5`` from being accepted -and causing confusing errors later. Patch by Michiel Beijen. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst b/Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst deleted file mode 100644 index 66e07dc3098..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-12-00-00.gh-issue-144984.b93995c982.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix crash in :meth:`xml.parsers.expat.xmlparser.ExternalEntityParserCreate` -when an allocation fails. The error paths could dereference NULL ``handlers`` -and double-decrement the parent parser's reference count. diff --git a/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst b/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst deleted file mode 100644 index b8a4374bc2d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst +++ /dev/null @@ -1,3 +0,0 @@ -Made the *tag* parameter of :class:`xml.etree.ElementTree.Element` and the -*parent* and *tag* parameters of :func:`xml.etree.ElementTree.SubElement` -positional-only, matching the behavior of the C accelerator. diff --git a/Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst b/Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst deleted file mode 100644 index b20da3b54c0..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-23-21-28-12.gh-issue-145035.J5UjS6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Allows omitting the internal library ``_pyrepl`` with limited loss of -functionality. This allows complete removal of the modern REPL, which is an -unsupported configuration, but still desirable for some distributions. diff --git a/Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst b/Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst deleted file mode 100644 index 22d53fe8db1..00000000000 --- a/Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst +++ /dev/null @@ -1,4 +0,0 @@ -Base64 decoder (see :func:`binascii.a2b_base64`, :func:`base64.b64decode`, etc) no -longer ignores excess data after the first padded quad in non-strict -(default) mode. Instead, in conformance with :rfc:`4648`, section 3.3, it now ignores -the pad character, "=", if it is present before the end of the encoded data. diff --git a/Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst b/Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst deleted file mode 100644 index 96eb0d9ddb0..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-03-23-21-40.gh-issue-145446.0c-TJX.rst +++ /dev/null @@ -1 +0,0 @@ -Now :mod:`functools` is safer in free-threaded build when using keywords in :func:`functools.partial` diff --git a/Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst b/Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst deleted file mode 100644 index e9401bb08c6..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-05-14-13-10.gh-issue-145546.3tnlxx.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``unittest.util.sorted_list_difference()`` to deduplicate remaining -elements when one input list is exhausted before the other. diff --git a/Misc/NEWS.d/next/Library/2026-03-07-02-44-52.gh-issue-145616.x8Mf23.rst b/Misc/NEWS.d/next/Library/2026-03-07-02-44-52.gh-issue-145616.x8Mf23.rst deleted file mode 100644 index 131570a0e03..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-07-02-44-52.gh-issue-145616.x8Mf23.rst +++ /dev/null @@ -1 +0,0 @@ -Detect Android sysconfig ABI correctly on 32-bit ARM Android on 64-bit ARM kernel diff --git a/Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst b/Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst deleted file mode 100644 index c17d01f36b8..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-07-14-34-39.gh-issue-145587.flFQ5-.rst +++ /dev/null @@ -1 +0,0 @@ -Resolved a performance regression in ``multiprocessing.connection.wait`` on Windows that caused infinite busy loops when called with no objects. The function now properly yields control to the OS to conserve CPU resources. Patch By Shrey Naithani diff --git a/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst b/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst deleted file mode 100644 index 243834d0bbd..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :meth:`~object.__repr__` support to :class:`logging.Formatter` and -:class:`logging.Filter`, showing the format string and filter name -respectively. diff --git a/Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst b/Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst deleted file mode 100644 index 297ee4099f1..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145492.457Afc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix infinite recursion in :class:`collections.defaultdict` ``__repr__`` -when a ``defaultdict`` contains itself. Based on analysis by KowalskiThomas -in :gh:`145492`. diff --git a/Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst b/Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst deleted file mode 100644 index c3a476df75f..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-09-18-33-16.gh-issue-145697.d6hFmm.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``application/sql`` and ``application/vnd.sqlite3`` into ``mimetypes``. diff --git a/Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst b/Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst deleted file mode 100644 index bc239ce58c9..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-09-19-59-05.gh-issue-145703.4EEP7J.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`asyncio`: Make sure that :meth:`loop.call_at ` and -:meth:`loop.call_later ` trigger scheduled events on -time when the clock resolution becomes too small. diff --git a/Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst b/Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst deleted file mode 100644 index 55ef5206c99..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-10-01-48-12.gh-issue-145717.dPc0Rt.rst +++ /dev/null @@ -1 +0,0 @@ -Add a few Microsoft-specific MIME types. diff --git a/Misc/NEWS.d/next/Library/2026-03-10-01-54-34.gh-issue-145719.okJRoK.rst b/Misc/NEWS.d/next/Library/2026-03-10-01-54-34.gh-issue-145719.okJRoK.rst deleted file mode 100644 index b7e82a45675..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-10-01-54-34.gh-issue-145719.okJRoK.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``application/efi`` MIME type to :mod:`mimetypes`. diff --git a/Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst b/Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst deleted file mode 100644 index a909bea2caf..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-10-14-13-12.gh-issue-145750.iQsTeX.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid undefined behaviour from signed integer overflow when parsing format -strings in the :mod:`struct` module. Found by OSS Fuzz in -:oss-fuzz:`488466741`. diff --git a/Misc/NEWS.d/next/Library/2026-03-10-14-57-15.gh-issue-145754.YBL5Ko.rst b/Misc/NEWS.d/next/Library/2026-03-10-14-57-15.gh-issue-145754.YBL5Ko.rst deleted file mode 100644 index 7de81ac19c2..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-10-14-57-15.gh-issue-145754.YBL5Ko.rst +++ /dev/null @@ -1,2 +0,0 @@ -Request signature during mock autospec with ``FORWARDREF`` annotation format. -This prevents runtime errors when an annotation uses a name that is not defined at runtime. diff --git a/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst b/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst deleted file mode 100644 index 2059557e8bb..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-10-19-50-59.gh-issue-138122.CsoBEo.rst +++ /dev/null @@ -1,4 +0,0 @@ -The ``profiling.sampling`` module now supports differential flamegraph -visualization via ``--diff-flamegraph`` to compare two profiling runs. -Functions are colored red (regressions), blue (improvements), gray (neutral), -or purple (new). Elided stacks show code paths that disappeared between runs. diff --git a/Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst b/Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst deleted file mode 100644 index 04e6a377dd8..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-11-10-25-32.gh-issue-123720.TauFRx.rst +++ /dev/null @@ -1,5 +0,0 @@ -asyncio: Fix :func:`asyncio.Server.serve_forever` shutdown regression. Since -3.12, cancelling ``serve_forever()`` could hang waiting for a handler blocked -on a read from a client that never closed (effectively requiring two -interrupts to stop); the shutdown sequence now ensures client streams are -closed so ``serve_forever()`` exits promptly and handlers observe EOF. diff --git a/Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst b/Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst deleted file mode 100644 index 35ba57a95b0..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-12-12-17-39.gh-issue-145850.uW3stt.rst +++ /dev/null @@ -1,6 +0,0 @@ -Changed some implementation details in :class:`struct.Struct`: calling it -with non-ASCII string format will now raise a :exc:`ValueError` instead of -:exc:`UnicodeEncodeError`, calling it with non-ASCII bytes format will now -raise a :exc:`ValueError` instead of :exc:`struct.error`, getting -the :attr:`!format` attribute of uninitialized object will now raise an -:exc:`AttributeError` instead of :exc:`RuntimeError`. diff --git a/Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst b/Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst deleted file mode 100644 index 2c17768c518..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-12-21-01-48.gh-issue-145883.lUvXcc.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`zoneinfo`: Fix heap buffer overflow reads from malformed TZif data. -Found by OSS Fuzz, issues :oss-fuzz:`492245058` and :oss-fuzz:`492230068`. diff --git a/Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.rst b/Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.rst deleted file mode 100644 index c0d4907ada0..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-15-00-00-00.gh-issue-145966.tCI0uD4I.rst +++ /dev/null @@ -1,2 +0,0 @@ -Non-:exc:`AttributeError` exceptions raised during dialect attribute lookup -in :mod:`csv` are no longer silently suppressed. diff --git a/Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst b/Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst deleted file mode 100644 index 9eae1dc4008..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-15-10-17-51.gh-issue-145968.gZexry.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix translation in :func:`base64.b64decode` when altchars overlaps with the -standard ones. diff --git a/Misc/NEWS.d/next/Library/2026-03-15-16-38-48.gh-issue-145980.mRze5H.rst b/Misc/NEWS.d/next/Library/2026-03-15-16-38-48.gh-issue-145980.mRze5H.rst deleted file mode 100644 index e6984619f83..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-15-16-38-48.gh-issue-145980.mRze5H.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added the *alphabet* parameter in :func:`~binascii.b2a_base64`, -:func:`~binascii.a2b_base64`, :func:`~binascii.b2a_base85` and -:func:`~binascii.a2b_base85` and a number of ``*_ALPHABET`` constants in the -:mod:`binascii` module. Removed :func:`!b2a_z85` and -:func:`!a2b_z85`. diff --git a/Misc/NEWS.d/next/Library/2026-03-16-00-00-00.gh-issue-146004.xOptProp.rst b/Misc/NEWS.d/next/Library/2026-03-16-00-00-00.gh-issue-146004.xOptProp.rst deleted file mode 100644 index 234e6102c6a..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-16-00-00-00.gh-issue-146004.xOptProp.rst +++ /dev/null @@ -1,9 +0,0 @@ -All :option:`-X` options from the Python command line are now propagated to -child processes spawned by :mod:`multiprocessing`, not just a hard-coded -subset. This makes the behavior consistent between default "spawn" and -"forkserver" start methods and the old "fork" start method. The options -that were previously not propagated are: ``context_aware_warnings``, -``cpu_count``, ``disable-remote-debug``, ``int_max_str_digits``, -``lazy_imports``, ``no_debug_ranges``, ``pathconfig_warnings``, ``perf``, -``perf_jit``, ``presite``, ``pycache_prefix``, ``thread_inherit_context``, -and ``warn_default_encoding``. diff --git a/Misc/NEWS.d/next/Library/2026-03-17-11-46-20.gh-issue-146054.udYcqn.rst b/Misc/NEWS.d/next/Library/2026-03-17-11-46-20.gh-issue-146054.udYcqn.rst deleted file mode 100644 index 8692c7f171d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-17-11-46-20.gh-issue-146054.udYcqn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Limit the size of :func:`encodings.search_function` cache. -Found by OSS Fuzz in :oss-fuzz:`493449985`. diff --git a/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst b/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst deleted file mode 100644 index 792ea3ad668..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst +++ /dev/null @@ -1 +0,0 @@ -Errors when calling :func:`functools.partial` with a malformed keyword will no longer crash the interpreter. diff --git a/Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.rst b/Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.rst deleted file mode 100644 index 8d2e1b970e8..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.rst +++ /dev/null @@ -1 +0,0 @@ -Make concurrent iteration over :class:`itertools.zip_longest` safe under free-threading. diff --git a/Misc/NEWS.d/next/Library/2026-03-17-20-41-27.gh-issue-146076.yoBNnB.rst b/Misc/NEWS.d/next/Library/2026-03-17-20-41-27.gh-issue-146076.yoBNnB.rst deleted file mode 100644 index 746f5b27882..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-17-20-41-27.gh-issue-146076.yoBNnB.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`zoneinfo`: fix crashes when deleting ``_weak_cache`` from a -:class:`zoneinfo.ZoneInfo` subclass. diff --git a/Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst b/Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst deleted file mode 100644 index 6805a40a03e..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst +++ /dev/null @@ -1 +0,0 @@ -Update bundled `libexpat `_ to version 2.7.5. diff --git a/Misc/NEWS.d/next/Library/2026-03-18-16-58-17.gh-issue-146091.lBbo1L.rst b/Misc/NEWS.d/next/Library/2026-03-18-16-58-17.gh-issue-146091.lBbo1L.rst deleted file mode 100644 index 2ed3ea8f90e..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-18-16-58-17.gh-issue-146091.lBbo1L.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a bug in :func:`termios.tcsetwinsize` where passing a sequence that -raises an exception in ``__getitem__`` would cause a :exc:`SystemError` -instead of propagating the original exception. diff --git a/Misc/NEWS.d/next/Library/2026-03-18-23-54-36.gh-issue-145410.NvLWj5.rst b/Misc/NEWS.d/next/Library/2026-03-18-23-54-36.gh-issue-145410.NvLWj5.rst deleted file mode 100644 index 8d84b70097d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-18-23-54-36.gh-issue-145410.NvLWj5.rst +++ /dev/null @@ -1,3 +0,0 @@ -On Windows, :func:`sysconfig.get_platform` now gets the platform from the -``_sysconfig`` module instead of parsing :data:`sys.version` string. Patch -by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-03-20-00-28-00.gh-issue-146171.P5Jk2R7v.rst b/Misc/NEWS.d/next/Library/2026-03-20-00-28-00.gh-issue-146171.P5Jk2R7v.rst deleted file mode 100644 index 9514085bd3d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-20-00-28-00.gh-issue-146171.P5Jk2R7v.rst +++ /dev/null @@ -1,2 +0,0 @@ -Nested :exc:`AttributeError` suggestions now include property-backed -attributes on nested objects without executing the property getter. diff --git a/Misc/NEWS.d/next/Library/2026-03-20-14-53-00.gh-issue-146228.OJVEDL.rst b/Misc/NEWS.d/next/Library/2026-03-20-14-53-00.gh-issue-146228.OJVEDL.rst deleted file mode 100644 index 1356e2ca07d..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-20-14-53-00.gh-issue-146228.OJVEDL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Cached FastPath objects in importlib.metadata are now cleared on fork, -avoiding broken references to zip files during fork. diff --git a/Misc/NEWS.d/next/Library/2026-03-20-16-17-31.gh-issue-143387.9Waopa.rst b/Misc/NEWS.d/next/Library/2026-03-20-16-17-31.gh-issue-143387.9Waopa.rst deleted file mode 100644 index 16bab047424..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-20-16-17-31.gh-issue-143387.9Waopa.rst +++ /dev/null @@ -1,7 +0,0 @@ -In importlib.metadata, when a distribution file is corrupt and there is no -metadata file, calls to ``Distribution.metadata()`` (including implicit -calls from other properties like ``.name`` and ``.requires``) will now raise -a ``MetadataNotFound`` Exception. This allows callers to distinguish between -missing metadata and a degenerate (empty) metadata. Previously, if the file -was missing, an empty ``PackageMetadata`` would be returned and would be -indistinguishable from the presence of an empty file. diff --git a/Misc/NEWS.d/next/Library/2026-03-21-06-21-38.gh-issue-146151.yNpgml.rst b/Misc/NEWS.d/next/Library/2026-03-21-06-21-38.gh-issue-146151.yNpgml.rst deleted file mode 100644 index 020b7d7d6cc..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-21-06-21-38.gh-issue-146151.yNpgml.rst +++ /dev/null @@ -1,3 +0,0 @@ -Support the :c:expr:`float complex` and :c:expr:`double complex` C types -in the :mod:`array` module: formatting characters ``'F'`` and ``'D'`` -respectively. Patch by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Library/2026-03-21-08-23-26.gh-issue-140947.owZ4r_.rst b/Misc/NEWS.d/next/Library/2026-03-21-08-23-26.gh-issue-140947.owZ4r_.rst deleted file mode 100644 index 88e787e8549..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-21-08-23-26.gh-issue-140947.owZ4r_.rst +++ /dev/null @@ -1 +0,0 @@ -Fix incorrect contextvars handling in server tasks created by :mod:`asyncio`. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst b/Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst deleted file mode 100644 index 35e951e38e4..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-21-10-02-20.gh-issue-146238.2WpMOj.rst +++ /dev/null @@ -1,2 +0,0 @@ -Support half-floats (type code ``'e'`` of the :mod:`struct` module) in the -:mod:`array` module. Patch by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst b/Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst deleted file mode 100644 index 19c30f11b33..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-21-16-03-16.gh-issue-141510.tKptA7.rst +++ /dev/null @@ -1,2 +0,0 @@ -Support :class:`frozendict` in :mod:`plistlib`, for serialization only. -Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2026-03-24-03-49-50.gh-issue-146310.WhlDir.rst b/Misc/NEWS.d/next/Library/2026-03-24-03-49-50.gh-issue-146310.WhlDir.rst deleted file mode 100644 index b7125955852..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-24-03-49-50.gh-issue-146310.WhlDir.rst +++ /dev/null @@ -1,2 +0,0 @@ -The :mod:`ensurepip` module no longer looks for ``pip-*.whl`` wheel packages -in the current directory. diff --git a/Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst b/Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst deleted file mode 100644 index 6268a52926f..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-25-21-08-51.gh-issue-146431.zERPwe.rst +++ /dev/null @@ -1,11 +0,0 @@ -Add the *wrapcol* parameter to :mod:`base64` functions -:func:`~base64.b16encode`, :func:`~base64.b32encode`, -:func:`~base64.b32hexencode`, :func:`~base64.b85encode` and -:func:`~base64.z85encode`, and :mod:`binascii` functions -:func:`~binascii.b2a_base32` and :func:`~binascii.b2a_base85`. Add the -*ignorechars* parameter to :mod:`base64` functions -:func:`~base64.b16decode`, :func:`~base64.b32decode`, -:func:`~base64.b32hexdecode`, :func:`~base64.b85decode` and -:func:`~base64.z85decode`, and :mod:`binascii` functions -:func:`~binascii.a2b_hex`, :func:`~binascii.unhexlify`, -:func:`~binascii.a2b_base32` and :func:`~binascii.a2b_base85`. diff --git a/Misc/NEWS.d/next/Library/2026-03-26-02-06-52.gh-issue-146440.HXjhQO.rst b/Misc/NEWS.d/next/Library/2026-03-26-02-06-52.gh-issue-146440.HXjhQO.rst deleted file mode 100644 index 231c56fa063..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-26-02-06-52.gh-issue-146440.HXjhQO.rst +++ /dev/null @@ -1,6 +0,0 @@ -:mod:`json`: Add the *array_hook* parameter to :func:`~json.load` and -:func:`~json.loads` functions: -allow a callback for JSON literal array types to customize Python lists in the -resulting decoded object. Passing combined :class:`frozendict` to -*object_pairs_hook* param and :class:`tuple` to ``array_hook`` will yield a -deeply nested immutable Python structure representing the JSON data. diff --git a/Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.rst b/Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.rst deleted file mode 100644 index 00507fe89d0..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-26-11-04-42.gh-issue-145633.RWjlaX.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``struct.pack('f', float)``: use :c:func:`PyFloat_Pack4` to raise -:exc:`OverflowError`. Patch by Sergey B Kirpichev and Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst b/Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst deleted file mode 100644 index 66e31117e33..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-26-14-44-07.gh-issue-145056.L9KPC3.rst +++ /dev/null @@ -1 +0,0 @@ -Add support for merging :class:`collections.UserDict` and :class:`frozendict`. diff --git a/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst b/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst deleted file mode 100644 index 4eaabfbb9a8..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst +++ /dev/null @@ -1 +0,0 @@ -Fix merging of :class:`collections.OrderedDict` and :class:`frozendict`. diff --git a/Misc/NEWS.d/next/Library/2026-03-27-12-00-00.gh-issue-146507.1D95A7.rst b/Misc/NEWS.d/next/Library/2026-03-27-12-00-00.gh-issue-146507.1D95A7.rst deleted file mode 100644 index f0aae2068fc..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-27-12-00-00.gh-issue-146507.1D95A7.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make :meth:`asyncio.SelectorEventLoop` stream transport's -:meth:`~asyncio.WriteTransport.get_write_buffer_size` O(1) by maintaining a -running byte counter instead of iterating the buffer on every call. diff --git a/Misc/NEWS.d/next/Library/2026-03-28-12-01-48.gh-issue-146090.wh1qJR.rst b/Misc/NEWS.d/next/Library/2026-03-28-12-01-48.gh-issue-146090.wh1qJR.rst deleted file mode 100644 index a6d60d2c929..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-28-12-01-48.gh-issue-146090.wh1qJR.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`sqlite3`: properly raise :exc:`MemoryError` instead of :exc:`SystemError` -when a context callback fails to be allocated. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-03-28-12-05-34.gh-issue-146090.wf9_ef.rst b/Misc/NEWS.d/next/Library/2026-03-28-12-05-34.gh-issue-146090.wf9_ef.rst deleted file mode 100644 index 5b835b0271a..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-28-12-05-34.gh-issue-146090.wf9_ef.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`sqlite3`: fix a crash when :meth:`sqlite3.Connection.create_collation` -fails with `SQLITE_BUSY `__. Patch by -Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-03-28-12-20-19.gh-issue-146556.Y8Eson.rst b/Misc/NEWS.d/next/Library/2026-03-28-12-20-19.gh-issue-146556.Y8Eson.rst deleted file mode 100644 index 71f84593edb..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-28-12-20-19.gh-issue-146556.Y8Eson.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix :func:`annotationlib.get_annotations` hanging indefinitely when called -with ``eval_str=True`` on a callable that has a circular ``__wrapped__`` -chain (e.g. ``f.__wrapped__ = f``). Cycle detection using an id-based -visited set now stops the traversal and falls back to the globals found -so far, mirroring the approach of :func:`inspect.unwrap`. diff --git a/Misc/NEWS.d/next/Library/2026-03-28-13-19-20.gh-issue-146080.srN12a.rst b/Misc/NEWS.d/next/Library/2026-03-28-13-19-20.gh-issue-146080.srN12a.rst deleted file mode 100644 index c80e8e05d48..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-28-13-19-20.gh-issue-146080.srN12a.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`ssl`: fix a crash when an SNI callback tries to use an SSL object that -has already been garbage-collected. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst b/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst deleted file mode 100644 index 7ba75bac79c..00000000000 --- a/Misc/NEWS.d/next/Library/2026-03-31-19-54-32.gh-issue-147944.3dn8GZ.rst +++ /dev/null @@ -1,4 +0,0 @@ -Accepted range for the *bytes_per_sep* argument of :meth:`bytes.hex`, -:meth:`bytearray.hex`, :meth:`memoryview.hex`, and :func:`binascii.b2a_hex` -is now increased, so passing ``sys.maxsize`` and ``-sys.maxsize`` is now -valid. diff --git a/Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst b/Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst deleted file mode 100644 index 94e198e7b28..00000000000 --- a/Misc/NEWS.d/next/Library/2026-04-01-11-05-36.gh-issue-146613.GzjUFK.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`itertools`: Fix a crash in :func:`itertools.groupby` when -the grouper iterator is concurrently mutated. diff --git a/Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst b/Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst deleted file mode 100644 index 8c50972d3ca..00000000000 --- a/Misc/NEWS.d/next/Library/2026-04-01-18-17-55.gh-issue-73613.PLEebm.rst +++ /dev/null @@ -1,7 +0,0 @@ -Add the *padded* parameter in functions related to Base32 and Base64 codecs -in the :mod:`binascii` and :mod:`base64` modules. -In the encoding functions it controls whether the pad character can be added -in the output, in the decoding functions it controls whether padding is -required in input. -Padding of input no longer required in :func:`base64.urlsafe_b64decode` -by default. diff --git a/Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst b/Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst deleted file mode 100644 index 7fd30562739..00000000000 --- a/Misc/NEWS.d/next/Library/2026-04-06-11-20-24.gh-issue-148153.ZtsuTl.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`base64.b32encode` now always raises :exc:`ValueError` instead of -:exc:`AssertionError` for the value of *map01* with invalid length. diff --git a/Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst b/Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst deleted file mode 100644 index fc73d1902ea..00000000000 --- a/Misc/NEWS.d/next/Library/2026-04-07-01-04-00.gh-issue-144503.argvfs.rst +++ /dev/null @@ -1,6 +0,0 @@ -Fix a regression introduced in 3.14.3 and 3.13.12 where the -:mod:`multiprocessing` ``forkserver`` start method would fail with -:exc:`BrokenPipeError` when the parent process had a very large -:data:`sys.argv`. The argv is now passed to the forkserver as separate -command-line arguments rather than being embedded in the ``-c`` command -string, avoiding the operating system's per-argument length limit. diff --git a/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst b/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst deleted file mode 100644 index c561023c3c2..00000000000 --- a/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst +++ /dev/null @@ -1 +0,0 @@ -Reject leading dashes in URLs passed to :func:`webbrowser.open`. diff --git a/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst b/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst deleted file mode 100644 index e53a932d12f..00000000000 --- a/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst +++ /dev/null @@ -1,4 +0,0 @@ -Reject control characters in :class:`http.cookies.Morsel` -:meth:`~http.cookies.Morsel.update` and -:meth:`~http.cookies.BaseCookie.js_output`. -This addresses :cve:`2026-3644`. diff --git a/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst b/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst deleted file mode 100644 index 79536d1fef5..00000000000 --- a/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst +++ /dev/null @@ -1,4 +0,0 @@ -:mod:`xml.parsers.expat`: Fixed a crash caused by unbounded C recursion when -converting deeply nested XML content models with -:meth:`~xml.parsers.expat.xmlparser.ElementDeclHandler`. -This addresses :cve:`2026-4224`. diff --git a/Misc/NEWS.d/next/Tests/2026-03-24-00-15-58.gh-issue-146202.LgH6Bj.rst b/Misc/NEWS.d/next/Tests/2026-03-24-00-15-58.gh-issue-146202.LgH6Bj.rst deleted file mode 100644 index ef869fe2617..00000000000 --- a/Misc/NEWS.d/next/Tests/2026-03-24-00-15-58.gh-issue-146202.LgH6Bj.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a race condition in regrtest: make sure that the temporary directory is -created in the worker process. Previously, temp_cwd() could fail on Windows if -the "build" directory was not created. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst b/Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst deleted file mode 100644 index dd72996d51a..00000000000 --- a/Misc/NEWS.d/next/Tests/2026-04-03-21-37-18.gh-issue-144418.PusC0S.rst +++ /dev/null @@ -1 +0,0 @@ -The Android testbed's emulator RAM has been increased from 2 GB to 4 GB. diff --git a/Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst b/Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst deleted file mode 100644 index 0d74776ff90..00000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2026-03-15-11-32-35.gh-issue-145976.mqhzmB.rst +++ /dev/null @@ -1 +0,0 @@ -Remove :file:`Misc/vgrindefs` and :file:`Misc/Porting`. diff --git a/Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst b/Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst deleted file mode 100644 index 17b0f2d797f..00000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2026-03-15-20-59-29.gh-issue-145976.rEdUI-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove :file:`Misc/indent.pro`, a configuration file for GNU -:manpage:`indent(1)`. diff --git a/Misc/NEWS.d/next/Tools-Demos/2026-03-22-00-00-00.gh-issue-135953.IptOwg.rst b/Misc/NEWS.d/next/Tools-Demos/2026-03-22-00-00-00.gh-issue-135953.IptOwg.rst deleted file mode 100644 index 50f39a830de..00000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2026-03-22-00-00-00.gh-issue-135953.IptOwg.rst +++ /dev/null @@ -1,3 +0,0 @@ -Properly identify the main thread in the Gecko profiler collector by -using a status flag from the interpreter state instead of relying on -:func:`threading.main_thread` in the collector process. diff --git a/Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst b/Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst deleted file mode 100644 index 3c2d30d8d98..00000000000 --- a/Misc/NEWS.d/next/Windows/2025-10-19-23-44-46.gh-issue-140131.AABF2k.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix REPL cursor position on Windows when module completion suggestion line -hits console width. diff --git a/Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst b/Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst deleted file mode 100644 index 8e42065392a..00000000000 --- a/Misc/NEWS.d/next/macOS/2025-10-17-01-07-03.gh-issue-137586.kVzxvp.rst +++ /dev/null @@ -1 +0,0 @@ -Invoke :program:`osascript` with absolute path in :mod:`webbrowser` and :mod:`!turtledemo`. diff --git a/README.rst b/README.rst index 1d2874e9ca4..710882bc84b 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.15.0 alpha 7 +This is Python version 3.15.0 alpha 8 ===================================== .. image:: https://github.com/python/cpython/actions/workflows/build.yml/badge.svg?branch=main&event=push From dfeb160bc35f0ba16800d07b85cb11598d1cd307 Mon Sep 17 00:00:00 2001 From: grayjk Date: Tue, 7 Apr 2026 09:05:23 -0400 Subject: [PATCH 447/775] gh-130273: Fix traceback color output with unicode characters (GH-142529) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Account for the display width of Unicode characters so that colors and underlining in traceback output is correct. Co-authored-by: Łukasz Langa Co-authored-by: Victor Stinner --- Lib/_pyrepl/utils.py | 1 + Lib/test/test_traceback.py | 87 +++++++++++++++++++ Lib/traceback.py | 70 +++++++++++---- ...-12-10-15-15-09.gh-issue-130273.iCfiY5.rst | 1 + 4 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-12-10-15-15-09.gh-issue-130273.iCfiY5.rst diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index 7175d57a9e3..d399b4cf53c 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -16,6 +16,7 @@ from .types import CharBuffer, CharWidths from .trace import trace + ANSI_ESCAPE_SEQUENCE = re.compile(r"\x1b\[[ -@]*[A-~]") ZERO_WIDTH_BRACKET = re.compile(r"\x01.*?\x02") ZERO_WIDTH_TRANS = str.maketrans({"\x01": "", "\x02": ""}) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 5dc11253e0d..909808825f0 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1790,6 +1790,7 @@ def f(): ] self.assertEqual(result_lines, expected) + class TestKeywordTypoSuggestions(unittest.TestCase): TYPO_CASES = [ ("with block ad something:\n pass", "and"), @@ -5414,6 +5415,92 @@ def expected(t, m, fn, l, f, E, e, z, n): ] self.assertEqual(actual, expected(**colors)) + def test_colorized_traceback_unicode(self): + try: + 啊哈=1; 啊哈/0#### + except Exception as e: + exc = traceback.TracebackException.from_exception(e) + + actual = "".join(exc.format(colorize=True)).splitlines() + def expected(t, m, fn, l, f, E, e, z, n): + return [ + f" 啊哈=1; {e}啊哈{z}{E}/{z}{e}0{z}####", + f" {e}~~~~{z}{E}^{z}{e}~{z}", + ] + self.assertEqual(actual[2:4], expected(**colors)) + + try: + ééééé/0 + except Exception as e: + exc = traceback.TracebackException.from_exception(e) + + actual = "".join(exc.format(colorize=True)).splitlines() + def expected(t, m, fn, l, f, E, e, z, n): + return [ + f" {E}ééééé{z}/0", + f" {E}^^^^^{z}", + ] + self.assertEqual(actual[2:4], expected(**colors)) + + def test_colorized_syntax_error_ascii_display_width(self): + """Caret alignment for ASCII edge cases handled by _wlen. + + The old ASCII fast track in _display_width returned the raw character + offset for ASCII strings, which is wrong for CTRL-Z (display width 2) + and ANSI escape sequences (display width 0). + """ + E = colors["E"] + z = colors["z"] + t = colors["t"] + m = colors["m"] + fn = colors["fn"] + l = colors["l"] + + def _make_syntax_error(text, offset, end_offset): + err = SyntaxError("invalid syntax") + err.filename = "" + err.lineno = 1 + err.end_lineno = 1 + err.text = text + err.offset = offset + err.end_offset = end_offset + return err + + # CTRL-Z (\x1a) is ASCII but displayed as ^Z (2 columns). + # Verify caret aligns when CTRL-Z precedes the error. + err = _make_syntax_error("a\x1a$\n", offset=3, end_offset=4) + exc = traceback.TracebackException.from_exception(err) + actual = "".join(exc.format(colorize=True)) + # 'a' (1 col) + '\x1a' (2 cols) = 3 cols before '$' + self.assertIn( + f' File {fn}""{z}, line {l}1{z}\n' + f' a\x1a{E}${z}\n' + f' {" " * 3}{E}^{z}\n' + f'{t}SyntaxError{z}: {m}invalid syntax{z}\n', + actual, + ) + + # CTRL-Z in the highlighted (error) region counts as 2 columns. + err = _make_syntax_error("$\x1a\n", offset=1, end_offset=3) + exc = traceback.TracebackException.from_exception(err) + actual = "".join(exc.format(colorize=True)) + # '$' (1 col) + '\x1a' (2 cols) = 3 columns of carets + self.assertIn( + f' {E}$\x1a{z}\n' + f' {E}{"^" * 3}{z}\n', + actual, + ) + + # ANSI escape sequences are ASCII but take 0 display columns. + err = _make_syntax_error("a\x1b[1mb$\n", offset=7, end_offset=8) + exc = traceback.TracebackException.from_exception(err) + actual = "".join(exc.format(colorize=True)) + # 'a' (1 col) + '\x1b[1m' (0 cols) + 'b' (1 col) = 2 before '$' + self.assertIn( + f' a\x1b[1mb{E}${z}\n' + f' {" " * 2}{E}^{z}\n', + actual, + ) class TestLazyImportSuggestions(unittest.TestCase): """Test that lazy imports are not reified when computing AttributeError suggestions.""" diff --git a/Lib/traceback.py b/Lib/traceback.py index 1f9f151ebf5..343d0e5f108 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1,9 +1,11 @@ """Extract, format and print information about Python stack traces.""" import collections.abc +import functools import itertools import linecache import os +import re import sys import textwrap import types @@ -684,12 +686,12 @@ def output_line(lineno): colorized_line_parts = [] colorized_carets_parts = [] - for color, group in itertools.groupby(itertools.zip_longest(line, carets, fillvalue=""), key=lambda x: x[1]): + for color, group in itertools.groupby(_zip_display_width(line, carets), key=lambda x: x[1]): caret_group = list(group) - if color == "^": + if "^" in color: colorized_line_parts.append(theme.error_highlight + "".join(char for char, _ in caret_group) + theme.reset) colorized_carets_parts.append(theme.error_highlight + "".join(caret for _, caret in caret_group) + theme.reset) - elif color == "~": + elif "~" in color: colorized_line_parts.append(theme.error_range + "".join(char for char, _ in caret_group) + theme.reset) colorized_carets_parts.append(theme.error_range + "".join(caret for _, caret in caret_group) + theme.reset) else: @@ -971,7 +973,54 @@ def setup_positions(expr, force_valid=True): return None -_WIDE_CHAR_SPECIFIERS = "WF" + +def _zip_display_width(line, carets): + carets = iter(carets) + if line.isascii() and '\x1a' not in line: + for char in line: + yield char, next(carets, "") + return + + import unicodedata + for char in unicodedata.iter_graphemes(line): + char = str(char) + char_width = _display_width(char) + yield char, "".join(itertools.islice(carets, char_width)) + + +@functools.cache +def _str_width(c: str) -> int: + # copied from _pyrepl.utils to fix gh-130273 + + if ord(c) < 128: + return 1 + import unicodedata + # gh-139246 for zero-width joiner and combining characters + if unicodedata.combining(c): + return 0 + category = unicodedata.category(c) + if category == "Cf" and c != "\u00ad": + return 0 + w = unicodedata.east_asian_width(c) + if w in ("N", "Na", "H", "A"): + return 1 + return 2 + + +_ANSI_ESCAPE_SEQUENCE = re.compile(r"\x1b\[[ -@]*[A-~]") + + +def _wlen(s: str) -> int: + # copied from _pyrepl.utils to fix gh-130273 + + if len(s) == 1 and s != "\x1a": + return _str_width(s) + length = sum(_str_width(i) for i in s) + # remove lengths of any escape sequences + sequence = _ANSI_ESCAPE_SEQUENCE.findall(s) + ctrl_z_cnt = s.count("\x1a") + return length - sum(len(i) for i in sequence) + ctrl_z_cnt + def _display_width(line, offset=None): """Calculate the extra amount of width space the given source @@ -979,18 +1028,9 @@ def _display_width(line, offset=None): width output device. Supports wide unicode characters and emojis.""" if offset is None: - offset = len(line) + return _wlen(line) - # Fast track for ASCII-only strings - if line.isascii(): - return offset - - import unicodedata - - return sum( - 2 if unicodedata.east_asian_width(char) in _WIDE_CHAR_SPECIFIERS else 1 - for char in line[:offset] - ) + return _wlen(line[:offset]) def _format_note(note, indent, theme): diff --git a/Misc/NEWS.d/next/Library/2025-12-10-15-15-09.gh-issue-130273.iCfiY5.rst b/Misc/NEWS.d/next/Library/2025-12-10-15-15-09.gh-issue-130273.iCfiY5.rst new file mode 100644 index 00000000000..2e0695334fd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-10-15-15-09.gh-issue-130273.iCfiY5.rst @@ -0,0 +1 @@ +Fix traceback color output with Unicode characters. From e65987d4c0d63585dd63e742ec3c8aa07645ffc5 Mon Sep 17 00:00:00 2001 From: Jonathan Dung Date: Tue, 7 Apr 2026 21:26:53 +0800 Subject: [PATCH 448/775] gh-146547: Use lazy imports in ctypes (GH-146548) --- Lib/ctypes/__init__.py | 3 ++- Lib/ctypes/_layout.py | 3 ++- Lib/ctypes/util.py | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 1c822759eca..6d7cb56f6c3 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -2,9 +2,10 @@ import os as _os import sys as _sys -import sysconfig as _sysconfig import types as _types +lazy import sysconfig as _sysconfig + from _ctypes import Union, Structure, Array from _ctypes import _Pointer from _ctypes import CFuncPtr as _CFuncPtr diff --git a/Lib/ctypes/_layout.py b/Lib/ctypes/_layout.py index 2048ccb6a1c..61b4c6c70fb 100644 --- a/Lib/ctypes/_layout.py +++ b/Lib/ctypes/_layout.py @@ -5,11 +5,12 @@ """ import sys -import warnings from _ctypes import CField, buffer_info import ctypes +lazy import warnings + def round_down(n, multiple): assert n >= 0 assert multiple > 0 diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 3b21658433b..35ac5b6bfd6 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -1,8 +1,9 @@ import os -import shutil -import subprocess import sys +lazy import shutil +lazy import subprocess + # find_library(name) returns the pathname of a library, or None. if os.name == "nt": From feee573f36ecdc767d73c95d43e68dd02e41549d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 7 Apr 2026 16:05:39 +0200 Subject: [PATCH 449/775] gh-148014: Accept a function name in -X presite option (#148015) --- Doc/c-api/init_config.rst | 6 +- Doc/using/cmdline.rst | 11 +- Lib/test/_test_embed_structseq.py | 29 +++-- Lib/test/cov.py | 8 +- Lib/test/libregrtest/runtests.py | 2 +- Lib/test/support/__init__.py | 2 +- Lib/test/test_cmd_line.py | 22 ++++ Lib/test/test_embed.py | 2 +- ...-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst | 2 + Python/pylifecycle.c | 120 ++++++++++++++++-- 10 files changed, 167 insertions(+), 37 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index f6dc604a609..209e48767cc 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -1807,10 +1807,10 @@ PyConfig .. c:member:: wchar_t* run_presite - ``package.module`` path to module that should be imported before - ``site.py`` is run. + ``module`` or ``module:func`` entry point that should be executed before + the :mod:`site` module is imported. - Set by the :option:`-X presite=package.module <-X>` command-line + Set by the :option:`-X presite=module:func <-X>` command-line option and the :envvar:`PYTHON_PRESITE` environment variable. The command-line option takes precedence. diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index d0355ce47a6..7cbc03f5f12 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -654,13 +654,17 @@ Miscellaneous options .. versionadded:: 3.13 - * :samp:`-X presite={package.module}` specifies a module that should be - imported before the :mod:`site` module is executed and before the + * :samp:`-X presite={module}` or :samp:`-X presite={module:func}` specifies + an entry point that should be executed before the :mod:`site` module is + executed and before the :mod:`__main__` module exists. Therefore, the imported module isn't :mod:`__main__`. This can be used to execute code early during Python initialization. Python needs to be :ref:`built in debug mode ` for this option to exist. See also :envvar:`PYTHON_PRESITE`. + .. versionchanged:: next + Accept also ``module:func`` entry point format. + .. versionadded:: 3.13 * :samp:`-X gil={0,1}` forces the GIL to be disabled or enabled, @@ -1458,4 +1462,7 @@ Debug-mode variables Needs Python configured with the :option:`--with-pydebug` build option. + .. versionchanged:: next + Accept also ``module:func`` entry point format. + .. versionadded:: 3.13 diff --git a/Lib/test/_test_embed_structseq.py b/Lib/test/_test_embed_structseq.py index 4cac84d7a46..c6050ca62aa 100644 --- a/Lib/test/_test_embed_structseq.py +++ b/Lib/test/_test_embed_structseq.py @@ -47,16 +47,21 @@ def test_sys_funcs(self): self.check_structseq(type(obj)) -try: - unittest.main( - module=( - '__main__' - if __name__ == '__main__' - # Avoiding a circular import: - else sys.modules['test._test_embed_structseq'] +def main(): + try: + unittest.main( + module=( + '__main__' + if __name__ == '__main__' + # Avoiding a circular import: + else sys.modules['test._test_embed_structseq'] + ) ) - ) -except SystemExit as exc: - if exc.args[0] != 0: - raise -print("Tests passed") + except SystemExit as exc: + if exc.args[0] != 0: + raise + print("Tests passed") + + +if __name__ == "__main__": + main() diff --git a/Lib/test/cov.py b/Lib/test/cov.py index e4699c7afe1..8717b1f20dd 100644 --- a/Lib/test/cov.py +++ b/Lib/test/cov.py @@ -1,8 +1,7 @@ """A minimal hook for gathering line coverage of the standard library. -Designed to be used with -Xpresite= which means: -* it installs itself on import -* it's not imported as `__main__` so can't use the ifmain idiom +Designed to be used with -Xpresite=test.cov:enable which means: + * it can't import anything besides `sys` to avoid tainting gathered coverage * filenames are not normalized @@ -45,4 +44,5 @@ def disable(): mon.free_tool_id(mon.COVERAGE_ID) -enable() +if __name__ == "__main__": + enable() diff --git a/Lib/test/libregrtest/runtests.py b/Lib/test/libregrtest/runtests.py index e6d34d8e6a3..0a9edce1085 100644 --- a/Lib/test/libregrtest/runtests.py +++ b/Lib/test/libregrtest/runtests.py @@ -159,7 +159,7 @@ def create_python_cmd(self) -> list[str]: if '-u' not in python_opts: cmd.append('-u') # Unbuffered stdout and stderr if self.coverage: - cmd.append("-Xpresite=test.cov") + cmd.append("-Xpresite=test.cov:enable") return cmd def bisect_cmd_args(self) -> list[str]: diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 8ff061e0740..2cac70f4ab2 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1397,7 +1397,7 @@ def trace_wrapper(*args, **kwargs): sys.settrace(original_trace) coverage_wrapper = trace_wrapper - if 'test.cov' in sys.modules: # -Xpresite=test.cov used + if 'test.cov' in sys.modules: # -Xpresite=test.cov:enable used cov = sys.monitoring.COVERAGE_ID @functools.wraps(func) def coverage_wrapper(*args, **kwargs): diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 5f035c35367..8740f65b7b0 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -32,6 +32,17 @@ def _kill_python_and_exit_code(p): return data, returncode +def presite_func(): + print("presite func") + +class Namespace: + pass + +presite = Namespace() +presite.attr = Namespace() +presite.attr.func = presite_func + + class CmdLineTest(unittest.TestCase): def test_directories(self): assert_python_failure('.') @@ -1266,6 +1277,17 @@ def test_invalid_thread_local_bytecode(self): rc, out, err = assert_python_failure(PYTHON_TLBC="2") self.assertIn(b"PYTHON_TLBC=N: N is missing or invalid", err) + @unittest.skipUnless(support.Py_DEBUG, + '-X presite requires a Python debug build') + def test_presite(self): + entrypoint = "test.test_cmd_line:presite_func" + proc = assert_python_ok("-X", f"presite={entrypoint}", "-c", "pass") + self.assertEqual(proc.out.rstrip(), b"presite func") + + entrypoint = "test.test_cmd_line:presite.attr.func" + proc = assert_python_ok("-X", f"presite={entrypoint}", "-c", "pass") + self.assertEqual(proc.out.rstrip(), b"presite func") + @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -I tests when PYTHON env vars are required.') diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 45d0d8308db..a2de58c2926 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -2051,7 +2051,7 @@ def test_no_memleak(self): def test_presite(self): cmd = [ sys.executable, - "-I", "-X", "presite=test._test_embed_structseq", + "-I", "-X", "presite=test._test_embed_structseq:main", "-c", "print('unique-python-message')", ] proc = subprocess.run( diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst new file mode 100644 index 00000000000..964e5bdabbe --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-02-17-52-33.gh-issue-148014.2Y6ND_.rst @@ -0,0 +1,2 @@ +Accept a function name in :option:`-X presite <-X>` command line option and +:envvar:`PYTHON_PRESITE` environment variable. Patch by Victor Stinner. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 5da0f3e5be3..8be9e6d7373 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1218,6 +1218,54 @@ pyinit_main_reconfigure(PyThreadState *tstate) #ifdef Py_DEBUG +// Equivalent to the Python code: +// +// for part in attr.split('.'): +// obj = getattr(obj, part) +static PyObject* +presite_resolve_name(PyObject *obj, PyObject *attr) +{ + obj = Py_NewRef(obj); + attr = Py_NewRef(attr); + PyObject *res; + + while (1) { + Py_ssize_t len = PyUnicode_GET_LENGTH(attr); + Py_ssize_t pos = PyUnicode_FindChar(attr, '.', 0, len, 1); + if (pos < 0) { + break; + } + + PyObject *name = PyUnicode_Substring(attr, 0, pos); + if (name == NULL) { + goto error; + } + res = PyObject_GetAttr(obj, name); + Py_DECREF(name); + if (res == NULL) { + goto error; + } + Py_SETREF(obj, res); + + PyObject *suffix = PyUnicode_Substring(attr, pos + 1, len); + if (suffix == NULL) { + goto error; + } + Py_SETREF(attr, suffix); + } + + res = PyObject_GetAttr(obj, attr); + Py_DECREF(obj); + Py_DECREF(attr); + return res; + +error: + Py_DECREF(obj); + Py_DECREF(attr); + return NULL; +} + + static void run_presite(PyThreadState *tstate) { @@ -1228,22 +1276,68 @@ run_presite(PyThreadState *tstate) return; } - PyObject *presite_modname = PyUnicode_FromWideChar( - config->run_presite, - wcslen(config->run_presite) - ); - if (presite_modname == NULL) { - fprintf(stderr, "Could not convert pre-site module name to unicode\n"); + PyObject *presite = PyUnicode_FromWideChar(config->run_presite, -1); + if (presite == NULL) { + fprintf(stderr, "Could not convert pre-site command to Unicode\n"); + _PyErr_Print(tstate); + return; + } + + // Accept "mod_name" and "mod_name:func_name" entry point syntax + Py_ssize_t len = PyUnicode_GET_LENGTH(presite); + Py_ssize_t pos = PyUnicode_FindChar(presite, ':', 0, len, 1); + PyObject *mod_name = NULL; + PyObject *func_name = NULL; + PyObject *module = NULL; + if (pos > 0) { + mod_name = PyUnicode_Substring(presite, 0, pos); + if (mod_name == NULL) { + goto error; + } + + func_name = PyUnicode_Substring(presite, pos + 1, len); + if (func_name == NULL) { + goto error; + } } else { - PyObject *presite = PyImport_Import(presite_modname); - if (presite == NULL) { - fprintf(stderr, "pre-site import failed:\n"); - _PyErr_Print(tstate); - } - Py_XDECREF(presite); - Py_DECREF(presite_modname); + mod_name = Py_NewRef(presite); } + + // mod_name can contain dots (ex: "math.integer") + module = PyImport_Import(mod_name); + if (module == NULL) { + goto error; + } + + if (func_name != NULL) { + PyObject *func = presite_resolve_name(module, func_name); + if (func == NULL) { + goto error; + } + + PyObject *res = PyObject_CallNoArgs(func); + Py_DECREF(func); + if (res == NULL) { + goto error; + } + Py_DECREF(res); + } + + Py_DECREF(presite); + Py_DECREF(mod_name); + Py_XDECREF(func_name); + Py_DECREF(module); + return; + +error: + fprintf(stderr, "pre-site failed:\n"); + _PyErr_Print(tstate); + + Py_DECREF(presite); + Py_XDECREF(mod_name); + Py_XDECREF(func_name); + Py_XDECREF(module); } #endif From 7e0a0be4097f9d29d66fe23f5af86f18a34ed7dd Mon Sep 17 00:00:00 2001 From: Joshua Swanson <22283299+joshuaswanson@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:10:34 +0200 Subject: [PATCH 450/775] gh-146333: Fix quadratic regex backtracking in configparser option parsing (GH-146399) Use negative lookahead in option regex to prevent backtracking, and to avoid changing logic outside the regexes (since people could use the regex directly). --- Lib/configparser.py | 8 ++++++-- Lib/test/test_configparser.py | 20 +++++++++++++++++++ ...3-25-00-51-03.gh-issue-146333.LqdL__bn.rst | 3 +++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2026-03-25-00-51-03.gh-issue-146333.LqdL__bn.rst diff --git a/Lib/configparser.py b/Lib/configparser.py index d435a5c2fe0..e76647d339e 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -613,7 +613,9 @@ class RawConfigParser(MutableMapping): \] # ] """ _OPT_TMPL = r""" - (?P
+
+ File Paths +
+ Module Names +
+
Flamegraph
diff --git a/Lib/profiling/sampling/heatmap_collector.py b/Lib/profiling/sampling/heatmap_collector.py index ea1beec70d3..5c36d78f553 100644 --- a/Lib/profiling/sampling/heatmap_collector.py +++ b/Lib/profiling/sampling/heatmap_collector.py @@ -20,6 +20,7 @@ from .collector import normalize_location, extract_lineno from .opcode_utils import get_opcode_info, format_opcode from .stack_collector import StackTraceCollector +from .module_utils import extract_module_name, get_python_path_info # ============================================================================ @@ -49,126 +50,6 @@ class TreeNode: children: Dict[str, 'TreeNode'] = field(default_factory=dict) -# ============================================================================ -# Module Path Analysis -# ============================================================================ - -def get_python_path_info(): - """Get information about Python installation paths for module extraction. - - Returns: - dict: Dictionary containing stdlib path, site-packages paths, and sys.path entries. - """ - info = { - 'stdlib': None, - 'site_packages': [], - 'sys_path': [] - } - - # Get standard library path from os module location - try: - if hasattr(os, '__file__') and os.__file__: - info['stdlib'] = Path(os.__file__).parent - except (AttributeError, OSError): - pass # Silently continue if we can't determine stdlib path - - # Get site-packages directories - site_packages = [] - try: - site_packages.extend(Path(p) for p in site.getsitepackages()) - except (AttributeError, OSError): - pass # Continue without site packages if unavailable - - # Get user site-packages - try: - user_site = site.getusersitepackages() - if user_site and Path(user_site).exists(): - site_packages.append(Path(user_site)) - except (AttributeError, OSError): - pass # Continue without user site packages - - info['site_packages'] = site_packages - info['sys_path'] = [Path(p) for p in sys.path if p] - - return info - - -def extract_module_name(filename, path_info): - """Extract Python module name and type from file path. - - Args: - filename: Path to the Python file - path_info: Dictionary from get_python_path_info() - - Returns: - tuple: (module_name, module_type) where module_type is one of: - 'stdlib', 'site-packages', 'project', or 'other' - """ - if not filename: - return ('unknown', 'other') - - try: - file_path = Path(filename) - except (ValueError, OSError): - return (str(filename), 'other') - - # Check if it's in stdlib - if path_info['stdlib'] and _is_subpath(file_path, path_info['stdlib']): - try: - rel_path = file_path.relative_to(path_info['stdlib']) - return (_path_to_module(rel_path), 'stdlib') - except ValueError: - pass - - # Check site-packages - for site_pkg in path_info['site_packages']: - if _is_subpath(file_path, site_pkg): - try: - rel_path = file_path.relative_to(site_pkg) - return (_path_to_module(rel_path), 'site-packages') - except ValueError: - continue - - # Check other sys.path entries (project files) - if not str(file_path).startswith(('<', '[')): # Skip special files - for path_entry in path_info['sys_path']: - if _is_subpath(file_path, path_entry): - try: - rel_path = file_path.relative_to(path_entry) - return (_path_to_module(rel_path), 'project') - except ValueError: - continue - - # Fallback: just use the filename - return (_path_to_module(file_path), 'other') - - -def _is_subpath(file_path, parent_path): - try: - file_path.relative_to(parent_path) - return True - except (ValueError, OSError): - return False - - -def _path_to_module(path): - if isinstance(path, str): - path = Path(path) - - # Remove .py extension - if path.suffix == '.py': - path = path.with_suffix('') - - # Convert path separators to dots - parts = path.parts - - # Handle __init__ files - they represent the package itself - if parts and parts[-1] == '__init__': - parts = parts[:-1] - - return '.'.join(parts) if parts else path.stem - - # ============================================================================ # Helper Classes # ============================================================================ diff --git a/Lib/profiling/sampling/module_utils.py b/Lib/profiling/sampling/module_utils.py new file mode 100644 index 00000000000..dfde2b28ab2 --- /dev/null +++ b/Lib/profiling/sampling/module_utils.py @@ -0,0 +1,102 @@ +"""Utilities for extracting module names from file paths.""" + +import os +import site +import sys +from pathlib import Path + + +def get_python_path_info(): + """Get information about Python's search paths. + + Returns: + dict: Dictionary containing stdlib path, site-packages paths, and sys.path entries. + """ + info = { + 'stdlib': None, + 'site_packages': [], + 'sys_path': [] + } + + # Get standard library path from os module location + try: + if hasattr(os, '__file__') and os.__file__: + info['stdlib'] = Path(os.__file__).parent + except (AttributeError, OSError): + pass # Silently continue if we can't determine stdlib path + + # Get site-packages directories + site_packages = [] + try: + site_packages.extend(Path(p) for p in site.getsitepackages()) + except (AttributeError, OSError): + pass # Continue without site packages if unavailable + + # Get user site-packages + try: + user_site = site.getusersitepackages() + if user_site and Path(user_site).exists(): + site_packages.append(Path(user_site)) + except (AttributeError, OSError): + pass # Continue without user site packages + + info['site_packages'] = site_packages + info['sys_path'] = [Path(p) for p in sys.path if p] + + return info + + +def extract_module_name(filename, path_info): + """Extract Python module name and type from file path. + + Args: + filename: Path to the Python file + path_info: Dictionary from get_python_path_info() + + Returns: + tuple: (module_name, module_type) where module_type is one of: + 'stdlib', 'site-packages', 'project', or 'other' + """ + if not filename: + return ('unknown', 'other') + + try: + file_path = Path(filename) + except (ValueError, OSError): + return (str(filename), 'other') + + # Check if it's in stdlib + if path_info['stdlib'] and file_path.is_relative_to(path_info['stdlib']): + return (_path_to_module(file_path.relative_to(path_info['stdlib'])), 'stdlib') + + # Check site-packages + for site_pkg in path_info['site_packages']: + if file_path.is_relative_to(site_pkg): + return (_path_to_module(file_path.relative_to(site_pkg)), 'site-packages') + + # Check other sys.path entries (project files) + if not str(file_path).startswith(('<', '[')): # Skip special files + for path_entry in path_info['sys_path']: + if file_path.is_relative_to(path_entry): + return (_path_to_module(file_path.relative_to(path_entry)), 'project') + + # Fallback: just use the filename + return (_path_to_module(file_path), 'other') + + +def _path_to_module(path): + if isinstance(path, str): + path = Path(path) + + # Remove .py extension + if path.suffix == '.py': + path = path.with_suffix('') + + # Convert path separators to dots, stripping root/drive (e.g. "/" or "C:\") + parts = [p for p in path.parts if p != path.root and p != path.drive] + + # Handle __init__ files - they represent the package itself + if parts and parts[-1] == '__init__': + parts = parts[:-1] + + return '.'.join(parts) if parts else path.stem diff --git a/Lib/profiling/sampling/stack_collector.py b/Lib/profiling/sampling/stack_collector.py index 461ce95a258..04622a8c1e8 100644 --- a/Lib/profiling/sampling/stack_collector.py +++ b/Lib/profiling/sampling/stack_collector.py @@ -12,6 +12,7 @@ from .collector import Collector, extract_lineno from .opcode_utils import get_opcode_mapping from .string_table import StringTable +from .module_utils import extract_module_name, get_python_path_info class StackTraceCollector(Collector): @@ -72,6 +73,7 @@ def __init__(self, *args, **kwargs): self._sample_count = 0 # Track actual number of samples (not thread traces) self._func_intern = {} self._string_table = StringTable() + self._module_cache = {} self._all_threads = set() # Thread status statistics (similar to LiveStatsCollector) @@ -182,6 +184,24 @@ def _format_function_name(func): return f"{funcname} ({filename}:{lineno})" + @staticmethod + @functools.lru_cache(maxsize=None) + def _format_module_name(func, module_name): + filename, lineno, funcname = func + + # Special frames like and should not show file:line + if filename == "~" and lineno == 0: + return funcname + + return f"{funcname} ({module_name}:{lineno})" + + def _get_module_name(self, filename, path_info): + module_name = self._module_cache.get(filename) + if module_name is None: + module_name, _ = extract_module_name(filename, path_info) + self._module_cache[filename] = module_name + return module_name + def _convert_to_flamegraph_format(self): if self._total_samples == 0: return { @@ -192,7 +212,7 @@ def _convert_to_flamegraph_format(self): "strings": self._string_table.get_strings() } - def convert_children(children, min_samples): + def convert_children(children, min_samples, path_info): out = [] for func, node in children.items(): samples = node["samples"] @@ -202,14 +222,20 @@ def convert_children(children, min_samples): # Intern all string components for maximum efficiency filename_idx = self._string_table.intern(func[0]) funcname_idx = self._string_table.intern(func[2]) + module_name = self._get_module_name(func[0], path_info) + + module_idx = self._string_table.intern(module_name) name_idx = self._string_table.intern(self._format_function_name(func)) + label_idx = self._string_table.intern(self._format_module_name(func, module_name)) child_entry = { "name": name_idx, + "label": label_idx, "value": samples, "self": node.get("self", 0), "children": [], "filename": filename_idx, + "module": module_idx, "lineno": func[1], "funcname": funcname_idx, "threads": sorted(list(node.get("threads", set()))), @@ -228,7 +254,7 @@ def convert_children(children, min_samples): # Recurse child_entry["children"] = convert_children( - node["children"], min_samples + node["children"], min_samples, path_info ) out.append(child_entry) @@ -239,8 +265,9 @@ def convert_children(children, min_samples): # Filter out very small functions (less than 0.1% of total samples) total_samples = self._total_samples min_samples = max(1, int(total_samples * 0.001)) + path_info = get_python_path_info() - root_children = convert_children(self._root["children"], min_samples) + root_children = convert_children(self._root["children"], min_samples, path_info) if not root_children: return { "name": self._string_table.intern("No significant data"), @@ -282,10 +309,11 @@ def convert_children(children, min_samples): # If we only have one root child, make it the root to avoid redundant level if len(root_children) == 1: main_child = root_children[0] - # Update the name to indicate it's the program root + # Update name and label to indicate it's the program root old_name = self._string_table.get_string(main_child["name"]) - new_name = f"Program Root: {old_name}" - main_child["name"] = self._string_table.intern(new_name) + main_child["name"] = self._string_table.intern(f"Program Root: {old_name}") + old_label = self._string_table.get_string(main_child["label"]) + main_child["label"] = self._string_table.intern(f"Program Root: {old_label}") main_child["stats"] = { **self.stats, "thread_stats": thread_stats, @@ -296,8 +324,10 @@ def convert_children(children, min_samples): main_child["opcode_mapping"] = opcode_mapping return main_child + program_root_idx = self._string_table.intern("Program Root") return { - "name": self._string_table.intern("Program Root"), + "name": program_root_idx, + "label": program_root_idx, "value": total_samples, "children": root_children, "stats": { diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py index 503430ddf02..240ec8a195c 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py @@ -436,6 +436,8 @@ def test_flamegraph_collector_basic(self): name = resolve_name(data, strings) self.assertTrue(name.startswith("Program Root: ")) self.assertIn("func2 (file.py:20)", name) + label = strings[data["label"]] + self.assertTrue(label.startswith("Program Root: ")) self.assertEqual(data["self"], 0) # non-leaf: no self time children = data.get("children", []) self.assertEqual(len(children), 1) From 4a5d25c26c01a04c0ddef1a0b00cb55cc835034f Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Wed, 29 Apr 2026 19:33:51 +0800 Subject: [PATCH 701/775] gh-135528: Support more second-level domain names in http.cookiejar (#135820) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Lib/http/cookiejar.py | 11 +++++++---- .../2025-06-22-16-29-10.gh-issue-135528.Rt_QhR.rst | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-06-22-16-29-10.gh-issue-135528.Rt_QhR.rst diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 68cf16c93cc..13e5b104a81 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -1032,10 +1032,13 @@ def set_ok_domain(self, cookie, request): if j == 0: # domain like .foo.bar tld = domain[i+1:] sld = domain[j+1:i] - if sld.lower() in ("co", "ac", "com", "edu", "org", "net", - "gov", "mil", "int", "aero", "biz", "cat", "coop", - "info", "jobs", "mobi", "museum", "name", "pro", - "travel", "eu") and len(tld) == 2: + known_slds = ( + "co", "ac", "com", "edu", "org", "net", + "gov", "mil", "int", "aero", "biz", "cat", "coop", + "info", "jobs", "mobi", "museum", "name", "pro", + "travel", "eu", "tv", "or", "nom", "sch", "web", + ) + if sld.lower() in known_slds and len(tld) == 2: # domain like .co.uk _debug(" country-code second level domain %s", domain) return False diff --git a/Misc/NEWS.d/next/Library/2025-06-22-16-29-10.gh-issue-135528.Rt_QhR.rst b/Misc/NEWS.d/next/Library/2025-06-22-16-29-10.gh-issue-135528.Rt_QhR.rst new file mode 100644 index 00000000000..ab3855582c7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-06-22-16-29-10.gh-issue-135528.Rt_QhR.rst @@ -0,0 +1 @@ +:mod:`http.cookiejar`: add "tv", "or", "nom", "sch", and "web" to the default list of supported country code second-level domains. From 16f292ef4e8c56bfd115ecdb91420c7b4006249f Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:35:51 +0100 Subject: [PATCH 702/775] gh-149122: Fix segfault in compiler when certain builtin functions are passed a coroutine as arg (#149138) --- Lib/test/test_builtin.py | 21 +++++++++++++++++++ ...-04-29-14-06-00.gh-issue-149122.P8k2Lm.rst | 4 ++++ Python/codegen.c | 7 ++++++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-29-14-06-00.gh-issue-149122.P8k2Lm.rst diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index e3237426652..81967fb8a83 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -308,6 +308,27 @@ def f_set(): self.assertEqual(overridden_outputs, ['all', 'any', 'tuple', 'list', 'set']) + def test_builtin_call_async_genexpr_no_crash(self): + async def f_all(): + return all(await 2 for _ in []) + + async def f_any(): + return any(await 2 for _ in []) + + async def f_tuple(): + return tuple(await 2 for _ in []) + + async def f_list(): + return list(await 2 for _ in []) + + async def f_set(): + return set(await 2 for _ in []) + + for f in (f_all, f_any, f_tuple, f_list, f_set): + with self.subTest(func=f.__name__): + with self.assertRaises(TypeError): + run_yielding_async_fn(f) + def test_ascii(self): self.assertEqual(ascii(''), '\'\'') self.assertEqual(ascii(0), '0') diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-29-14-06-00.gh-issue-149122.P8k2Lm.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-29-14-06-00.gh-issue-149122.P8k2Lm.rst new file mode 100644 index 00000000000..f34b6ea857a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-29-14-06-00.gh-issue-149122.P8k2Lm.rst @@ -0,0 +1,4 @@ +Fix a crash in optimized calls to :func:`all`, :func:`any`, :func:`tuple`, +:func:`list`, and :func:`set` with an async generator expression argument +(for example, ``tuple(await x for x in y)``). These calls now correctly raise +``TypeError`` instead of crashing. diff --git a/Python/codegen.c b/Python/codegen.c index 389e7cf85d3..a371bf332b6 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -3959,6 +3959,12 @@ maybe_optimize_function_call(compiler *c, expr_ty e, jump_target_label end) return 0; } + expr_ty generator_exp = asdl_seq_GET(args, 0); + PySTEntryObject *generator_entry = _PySymtable_Lookup(SYMTABLE(c), (void *)generator_exp); + if (generator_entry->ste_coroutine) { + return 0; + } + location loc = LOC(func); int optimized = 0; @@ -3998,7 +4004,6 @@ maybe_optimize_function_call(compiler *c, expr_ty e, jump_target_label end) } else if (const_oparg == CONSTANT_BUILTIN_SET) { ADDOP_I(c, loc, BUILD_SET, 0); } - expr_ty generator_exp = asdl_seq_GET(args, 0); VISIT(c, expr, generator_exp); NEW_JUMP_TARGET_LABEL(c, loop); From f1588d460db97086f5ea28b5797ccdcfffb0307f Mon Sep 17 00:00:00 2001 From: Jansen Price Date: Wed, 29 Apr 2026 08:44:22 -0500 Subject: [PATCH 703/775] gh-148740: Fix `uuid` CLI with custom UUIDs for UUIDv3/v5 namespaces (#148741) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/test/test_uuid.py | 84 +++++++++++++++---- Lib/uuid.py | 10 ++- ...-04-18-17-37-13.gh-issue-148740.sYnFi0.rst | 2 + 3 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-18-17-37-13.gh-issue-148740.sYnFi0.rst diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index 5f9ab048cde..055be2994bf 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -1182,6 +1182,47 @@ def test_cli_name_required_for_uuid3(self, mock_err): self.assertEqual(cm.exception.code, 2) self.assertIn("error: Incorrect number of arguments", mock_err.getvalue()) + @mock.patch.object(sys, "argv", + ["", "-u", "uuid3", "-n", "@dns", "-N", "python.org"]) + def test_cli_uuid3_outputted_with_valid_namespace_and_name(self): + stdout = io.StringIO() + with contextlib.redirect_stdout(stdout): + self.uuid.main() + + output = stdout.getvalue().strip() + uuid_output = self.uuid.UUID(output) + + # Output should be in the form of uuid3 + self.assertEqual(output, str(uuid_output)) + self.assertEqual(uuid_output.version, 3) + + @mock.patch.object(sys, "argv", + ["", "-u", "uuid3", "-n", + "0d6a16cc-34a7-47d8-b660-214d0ae184d2", + "-N", "some.user"]) + def test_cli_uuid3_outputted_with_custom_namespace_and_name(self): + stdout = io.StringIO() + with contextlib.redirect_stdout(stdout): + self.uuid.main() + + output = stdout.getvalue().strip() + uuid_output = self.uuid.UUID(output) + + # Output should be in the form of uuid3 + self.assertEqual(output, str(uuid_output)) + self.assertEqual(uuid_output.version, 3) + + @mock.patch.object(sys, "argv", + ["", "-u", "uuid3", "-n", "any UUID", "-N", "python.org"]) + @mock.patch('sys.stderr', new_callable=io.StringIO) + def test_cli_uuid3_with_invalid_namespace(self, mock_err): + with self.assertRaises(SystemExit) as cm: + self.uuid.main() + # Check that exception code is the same as argparse.ArgumentParser.error + self.assertEqual(cm.exception.code, 2) + self.assertIn("error: badly formed hexadecimal UUID string", + mock_err.getvalue()) + @mock.patch.object(sys, "argv", [""]) def test_cli_uuid4_outputted_with_no_args(self): stdout = io.StringIO() @@ -1209,23 +1250,9 @@ def test_cli_uuid4_outputted_with_count(self): uuid_output = self.uuid.UUID(o) self.assertEqual(uuid_output.version, 4) - @mock.patch.object(sys, "argv", - ["", "-u", "uuid3", "-n", "@dns", "-N", "python.org"]) - def test_cli_uuid3_ouputted_with_valid_namespace_and_name(self): - stdout = io.StringIO() - with contextlib.redirect_stdout(stdout): - self.uuid.main() - - output = stdout.getvalue().strip() - uuid_output = self.uuid.UUID(output) - - # Output should be in the form of uuid5 - self.assertEqual(output, str(uuid_output)) - self.assertEqual(uuid_output.version, 3) - @mock.patch.object(sys, "argv", ["", "-u", "uuid5", "-n", "@dns", "-N", "python.org"]) - def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self): + def test_cli_uuid5_outputted_with_valid_namespace_and_name(self): stdout = io.StringIO() with contextlib.redirect_stdout(stdout): self.uuid.main() @@ -1237,6 +1264,33 @@ def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self): self.assertEqual(output, str(uuid_output)) self.assertEqual(uuid_output.version, 5) + @mock.patch.object(sys, "argv", + ["", "-u", "uuid5", "-n", + "0d6a16cc-34a7-47d8-b660-214d0ae184d2", + "-N", "some.user"]) + def test_cli_uuid5_ouputted_with_custom_namespace_and_name(self): + stdout = io.StringIO() + with contextlib.redirect_stdout(stdout): + self.uuid.main() + + output = stdout.getvalue().strip() + uuid_output = self.uuid.UUID(output) + + # Output should be in the form of uuid5 + self.assertEqual(output, str(uuid_output)) + self.assertEqual(uuid_output.version, 5) + + @mock.patch.object(sys, "argv", + ["", "-u", "uuid5", "-n", "any UUID", "-N", "python.org"]) + @mock.patch('sys.stderr', new_callable=io.StringIO) + def test_cli_uuid5_with_invalid_namespace(self, mock_err): + with self.assertRaises(SystemExit) as cm: + self.uuid.main() + # Check that exception code is the same as argparse.ArgumentParser.error + self.assertEqual(cm.exception.code, 2) + self.assertIn("error: badly formed hexadecimal UUID string", + mock_err.getvalue()) + @mock.patch.object(sys, "argv", ["", "-u", "uuid6"]) def test_cli_uuid6(self): self.do_test_standalone_uuid(6) diff --git a/Lib/uuid.py b/Lib/uuid.py index c0150a59d7c..8c59581464b 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -962,7 +962,7 @@ def main(): default="uuid4", help="function to generate the UUID") parser.add_argument("-n", "--namespace", - choices=["any UUID", *namespaces.keys()], + metavar=f"{{any UUID,{','.join(namespaces)}}}", help="uuid3/uuid5 only: " "a UUID, or a well-known predefined UUID addressed " "by namespace name") @@ -984,7 +984,13 @@ def main(): f"{args.uuid} requires a namespace and a name. " "Run 'python -m uuid -h' for more information." ) - namespace = namespaces[namespace] if namespace in namespaces else UUID(namespace) + if namespace in namespaces: + namespace = namespaces[namespace] + else: + try: + namespace = UUID(namespace) + except ValueError as exc: + parser.error(f"{exc}: {args.namespace!r}") for _ in range(args.count): print(uuid_func(namespace, name)) else: diff --git a/Misc/NEWS.d/next/Library/2026-04-18-17-37-13.gh-issue-148740.sYnFi0.rst b/Misc/NEWS.d/next/Library/2026-04-18-17-37-13.gh-issue-148740.sYnFi0.rst new file mode 100644 index 00000000000..7e49cedda7b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-18-17-37-13.gh-issue-148740.sYnFi0.rst @@ -0,0 +1,2 @@ +Fix usage for :mod:`uuid` command-line interface to support a custom namespace be +provided for uuid3 and uuid5. From 025a82f138b9a59c2cb842aaa8835206f0879b20 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 29 Apr 2026 16:36:01 +0200 Subject: [PATCH 704/775] gh-149148: Upgrade bundled pip to 26.1 (#149150) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Lib/ensurepip/__init__.py | 2 +- ...none-any.whl => pip-26.1-py3-none-any.whl} | Bin 1787723 -> 1812804 bytes ...-04-29-14-33-42.gh-issue-149148.EaiYvk.rst | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) rename Lib/ensurepip/_bundled/{pip-26.0.1-py3-none-any.whl => pip-26.1-py3-none-any.whl} (73%) create mode 100644 Misc/NEWS.d/next/Library/2026-04-29-14-33-42.gh-issue-149148.EaiYvk.rst diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 93b4e7a820f..5a55525d6bd 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ __all__ = ["version", "bootstrap"] -_PIP_VERSION = "26.0.1" +_PIP_VERSION = "26.1" # Directory of system wheel packages. Some Linux distribution packaging # policies recommend against bundling dependencies. For example, Fedora diff --git a/Lib/ensurepip/_bundled/pip-26.0.1-py3-none-any.whl b/Lib/ensurepip/_bundled/pip-26.1-py3-none-any.whl similarity index 73% rename from Lib/ensurepip/_bundled/pip-26.0.1-py3-none-any.whl rename to Lib/ensurepip/_bundled/pip-26.1-py3-none-any.whl index 580d09a920422fcabbd462c937d08c96dd7f08bc..b51afa14f7c0ad88a192f4bf606775653df23681 100644 GIT binary patch delta 464459 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 z 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%0DQO{cgXjf39fzFK@VXk+x zOnx{aX;@f4U0oesUY;1=5=_J+;;fndgXqD6>JKGrOk|j3$N>$~8;)5Xs_LD#Z=Y1P zFoR51P_K}_rC6Z7ULa(8oCTZB;ANU_;5LQT_Y@LxQ2ThC`}H*hfqc z2W(f=v3}I8Uzg|>WHqT1HBK1letE!;(ceE$S1yW%SDRyxsyTK< zqV-#d15uNklj1|C>T2Y<{?cDu(Rrd9TYFG*LT+L&6AhB;R*>P{9-j}-);%*M&NNQf zKTHbp5MnF@^r|Hyz&`qthJ62u0yTZQpXC zaKSJ6jvA2ee>OjPa-D!-n_aDH+1*&3K2HfXq;S(|!E_?CP1b=)A$d(NLby$(JDp}% z5^KfAth{q0GsZqV$hMtsniZhV2Mz@vEHLG(HRBEHS^qp~{(iEfGKf8IrGN?m{Au>35p|C7X=kd5xW89pTw z^qTP9o4$A73NRA%cx`41&Nj0EyT_uJ*(fUE3ZHYgtWU}o^)LdxS1EjnFZp?@LxJl9 zMRp_3wjhOA;m1HUP~z3~_X8 zjCBq-y_^FeYkK8Hx~Cf`(;;rD>0sm!5q`(ri#fx{Th*sVUB>a}9u4vLTSD^KllhCoz}9PZ$D?u zb$Q*V|DxY93o2#U{+BYRVVJ|6(35$!7!4U;C(8pN4 zRaGCGdeX}T^uNnCrZ-*O%sl$A@Gat*%ESV_JPT+fXP}d4&HW+ASBD?xkGqfGps?NC zZz+bJcujum={~wGg`q0I}#=?_<3seP^Mbd^W7Q#zEX6t7~aLZjFO!7d2FW(%7dL? zOA7Xl`9&ImCK5nXR}uP)fXPbJ^mxBxhIB&FWXniy%easi6T6!&zAD;`ijUA56>RpA zH*5JXOw})RCc7eB2&p3J~3|J)XFy(g1 z^6U8?-yPY{6`;RB4H%mrca3Amf;ZGVx$oWX@nEhNqT})Ff41@PyImTlF6BXK87nfe zGL@>?ax56MAKy^RNG;pZE5<$&@eDcl*6DCiSp=x3f`3+ib%R2#XTN>kwyx3&0!8~N zuuzRrm&CEAUUz>F>4c%fW>Mn(7x4D|C#X8)MFbS(I)WRD$T+@)Bx(9X*{B2uw!yW9 zj~BlL@xM*TQTl%?BPg{G9_+E4>Ou=>8=;_3*+J(+L4)0ch>%dF;%VC@&96R0IqNwRfeDyvXomlMxr!-1Ok7X=V zWaSMua4=%U-)RY5JdZ0i5yT|AX#2!qVu=AX24GF*jiBm+)?V$>MDl<}Nr71+bfDSOsnLYC z_K7LxLG@W>5GovM*=hwQVHhDA%^1iJg($6b1k22*ph$BQq5``(>3DHh*A=8DAK9!x zr&aq)G7%aj@f*u{!@CPW3GXD%AgK^Rf}(L-m}2c5a4pGhh2e#Q`DI%ZOdWdO4+cpZ zgJrSnMImgGqS67KUKL8J2fWgEQ<*LQ^(D~&v*C*E)BrG9W9k0Q5!t|EEuSW&WKxsfHE`@PU{@H)FDdBg zsR)$BQB(^=@=VQs1D{=xLaniB|D^S5T97!)U@=|g@~Vr!2$i@t-}}FAYJ~d4FEfsJ z$cpJKkD*mC3_-5k*6vMYqr^N@E^qZ)!KAZ9+5-DI3VAk=QP6gX6n&d-1mk4tkjxuZ ze1+exzgN4L={3CH6@hjAEQwSIhnrCpiLk#Sage~K5XlYX{i6e-l#QAijv~4!W{?#P zN@~Z2^X=k{Md83xCa`i;#RGYuy(aZaJZNqlYJOjMzd`2T1QFNlSrOhJ3by2jl*w2u zoxsRtoWVDXSWdbB?q3Y3BjwX(aG+vmOE&Fld528L)TTNs$io)>Xh=)c10+2RJLaGBI)#5x9Dj5{G4d`!PDI{ zPR1hmWffkynRSy3K(#gPA4<1*UiFseBsDBD>i#GOi!maJ>^ySj7W4aBHQO?nBO#e# z_p1ZWGYU%)$bpVyX1o_gc;z&6V4*3x%NNIn!>?DGgq~%#{({@aBrU&8OH9prH#P~} z|LvmijO~fGEb0-MZP~mvvZp~~F5;&;4ndR)x zm`T;M1={7**~+1-y4EC;^rot0!hA==53kIQC4-8GZC!{04w@zlu649$FP-8{nN~cg#-$1DbIFI&ZFZCIED*xG@(!%U#JE}-%!o3yLX@cLh8@KgEm4KLn{!z zWz_)>DyPu#=(K2M#x2%ZDOh6th$|Wfv}a-$taLuVp9NRJ zt3sXwv>LfmGHx?hP~0ATPMacZpIoh~brBKFv@{gzbF+-R|0PEn-KnfNuZ?O(Oo3zY zobMduK$wrn3~2tQx8g zV{d?OmFWx%PuTtk?hBNYAKnWHQYy>Go-3oKw`LTJ)9SV%Pe8KCN+oA{62iIq<;Lj* z&ePa55)X_I;g_MNL!)dKvOD6795B@Xb(UGH$KlnDN_=mv?~n+QVCuT_ZJq87UFAo% znVxKE5M~4%4SwfNr3z9`6?ruID@A6zSv1cen@Dh>GobyJ33SSso^Y5n*@r)Zpw8GlPQhvc1m>Wn-#>gG>R{FY`zpxd=z7K`Fw z9uxnI{w1X9$d9!WQ2d*~a3h>}dA(NDr-6mTj=K$sB+|W2L?&%F-F_AXN!`{f^=4>Z zqK(z#&oUb|E1oV$=)uNF7y>XFw>-|eCrdBl9$G{ZNBGQ3a1T$f2aA|o#~m^Hlj=`8 z*$OUmYC-FKf8=g|;np4s57NnJ>cPi*a$F?`wt!_Sc?aT8$GtAE5RAAvZ%z#BuTZ!C zhCsPO&AGwKm~x_|YeJ05kInpCO#Rld&226~4Ze9%qaD;PNW^g39UQRgdaX;;`}Nc~ zc8)9md*5dsuPQFsZ2VUn-H-HeHxFNvGp_~RfBp$ALs!b)bA&Nz zse}q?#uMEV=x(n0hFy-VY9%Fe^)VviG>v$|h%4qm+LZN#_|>30gXb6HWs`c3(mV~> zu*f`}d1+ULsT2}=WX`#^PoS^nRQ#)#8fgC5L{0C^Nf95=RFi$3bjb46&pjvSV z^{J^6{e_P_lm!*2MDHY@6Zuynt?TUjJ#PK>@@8Z%>k`76l~mcL0`Ti$P;$FX&bSMH z#NN!u;rK0lqh3EFge&E}IBz2>0lmi6h5nDJ%_(39B5^Rp{)|G0xL3g!RK|BuHYc4rs^*_z8!$ID>=d&@g#A0+TQX0|$m#V0((>vUwxyXZ6Z z2eg!M*u#AJuqy#`t)T5mQ1<

=^`|Sd>=8{Ta&THfSs?4h48E(;xHhL?U56W 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 z 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 O~7>$DMKoV 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 delta 439167 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

Fjebtyy3aBYl&|A_nRsun&+8gz@VO#B;~; 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

    TSTyk+^umGJhh0%ifan52d*%Dzu4Ta2{n?E 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 z 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 Date: Wed, 29 Apr 2026 18:33:05 +0300 Subject: [PATCH 705/775] gh-149026: Add colour to `pickletools` CLI output (#149027) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/library/pickletools.rst | 3 + Doc/whatsnew/3.15.rst | 9 +++ Lib/_colorize.py | 21 ++++++ Lib/pickletools.py | 73 +++++++++++++++---- Lib/test/test_pickletools.py | 2 + ...-04-26-23-01-50.gh-issue-149026.Akk4Bc.rst | 1 + 6 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-26-23-01-50.gh-issue-149026.Akk4Bc.rst diff --git a/Doc/library/pickletools.rst b/Doc/library/pickletools.rst index 7a771ea3ab9..e753ad3b08b 100644 --- a/Doc/library/pickletools.rst +++ b/Doc/library/pickletools.rst @@ -79,6 +79,9 @@ Command-line options A pickle file to read, or ``-`` to indicate reading from standard input. +.. versionadded:: next + Output is in color by default and can be + :ref:`controlled using environment variables `. Programmatic interface diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index eb08f8c4ed6..3c2c7a7e399 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1053,6 +1053,15 @@ pickle (Contributed by Zackery Spytz and Serhiy Storchaka in :gh:`77188`.) +pickletools +----------- + +* The output of the :mod:`pickletools` command-line interface is colored by + default. This can be controlled with + :ref:`environment variables `. + (Contributed by Hugo van Kemenade in :gh:`149026`.) + + pprint ------ diff --git a/Lib/_colorize.py b/Lib/_colorize.py index 379ca2529b6..62806b1d8d7 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -359,6 +359,23 @@ class LiveProfiler(ThemeSection): ) +@dataclass(frozen=True, kw_only=True) +class Pickletools(ThemeSection): + annotation: str = ANSIColors.GREY + arg_number: str = ANSIColors.YELLOW + arg_string: str = ANSIColors.GREEN + mark: str = ANSIColors.GREY + op_call: str = ANSIColors.GREEN + op_container: str = ANSIColors.INTENSE_BLUE + op_memo: str = ANSIColors.MAGENTA + op_meta: str = ANSIColors.GREY + op_stack: str = ANSIColors.BOLD_RED + opcode_code: str = ANSIColors.CYAN + position: str = ANSIColors.GREY + proto: str = ANSIColors.YELLOW + reset: str = ANSIColors.RESET + + @dataclass(frozen=True, kw_only=True) class Syntax(ThemeSection): prompt: str = ANSIColors.BOLD_MAGENTA @@ -429,6 +446,7 @@ class Theme: fancycompleter: FancyCompleter = field(default_factory=FancyCompleter) http_server: HttpServer = field(default_factory=HttpServer) live_profiler: LiveProfiler = field(default_factory=LiveProfiler) + pickletools: Pickletools = field(default_factory=Pickletools) syntax: Syntax = field(default_factory=Syntax) timeit: Timeit = field(default_factory=Timeit) tokenize: Tokenize = field(default_factory=Tokenize) @@ -444,6 +462,7 @@ def copy_with( fancycompleter: FancyCompleter | None = None, http_server: HttpServer | None = None, live_profiler: LiveProfiler | None = None, + pickletools: Pickletools | None = None, syntax: Syntax | None = None, timeit: Timeit | None = None, tokenize: Tokenize | None = None, @@ -462,6 +481,7 @@ def copy_with( fancycompleter=fancycompleter or self.fancycompleter, http_server=http_server or self.http_server, live_profiler=live_profiler or self.live_profiler, + pickletools=pickletools or self.pickletools, syntax=syntax or self.syntax, timeit=timeit or self.timeit, tokenize=tokenize or self.tokenize, @@ -484,6 +504,7 @@ def no_colors(cls) -> Self: fancycompleter=FancyCompleter.no_colors(), http_server=HttpServer.no_colors(), live_profiler=LiveProfiler.no_colors(), + pickletools=Pickletools.no_colors(), syntax=Syntax.no_colors(), timeit=Timeit.no_colors(), tokenize=Tokenize.no_colors(), diff --git a/Lib/pickletools.py b/Lib/pickletools.py index 29baf3be7eb..976e218db19 100644 --- a/Lib/pickletools.py +++ b/Lib/pickletools.py @@ -16,6 +16,8 @@ import re import sys +lazy from _colorize import decolor, get_theme + __all__ = ['dis', 'genops', 'optimize'] bytes_types = pickle.bytes_types @@ -2209,6 +2211,32 @@ def __init__(self, name, code, arg, name2i[d.name] = i code2i[d.code] = i +# Group opcode names into categories for colourised CLI output. +_opcode_categories = frozendict( + op_call=frozenset({ + "BUILD", "EXT1", "EXT2", "EXT4", "GLOBAL", "INST", "NEWOBJ", + "NEWOBJ_EX", "OBJ", "REDUCE", "STACK_GLOBAL", + }), + op_container=frozenset({ + "ADDITEMS", "APPEND", "APPENDS", "DICT", "EMPTY_DICT", "EMPTY_LIST", + "EMPTY_SET", "EMPTY_TUPLE", "FROZENSET", "LIST", "SETITEM", + "SETITEMS", "TUPLE", "TUPLE1", "TUPLE2", "TUPLE3", + }), + op_memo=frozenset({ + "BINGET", "BINPUT", "GET", "LONG_BINGET", "LONG_BINPUT", "MEMOIZE", + "PUT", + }), + op_meta=frozenset({"BINPERSID", "FRAME", "MARK", "PERSID", "PROTO"}), + op_stack=frozenset({"DUP", "POP", "POP_MARK", "STOP"}), +) +_opcode_color_attr = frozendict({ + name: attr + for attr, names in _opcode_categories.items() + for name in names +}) +assert _opcode_color_attr.keys() <= name2i.keys(), ( + f"unknown opcodes: {_opcode_color_attr.keys() - name2i.keys()}" +) del name2i, code2i, i, d ############################################################################## @@ -2443,13 +2471,19 @@ def dis(pickle, out=None, memo=None, indentlevel=4, annotate=0): indentchunk = ' ' * indentlevel errormsg = None annocol = annotate # column hint for annotations + t = get_theme(tty_file=out).pickletools for opcode, arg, pos in genops(pickle): if pos is not None: - print("%5d:" % pos, end=' ', file=out) + print(f"{t.position}{pos:5d}:{t.reset}", end=' ', file=out) - line = "%-4s %s%s" % (repr(opcode.code)[1:-1], - indentchunk * len(markstack), - opcode.name) + attr = _opcode_color_attr.get(opcode.name) + opcode_color = getattr(t, attr) if attr else "" + opcode_reset = t.reset if attr else "" + line = ( + f"{t.opcode_code}{repr(opcode.code)[1:-1]:<4}{t.reset} " + f"{indentchunk * len(markstack)}" + f"{opcode_color}{opcode.name}{opcode_reset}" + ) maxproto = max(maxproto, opcode.proto) before = opcode.stack_before # don't mutate @@ -2510,18 +2544,26 @@ def dis(pickle, out=None, memo=None, indentlevel=4, annotate=0): line += ' ' * (10 - len(opcode.name)) if arg is not None: if opcode.name in ("STRING", "BINSTRING", "SHORT_BINSTRING"): - line += ' ' + ascii(arg) + arg_text = ascii(arg) else: - line += ' ' + repr(arg) + arg_text = repr(arg) + arg_color = ( + t.arg_number + if isinstance(arg, (int, float)) + else t.arg_string + ) + line += f" {arg_color}{arg_text}{t.reset}" if markmsg: - line += ' ' + markmsg + line += f" {t.mark}{markmsg}{t.reset}" if annotate: - line += ' ' * (annocol - len(line)) + visible_len = len(decolor(line)) + line += ' ' * (annocol - visible_len) # make a mild effort to align annotations - annocol = len(line) + annocol = max(visible_len, annocol) if annocol > 50: annocol = annotate - line += ' ' + opcode.doc.split('\n', 1)[0] + doc = opcode.doc.split('\n', 1)[0] + line += f" {t.annotation}{doc}{t.reset}" print(line, file=out) if errormsg: @@ -2541,7 +2583,11 @@ def dis(pickle, out=None, memo=None, indentlevel=4, annotate=0): stack.extend(after) - print("highest protocol among opcodes =", maxproto, file=out) + print( + "highest protocol among opcodes =", + f"{t.proto}{maxproto}{t.reset}", + file=out, + ) if stack: raise ValueError("stack not empty after STOP: %r" % stack) @@ -2841,10 +2887,7 @@ def __init__(self, value): def _main(args=None): import argparse - parser = argparse.ArgumentParser( - description='disassemble one or more pickle files', - color=True, - ) + parser = argparse.ArgumentParser(description='disassemble one or more pickle files') parser.add_argument( 'pickle_file', nargs='+', help='the pickle file') diff --git a/Lib/test/test_pickletools.py b/Lib/test/test_pickletools.py index 57285ddf6eb..caf2d7ba6bf 100644 --- a/Lib/test/test_pickletools.py +++ b/Lib/test/test_pickletools.py @@ -160,6 +160,7 @@ def test_unknown_opcode_without_pos(self): next(it) +@support.force_not_colorized_test_class class DisTests(unittest.TestCase): maxDiff = None @@ -518,6 +519,7 @@ def test__all__(self): support.check__all__(self, pickletools, not_exported=not_exported) +@support.force_not_colorized_test_class class CommandLineTest(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() diff --git a/Misc/NEWS.d/next/Library/2026-04-26-23-01-50.gh-issue-149026.Akk4Bc.rst b/Misc/NEWS.d/next/Library/2026-04-26-23-01-50.gh-issue-149026.Akk4Bc.rst new file mode 100644 index 00000000000..d12a92e9f53 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-26-23-01-50.gh-issue-149026.Akk4Bc.rst @@ -0,0 +1 @@ +Add colour to :mod:`pickletools` CLI output. Patch by Hugo van Kemenade. From 16952218d0535904236e8a39851133688c9ce1f0 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Wed, 29 Apr 2026 19:39:29 -0700 Subject: [PATCH 706/775] gh-149083: Convert dataclasses.MISSING and dataclasses.KW_ONLY to sentinels (#149086) There were comments claiming these were implemented as custom classes to give a nicer repr(), but the repr() wasn't all that nice: >>> repr(dataclasses.MISSING) '' >>> repr(dataclasses.KW_ONLY) '' Sentinels are conceptually the right tool for these, so let's use them. This does change the repr() of these two objects. --- Lib/dataclasses.py | 13 ++++--------- Lib/test/test_dataclasses/__init__.py | 2 +- .../2026-04-27-20-15-54.gh-issue-149083.BdrpU8.rst | 2 ++ 3 files changed, 7 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-27-20-15-54.gh-issue-149083.BdrpU8.rst diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index df192763c5b..e9810d6bd5d 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -178,17 +178,12 @@ def __repr__(self): return '' _HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS() -# A sentinel object to detect if a parameter is supplied or not. Use -# a class to give it a better repr. -class _MISSING_TYPE: - pass -MISSING = _MISSING_TYPE() +# A sentinel object to detect if a parameter is supplied or not. +MISSING = sentinel("MISSING") # A sentinel object to indicate that following fields are keyword-only by -# default. Use a class to give it a better repr. -class _KW_ONLY_TYPE: - pass -KW_ONLY = _KW_ONLY_TYPE() +# default. +KW_ONLY = sentinel("KW_ONLY") # Since most per-field metadata will be unused, create an empty # read-only dictionary that can be shared among all fields. diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 5eec9e23cd4..8a0a7d12c04 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -995,7 +995,7 @@ class D: self.assertNotIn('x', D.__dict__) def test_missing_repr(self): - self.assertIn('MISSING_TYPE object', repr(MISSING)) + self.assertEqual(repr(MISSING), 'MISSING') def test_dont_include_other_annotations(self): @dataclass diff --git a/Misc/NEWS.d/next/Library/2026-04-27-20-15-54.gh-issue-149083.BdrpU8.rst b/Misc/NEWS.d/next/Library/2026-04-27-20-15-54.gh-issue-149083.BdrpU8.rst new file mode 100644 index 00000000000..7ad81616802 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-27-20-15-54.gh-issue-149083.BdrpU8.rst @@ -0,0 +1,2 @@ +:data:`dataclasses.MISSING` and :data:`dataclasses.KW_ONLY` are now +instances of :class:`sentinel`. From 234c12c0fc6f9710cee34d033a7f6a808d74bfac Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Wed, 29 Apr 2026 22:55:09 -0700 Subject: [PATCH 707/775] GH-145378: Use PyREPL as the default input console for pdb (#145379) --- Doc/whatsnew/3.15.rst | 7 + Lib/pdb.py | 169 +++++++++++++++++- Lib/test/test_pdb.py | 103 ++++++++--- ...-03-01-01-58-10.gh-issue-145378.oy6rb9.rst | 1 + 4 files changed, 246 insertions(+), 34 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-01-01-58-10.gh-issue-145378.oy6rb9.rst diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 3c2c7a7e399..56b2553a401 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1046,6 +1046,13 @@ os.path (Contributed by Petr Viktorin for :cve:`2025-4517`.) +pdb +--- + +* Use the new interactive shell as the default input shell for :mod:`pdb`. + (Contributed by Tian Gao in :gh:`145379`.) + + pickle ------ diff --git a/Lib/pdb.py b/Lib/pdb.py index 7b08d2bb701..c4bc0020646 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -318,12 +318,34 @@ def namespace(self): class _PdbInteractiveConsole(code.InteractiveConsole): - def __init__(self, ns, message): + def __init__(self, ns=None, message=None): self._message = message super().__init__(locals=ns, local_exit=True) def write(self, data): - self._message(data, end='') + if self._message is not None: + self._message(data, end='') + else: + super().write(data) + + def more_lines(self, text): + # Generic Python multi-line completeness heuristic. + # Strips pyrepl's trailing auto-indent before compiling. + # This should be functionally identical to simple_interact._more_lines + src = text.rstrip(" \t") + n = len(src) + if n > 0 and text[n-1] == '\n': + text = src + try: + code_obj = self.compile(text, "", "single") + except (OverflowError, SyntaxError, ValueError): + lines = text.splitlines(keepends=True) + if len(lines) == 1: + return False + last = lines[-1] + return ((last.startswith((" ", "\t")) or last.strip() != "") + and not last.endswith("\n")) + return code_obj is None # Interaction prompt line will separate file and call info from code @@ -352,6 +374,96 @@ def get_default_backend(): return _default_backend +def _pyrepl_available(): + """return whether pdb should use _pyrepl for input""" + if not os.getenv("PYTHON_BASIC_REPL"): + CAN_USE_PYREPL = False + else: + try: + from _pyrepl.main import CAN_USE_PYREPL + except ModuleNotFoundError: + CAN_USE_PYREPL = False + return CAN_USE_PYREPL + + +class PdbPyReplInput: + def __init__(self, pdb_instance, stdin, stdout, prompt): + import _pyrepl.readline + + self.pdb_instance = pdb_instance + self.prompt = prompt + self.console = _PdbInteractiveConsole() + if not (os.isatty(stdin.fileno())): + raise ValueError("stdin is not a TTY") + self.readline_wrapper = _pyrepl.readline._ReadlineWrapper( + f_in=stdin.fileno(), + f_out=stdout.fileno(), + config=_pyrepl.readline.ReadlineConfig( + completer_delims=frozenset(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') + ) + ) + + def readline(self): + + def more_lines(text): + if text.strip() == "\x1a": + # Ctrl + Z raises EOFError to quit pdb + # This is similarly handled in simple_interact.py + raise EOFError + cmd, _, line = self.pdb_instance.parseline(text) + if not line or not cmd: + return False + func = getattr(self.pdb_instance, 'do_' + cmd, None) + if func is not None: + return False + return self.console.more_lines(text) + + try: + pyrepl_completer = self.readline_wrapper.get_completer() + self.readline_wrapper.set_completer(self.complete) + multiline = ( + self.readline_wrapper.multiline_input( + more_lines, + self.prompt, + '... ' + ' ' * (len(self.prompt) - 4) + ) + '\n' + ) + return multiline + except EOFError: + return 'EOF' + finally: + self.readline_wrapper.set_completer(pyrepl_completer) + + def complete(self, text, state): + """ + This function is very similar to cmd.Cmd.complete. + However, cmd.Cmd.complete assumes that we use readline module, but + pyrepl does not use it. + """ + if state == 0: + origline = self.readline_wrapper.get_line_buffer() + line = origline.lstrip() + stripped = len(origline) - len(line) + begidx = self.readline_wrapper.get_begidx() - stripped + endidx = self.readline_wrapper.get_endidx() - stripped + if begidx > 0: + cmd, args, foo = self.pdb_instance.parseline(line) + if not cmd: + compfunc = self.pdb_instance.completedefault + else: + try: + compfunc = getattr(self.pdb_instance, 'complete_' + cmd) + except AttributeError: + compfunc = self.pdb_instance.completedefault + else: + compfunc = self.pdb_instance.completenames + self.completion_matches = compfunc(text, line, begidx, endidx) + try: + return self.completion_matches[state] + except IndexError: + return None + + class Pdb(bdb.Bdb, cmd.Cmd): _previous_sigint_handler = None @@ -386,6 +498,12 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, except ImportError: pass + self.pyrepl_input = None + if _pyrepl_available(): + try: + self.pyrepl_input = PdbPyReplInput(self, self.stdin, self.stdout, self.prompt) + except Exception: + pass self.allow_kbdint = False self.nosigint = nosigint # Consider these characters as part of the command so when the users type @@ -624,6 +742,31 @@ def user_exception(self, frame, exc_info): self.message('%s%s' % (prefix, self._format_exc(exc_value))) self.interaction(frame, exc_traceback) + @contextmanager + def _replace_attribute(self, attrs): + original_attrs = {} + for attr, value in attrs.items(): + original_attrs[attr] = getattr(self, attr) + setattr(self, attr, value) + try: + yield + finally: + for attr, value in original_attrs.items(): + setattr(self, attr, value) + + @contextmanager + def _maybe_use_pyrepl_as_stdin(self): + if self.pyrepl_input is None: + yield + return + + with self._replace_attribute({ + 'stdin': self.pyrepl_input, + 'use_rawinput': False, + 'prompt': '', + }): + yield + # General interaction function def _cmdloop(self): while True: @@ -631,7 +774,8 @@ def _cmdloop(self): # keyboard interrupts allow for an easy way to cancel # the current command, so allow them during interactive input self.allow_kbdint = True - self.cmdloop() + with self._maybe_use_pyrepl_as_stdin(): + self.cmdloop() self.allow_kbdint = False break except KeyboardInterrupt: @@ -2364,10 +2508,21 @@ def do_interact(self, arg): contains all the (global and local) names found in the current scope. """ ns = {**self.curframe.f_globals, **self.curframe.f_locals} - with self._enable_rlcompleter(ns): - console = _PdbInteractiveConsole(ns, message=self.message) - console.interact(banner="*pdb interact start*", - exitmsg="*exit from pdb interact command*") + console = _PdbInteractiveConsole(ns, message=self.message) + banner = "*pdb interact start*" + exitmsg = "*exit from pdb interact command*" + if self.pyrepl_input is not None: + from _pyrepl.simple_interact import run_multiline_interactive_console + self.message(banner) + try: + run_multiline_interactive_console(console) + except SystemExit: + pass + self.message(exitmsg) + else: + with self._enable_rlcompleter(ns): + console.interact(banner=banner, + exitmsg=exitmsg) def do_alias(self, arg): """alias [name [command]] diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 0e23cd66043..c5171f3388c 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -6,6 +6,7 @@ import io import os import pdb +import re import sys import types import codecs @@ -5006,6 +5007,20 @@ def setUpClass(cls): if readline.backend == "editline": raise unittest.SkipTest("libedit readline is not supported for pdb") + def _run_pty(self, script, input, env=None): + if env is None: + # By default, we use basic repl for the test. + # Subclass can overwrite this method and set env to use advanced REPL + env = os.environ | {'PYTHON_BASIC_REPL': '1'} + output = run_pty(script, input, env=env) + # filter all control characters + # Strip ANSI CSI sequences (good enough for most REPL/prompt output) + output = re.sub(r"\x1b\[[0-?]*[ -/]*[@-~]", "", output.decode("utf-8")) + return output + + def _pyrepl_available(self): + return pdb._pyrepl_available() + def test_basic_completion(self): script = textwrap.dedent(""" import pdb; pdb.Pdb().set_trace() @@ -5017,12 +5032,12 @@ def test_basic_completion(self): # then add ntin and complete 'contin' to 'continue' input = b"co\t\tntin\t\n" - output = run_pty(script, input) + output = self._run_pty(script, input) - self.assertIn(b'commands', output) - self.assertIn(b'condition', output) - self.assertIn(b'continue', output) - self.assertIn(b'hello!', output) + self.assertIn('commands', output) + self.assertIn('condition', output) + self.assertIn('continue', output) + self.assertIn('hello!', output) def test_expression_completion(self): script = textwrap.dedent(""" @@ -5039,11 +5054,11 @@ def test_expression_completion(self): # Continue input += b"c\n" - output = run_pty(script, input) + output = self._run_pty(script, input) - self.assertIn(b'special', output) - self.assertIn(b'species', output) - self.assertIn(b'$_frame', output) + self.assertIn('special', output) + self.assertIn('species', output) + self.assertIn('$_frame', output) def test_builtin_completion(self): script = textwrap.dedent(""" @@ -5057,9 +5072,9 @@ def test_builtin_completion(self): # Continue input += b"c\n" - output = run_pty(script, input) + output = self._run_pty(script, input) - self.assertIn(b'special', output) + self.assertIn('special', output) def test_convvar_completion(self): script = textwrap.dedent(""" @@ -5075,10 +5090,10 @@ def test_convvar_completion(self): # Continue input += b"c\n" - output = run_pty(script, input) + output = self._run_pty(script, input) - self.assertIn(b' Date: Thu, 30 Apr 2026 10:30:34 +0200 Subject: [PATCH 708/775] Revert pylock.toml change to make MSI builds pass (#149175) GH-149058 made MSI installer tests fail. GHA didn't catch this because MSI-related files weren't changed. This reverts the build.bat change from commit 40dc61a0e0672810c3934da8cc2eda68027c24ce. Also: a README style nitpick to trigger CI. --- Doc/make.bat | 2 +- Tools/msi/README.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Doc/make.bat b/Doc/make.bat index 64a42257c92..99f0d5c44f0 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -13,7 +13,7 @@ if not defined SPHINXBUILD ( %PYTHON% -c "import sphinx" > nul 2> nul if errorlevel 1 ( echo Installing sphinx with %PYTHON% - %PYTHON% -m pip install -r pylock.toml + %PYTHON% -m pip install -r requirements.txt if errorlevel 1 exit /B ) set SPHINXBUILD=%PYTHON% -c "import sphinx.cmd.build, sys; sys.exit(sphinx.cmd.build.main())" diff --git a/Tools/msi/README.txt b/Tools/msi/README.txt index 8ae156450d5..4b3de9e82f6 100644 --- a/Tools/msi/README.txt +++ b/Tools/msi/README.txt @@ -528,4 +528,3 @@ explicitly handled by the installer. Python packages installed later using a tool like pip will not be removed. Some components may be installed by other installers and these will not be removed if another product has a dependency on them. - From 7fe51ceae8513e40452829d7d3ae6ff2a2576a0b Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Thu, 30 Apr 2026 11:36:04 +0200 Subject: [PATCH 709/775] gh-149049: Fix jit binary op stack underflow (GH-149076) --- Lib/test/test_capi/test_opt.py | 32 +++++++++++++++++++ ...-04-28-21-19-21.gh-issue-149049.98u2Ib.rst | 1 + Python/optimizer_bytecodes.c | 8 +++-- Python/optimizer_cases.c.h | 8 +++-- 4 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-28-21-19-21.gh-issue-149049.98u2Ib.rst diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 79643587a60..7118dfeed9f 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3919,6 +3919,38 @@ def testfunc(args): expected = TIER2_THRESHOLD * (5.0 / Fraction(4)) self.assertAlmostEqual(res, float(expected)) + def test_float_truediv_partial_float_no_stack_underflow(self): + # gh-149049: a speculative _GUARD_*_FLOAT for a partially-float + # truediv/remainder must not drop the original _BINARY_OP. + def truediv(args): + n, = args + nan = float("nan") + def victim(a=0, b=nan, c=2): + return (a + b) / c + for _ in range(n): + victim() + + def remainder(args): + n, = args + nan = float("nan") + def victim(a=0, b=nan, c=2): + return (a + b) % c + for _ in range(n): + victim() + + for testfunc in (truediv, remainder): + with self.subTest(op=testfunc.__name__): + # Iterations must be high enough that the buggy trace + # is not only built but executed (where it underflows). + _, ex = self._run_with_optimizer( + testfunc, (TIER2_THRESHOLD * 10,)) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertTrue( + "_GUARD_TOS_FLOAT" in uops or "_GUARD_NOS_FLOAT" in uops, + uops, + ) + def test_int_add_inplace_unique_lhs(self): # a * b produces a unique compact int; adding c reuses it in place def testfunc(args): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-28-21-19-21.gh-issue-149049.98u2Ib.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-28-21-19-21.gh-issue-149049.98u2Ib.rst new file mode 100644 index 00000000000..4c8f7e08a44 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-28-21-19-21.gh-issue-149049.98u2Ib.rst @@ -0,0 +1 @@ +Fix stack underflow for ``BINARY_OP`` in tier 2. diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index ae9e1934144..15d4d0bc181 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -293,6 +293,7 @@ dummy_func(void) { || oparg == NB_INPLACE_TRUE_DIVIDE); bool is_remainder = (oparg == NB_REMAINDER || oparg == NB_INPLACE_REMAINDER); + int emit_op = _BINARY_OP; // Promote probable-float operands to known floats via speculative // guards. _RECORD_TOS_TYPE / _RECORD_NOS_TYPE in the BINARY_OP macro // record the observed operand type during tracing, which @@ -318,17 +319,17 @@ dummy_func(void) { } if (is_truediv && lhs_float && rhs_float) { if (PyJitRef_IsUnique(lhs)) { - ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, 0, 0); + emit_op = _BINARY_OP_TRUEDIV_FLOAT_INPLACE; l = sym_new_null(ctx); r = rhs; } else if (PyJitRef_IsUnique(rhs)) { - ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, 0, 0); + emit_op = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT; l = lhs; r = sym_new_null(ctx); } else { - ADD_OP(_BINARY_OP_TRUEDIV_FLOAT, 0, 0); + emit_op = _BINARY_OP_TRUEDIV_FLOAT; l = lhs; r = rhs; } @@ -382,6 +383,7 @@ dummy_func(void) { else { res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } + ADD_OP(emit_op, oparg, 0); } op(_BINARY_OP_ADD_INT, (left, right -- res, l, r)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index d48f38a95f7..b09aca910fc 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -5242,6 +5242,7 @@ || oparg == NB_INPLACE_TRUE_DIVIDE); bool is_remainder = (oparg == NB_REMAINDER || oparg == NB_INPLACE_REMAINDER); + int emit_op = _BINARY_OP; if (is_truediv || is_remainder) { if (!sym_has_type(rhs) && sym_get_probable_type(rhs) == &PyFloat_Type) { @@ -5258,17 +5259,17 @@ } if (is_truediv && lhs_float && rhs_float) { if (PyJitRef_IsUnique(lhs)) { - ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, 0, 0); + emit_op = _BINARY_OP_TRUEDIV_FLOAT_INPLACE; l = sym_new_null(ctx); r = rhs; } else if (PyJitRef_IsUnique(rhs)) { - ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, 0, 0); + emit_op = _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT; l = lhs; r = sym_new_null(ctx); } else { - ADD_OP(_BINARY_OP_TRUEDIV_FLOAT, 0, 0); + emit_op = _BINARY_OP_TRUEDIV_FLOAT; l = lhs; r = rhs; } @@ -5304,6 +5305,7 @@ else { res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type)); } + ADD_OP(emit_op, oparg, 0); CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; stack_pointer[-1] = l; From 4599335a83a22cf73a0c20e3692c29fd0278d23b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 30 Apr 2026 12:05:48 +0200 Subject: [PATCH 710/775] gh-149122: Fix refleak in codegen (GH-149179) --- Python/codegen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Python/codegen.c b/Python/codegen.c index a371bf332b6..a77451152c6 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -3962,8 +3962,10 @@ maybe_optimize_function_call(compiler *c, expr_ty e, jump_target_label end) expr_ty generator_exp = asdl_seq_GET(args, 0); PySTEntryObject *generator_entry = _PySymtable_Lookup(SYMTABLE(c), (void *)generator_exp); if (generator_entry->ste_coroutine) { + Py_DECREF(generator_entry); return 0; } + Py_DECREF(generator_entry); location loc = LOC(func); From 7686abe063eb7fbf85f33437b9256e0d9e0f4a4f Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Thu, 30 Apr 2026 06:27:57 -0700 Subject: [PATCH 711/775] gh-149085: Add `max_threads` keyword to `faulthandler.dump_traceback()` (GH-149106) Add a keyword-only `max_threads` argument to `dump_traceback()` and `dump_traceback_later()`, defaulting to 100 to preserve existing behavior. Allows server processes with many worker threads to dump beyond the historical 100-thread cap (previously a hardcoded `MAX_NTHREADS = 100` in `Python/traceback.c`). The cap matters in practice: tstates are prepended to the PyInterpreterState linked list, so the dump walks newest-first. With more than 100 threads alive, the main thread (oldest, at the tail) is silently elided from watchdog dumps -- exactly the thread that's usually wanted. The hardcoded value is moved to a new internal macro `_Py_TRACEBACK_MAX_NTHREADS` in `pycore_traceback.h` so the in-tree fatal-signal callers all reference one source of truth. --- Doc/library/faulthandler.rst | 31 ++- Doc/whatsnew/3.15.rst | 9 + Include/internal/pycore_faulthandler.h | 3 + .../pycore_global_objects_fini_generated.h | 1 + Include/internal/pycore_global_strings.h | 1 + .../internal/pycore_runtime_init_generated.h | 1 + Include/internal/pycore_traceback.h | 3 +- .../internal/pycore_unicodeobject_generated.h | 4 + Lib/test/test_faulthandler.py | 110 +++++++++++ ...-04-28-16-30-48.gh-issue-149085.5aNgBD.rst | 3 + Modules/clinic/faulthandler.c.h | 185 +++++++++++++----- Modules/faulthandler.c | 58 ++++-- Python/pylifecycle.c | 2 +- Python/traceback.c | 13 +- 14 files changed, 349 insertions(+), 75 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-28-16-30-48.gh-issue-149085.5aNgBD.rst diff --git a/Doc/library/faulthandler.rst b/Doc/library/faulthandler.rst index 677966a8b2e..529e97bae6d 100644 --- a/Doc/library/faulthandler.rst +++ b/Doc/library/faulthandler.rst @@ -31,7 +31,8 @@ tracebacks: * Each string is limited to 500 characters. * Only the filename, the function name and the line number are displayed. (no source code) -* It is limited to 100 frames and 100 threads. +* It is limited to 100 frames per thread, and 100 threads + (configurable via *max_threads*). * The order is reversed: the most recent call is shown first. By default, the Python traceback is written to :data:`sys.stderr`. To see @@ -55,16 +56,20 @@ at Python startup. Dumping the traceback --------------------- -.. function:: dump_traceback(file=sys.stderr, all_threads=True) +.. function:: dump_traceback(file=sys.stderr, all_threads=True, *, max_threads=100) Dump the tracebacks of all threads into *file*. If *all_threads* is - ``False``, dump only the current thread. + ``False``, dump only the current thread. *max_threads* caps the number + of threads dumped. .. seealso:: :func:`traceback.print_tb`, which can be used to print a traceback object. .. versionchanged:: 3.5 Added support for passing file descriptor to this function. + .. versionchanged:: next + Added the *max_threads* keyword argument. + Dumping the C stack ------------------- @@ -100,7 +105,7 @@ instead of the stack, even if the operating system supports dumping stacks. Fault handler state ------------------- -.. function:: enable(file=sys.stderr, all_threads=True, c_stack=True) +.. function:: enable(file=sys.stderr, all_threads=True, c_stack=True, *, max_threads=100) Enable the fault handler: install handlers for the :const:`~signal.SIGSEGV`, :const:`~signal.SIGFPE`, :const:`~signal.SIGABRT`, :const:`~signal.SIGBUS` @@ -116,6 +121,8 @@ Fault handler state traceback, unless the system does not support it. See :func:`dump_c_stack` for more information on compatibility. + *max_threads* caps the number of threads dumped when a fatal signal fires. + .. versionchanged:: 3.5 Added support for passing file descriptor to this function. @@ -133,6 +140,9 @@ Fault handler state .. versionchanged:: 3.14 The dump now displays the C stack trace if *c_stack* is true. + .. versionchanged:: next + Added the *max_threads* keyword argument. + .. function:: disable() Disable the fault handler: uninstall the signal handlers installed by @@ -146,7 +156,7 @@ Fault handler state Dumping the tracebacks after a timeout -------------------------------------- -.. function:: dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False) +.. function:: dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False, *, max_threads=100) Dump the tracebacks of all threads, after a timeout of *timeout* seconds, or every *timeout* seconds if *repeat* is ``True``. If *exit* is ``True``, call @@ -154,7 +164,7 @@ Dumping the tracebacks after a timeout :c:func:`!_exit` exits the process immediately, which means it doesn't do any cleanup like flushing file buffers.) If the function is called twice, the new call replaces previous parameters and resets the timeout. The timer has a - sub-second resolution. + sub-second resolution. *max_threads* caps the number of threads dumped. The *file* must be kept open until the traceback is dumped or :func:`cancel_dump_traceback_later` is called: see :ref:`issue with file @@ -168,6 +178,9 @@ Dumping the tracebacks after a timeout .. versionchanged:: 3.7 This function is now always available. + .. versionchanged:: next + Added the *max_threads* keyword argument. + .. function:: cancel_dump_traceback_later() Cancel the last call to :func:`dump_traceback_later`. @@ -176,11 +189,12 @@ Dumping the tracebacks after a timeout Dumping the traceback on a user signal -------------------------------------- -.. function:: register(signum, file=sys.stderr, all_threads=True, chain=False) +.. function:: register(signum, file=sys.stderr, all_threads=True, chain=False, *, max_threads=100) Register a user signal: install a handler for the *signum* signal to dump the traceback of all threads, or of the current thread if *all_threads* is ``False``, into *file*. Call the previous handler if chain is ``True``. + *max_threads* caps the number of threads dumped. The *file* must be kept open until the signal is unregistered by :func:`unregister`: see :ref:`issue with file descriptors `. @@ -190,6 +204,9 @@ Dumping the traceback on a user signal .. versionchanged:: 3.5 Added support for passing file descriptor to this function. + .. versionchanged:: next + Added the *max_threads* keyword argument. + .. function:: unregister(signum) Unregister a user signal: uninstall the handler of the *signum* signal diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 56b2553a401..59b9688c18e 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -905,6 +905,15 @@ difflib (Contributed by Jiahao Li in :gh:`134580`.) +faulthandler +------------ + +* Added the *max_threads* parameter in :func:`faulthandler.enable`, + :func:`faulthandler.dump_traceback`, :func:`faulthandler.dump_traceback_later`, + and :func:`faulthandler.register`. + (Contributed by Eric Froemling in :gh:`149085`.) + + functools --------- diff --git a/Include/internal/pycore_faulthandler.h b/Include/internal/pycore_faulthandler.h index 78cd657e6ae..9ddd70d39ed 100644 --- a/Include/internal/pycore_faulthandler.h +++ b/Include/internal/pycore_faulthandler.h @@ -42,6 +42,7 @@ struct faulthandler_user_signal { int chain; _Py_sighandler_t previous; PyInterpreterState *interp; + Py_ssize_t max_threads; }; #endif /* FAULTHANDLER_USER */ @@ -57,6 +58,7 @@ struct _faulthandler_runtime_state { void *exc_handler; #endif int c_stack; + Py_ssize_t max_threads; } fatal_error; struct { @@ -68,6 +70,7 @@ struct _faulthandler_runtime_state { int exit; char *header; size_t header_len; + Py_ssize_t max_threads; /* The main thread always holds this lock. It is only released when faulthandler_thread() is interrupted before this thread exits, or at Python exit. */ diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 4fd42185d8a..4d6d5ce9c5e 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1897,6 +1897,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mask)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(match)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(max_length)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(max_threads)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxdigits)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxevents)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(maxlen)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index f2d43c22069..20dcf81ccf1 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -620,6 +620,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(mask) STRUCT_FOR_ID(match) STRUCT_FOR_ID(max_length) + STRUCT_FOR_ID(max_threads) STRUCT_FOR_ID(maxdigits) STRUCT_FOR_ID(maxevents) STRUCT_FOR_ID(maxlen) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 6ee64a461d8..1ce91dc51ea 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1895,6 +1895,7 @@ extern "C" { INIT_ID(mask), \ INIT_ID(match), \ INIT_ID(max_length), \ + INIT_ID(max_threads), \ INIT_ID(maxdigits), \ INIT_ID(maxevents), \ INIT_ID(maxlen), \ diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index 6b5e24979d5..fbf6bc2c41f 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -61,7 +61,8 @@ extern void _Py_DumpTraceback( extern const char* _Py_DumpTracebackThreads( int fd, PyInterpreterState *interp, - PyThreadState *current_tstate); + PyThreadState *current_tstate, + Py_ssize_t max_threads); /* Write a Unicode object into the file descriptor fd. Encode the string to ASCII using the backslashreplace error handler. diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index bcb117e1091..c7c23494845 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -2260,6 +2260,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(max_threads); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(maxdigits); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 5e88ae47775..11df59f2346 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -719,6 +719,76 @@ def test_dump_traceback_later_fd(self): def test_dump_traceback_later_twice(self): self.check_dump_traceback_later(loops=2) + def test_dump_traceback_max_threads(self): + # max_threads caps the dump and writes "...\n" when truncated. + # Spawn N worker threads, dump with cap < N, and verify the + # marker is present and exactly CAP thread headers are written. + code = dedent(""" + import faulthandler + import sys + import threading + + NTHREADS = 6 + CAP = 3 + + ready = threading.Barrier(NTHREADS + 1) + stop = threading.Event() + + def worker(): + ready.wait() + stop.wait() + + threads = [threading.Thread(target=worker) for _ in range(NTHREADS)] + for t in threads: + t.start() + ready.wait() + try: + faulthandler.dump_traceback(file=sys.stderr, max_threads=CAP) + finally: + stop.set() + for t in threads: + t.join() + """).strip() + proc = script_helper.assert_python_ok('-c', code) + output = proc.err + # Truncation marker is written on its own line when the cap is hit. + self.assertIn(b"\n...\n", output) + # Cap of 3 means exactly 3 thread headers in the dump. + self.assertEqual(output.count(b"Thread 0x"), 3) + + @skip_segfault_on_android + @unittest.skipIf(support.Py_GIL_DISABLED, + "fatal-signal handler only dumps the current thread " + "when the GIL is disabled") + def test_enable_max_threads(self): + # enable(max_threads=N) caps the thread dump produced when a + # fatal signal fires. + code = dedent(""" + import faulthandler + import threading + + NTHREADS = 6 + CAP = 3 + + ready = threading.Barrier(NTHREADS + 1) + stop = threading.Event() + + def worker(): + ready.wait() + stop.wait() + + for _ in range(NTHREADS): + threading.Thread(target=worker, daemon=True).start() + ready.wait() + faulthandler.enable(max_threads=CAP) + faulthandler._sigsegv() + """).strip() + output, exitcode = self.get_output(code) + output = '\n'.join(output) + # Cap of 3 means the dump is truncated with "..." on its own line. + self.assertIn("\n...\n", output) + self.assertNotEqual(exitcode, 0) + @unittest.skipIf(not hasattr(faulthandler, "register"), "need faulthandler.register") def check_register(self, filename=False, all_threads=False, @@ -825,6 +895,46 @@ def test_register_threads(self): def test_register_chain(self): self.check_register(chain=True) + @unittest.skipIf(not hasattr(faulthandler, "register"), + "need faulthandler.register") + def test_register_max_threads(self): + # register(max_threads=N) caps the thread dump produced when + # the registered signal fires. + code = dedent(""" + import faulthandler + import signal + import threading + + NTHREADS = 6 + CAP = 3 + + ready = threading.Barrier(NTHREADS + 1) + stop = threading.Event() + + def worker(): + ready.wait() + stop.wait() + + threads = [threading.Thread(target=worker) for _ in range(NTHREADS)] + for t in threads: + t.start() + ready.wait() + try: + faulthandler.register(signal.SIGUSR1, all_threads=True, + max_threads=CAP) + signal.raise_signal(signal.SIGUSR1) + finally: + stop.set() + for t in threads: + t.join() + """).strip() + proc = script_helper.assert_python_ok('-c', code) + output = proc.err + # Cap of 3 means the dump is truncated with "..." on its own line. + self.assertIn(b"\n...\n", output) + # Cap of 3 means exactly 3 thread headers in the dump. + self.assertEqual(output.count(b"Thread 0x"), 3) + @contextmanager def check_stderr_none(self): stderr = sys.stderr diff --git a/Misc/NEWS.d/next/Library/2026-04-28-16-30-48.gh-issue-149085.5aNgBD.rst b/Misc/NEWS.d/next/Library/2026-04-28-16-30-48.gh-issue-149085.5aNgBD.rst new file mode 100644 index 00000000000..a5b92287bd0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-28-16-30-48.gh-issue-149085.5aNgBD.rst @@ -0,0 +1,3 @@ +Add a *max_threads* keyword argument to :func:`faulthandler.dump_traceback`, +:func:`faulthandler.dump_traceback_later`, :func:`faulthandler.enable`, and +:func:`faulthandler.register`. diff --git a/Modules/clinic/faulthandler.c.h b/Modules/clinic/faulthandler.c.h index de8280ce26b..e06cfdcfba2 100644 --- a/Modules/clinic/faulthandler.c.h +++ b/Modules/clinic/faulthandler.c.h @@ -6,23 +6,26 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_long.h" // _PyLong_UnsignedInt_Converter() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(faulthandler_dump_traceback_py__doc__, -"dump_traceback($module, /, file=sys.stderr, all_threads=True)\n" +"dump_traceback($module, /, file=sys.stderr, all_threads=True, *,\n" +" max_threads=100)\n" "--\n" "\n" "Dump the traceback of the current thread into file.\n" "\n" -"Dump the traceback of all threads if all_threads is true."); +"Dump the traceback of all threads if all_threads is true. max_threads\n" +"caps the number of threads dumped."); #define FAULTHANDLER_DUMP_TRACEBACK_PY_METHODDEF \ {"dump_traceback", _PyCFunction_CAST(faulthandler_dump_traceback_py), METH_FASTCALL|METH_KEYWORDS, faulthandler_dump_traceback_py__doc__}, static PyObject * faulthandler_dump_traceback_py_impl(PyObject *module, PyObject *file, - int all_threads); + int all_threads, Py_ssize_t max_threads); static PyObject * faulthandler_dump_traceback_py(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -30,7 +33,7 @@ faulthandler_dump_traceback_py(PyObject *module, PyObject *const *args, Py_ssize PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -39,7 +42,7 @@ faulthandler_dump_traceback_py(PyObject *module, PyObject *const *args, Py_ssize } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(file), &_Py_ID(all_threads), }, + .ob_item = { &_Py_ID(file), &_Py_ID(all_threads), &_Py_ID(max_threads), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -48,17 +51,18 @@ faulthandler_dump_traceback_py(PyObject *module, PyObject *const *args, Py_ssize # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"file", "all_threads", NULL}; + static const char * const _keywords[] = {"file", "all_threads", "max_threads", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "dump_traceback", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[2]; + PyObject *argsbuf[3]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *file = NULL; int all_threads = 1; + Py_ssize_t max_threads = 100; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -74,12 +78,33 @@ faulthandler_dump_traceback_py(PyObject *module, PyObject *const *args, Py_ssize goto skip_optional_pos; } } - all_threads = PyObject_IsTrue(args[1]); - if (all_threads < 0) { - goto exit; + if (args[1]) { + all_threads = PyObject_IsTrue(args[1]); + if (all_threads < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - return_value = faulthandler_dump_traceback_py_impl(module, file, all_threads); + if (!noptargs) { + goto skip_optional_kwonly; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + max_threads = ival; + } +skip_optional_kwonly: + return_value = faulthandler_dump_traceback_py_impl(module, file, all_threads, max_threads); exit: return return_value; @@ -149,7 +174,8 @@ exit: } PyDoc_STRVAR(faulthandler_py_enable__doc__, -"enable($module, /, file=sys.stderr, all_threads=True, c_stack=True)\n" +"enable($module, /, file=sys.stderr, all_threads=True, c_stack=True, *,\n" +" max_threads=100)\n" "--\n" "\n" "Enable the fault handler."); @@ -159,7 +185,8 @@ PyDoc_STRVAR(faulthandler_py_enable__doc__, static PyObject * faulthandler_py_enable_impl(PyObject *module, PyObject *file, - int all_threads, int c_stack); + int all_threads, int c_stack, + Py_ssize_t max_threads); static PyObject * faulthandler_py_enable(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -167,7 +194,7 @@ faulthandler_py_enable(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -176,7 +203,7 @@ faulthandler_py_enable(PyObject *module, PyObject *const *args, Py_ssize_t nargs } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(file), &_Py_ID(all_threads), &_Py_ID(c_stack), }, + .ob_item = { &_Py_ID(file), &_Py_ID(all_threads), &_Py_ID(c_stack), &_Py_ID(max_threads), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -185,18 +212,19 @@ faulthandler_py_enable(PyObject *module, PyObject *const *args, Py_ssize_t nargs # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"file", "all_threads", "c_stack", NULL}; + static const char * const _keywords[] = {"file", "all_threads", "c_stack", "max_threads", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "enable", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[3]; + PyObject *argsbuf[4]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *file = NULL; int all_threads = 1; int c_stack = 1; + Py_ssize_t max_threads = 100; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -221,12 +249,33 @@ faulthandler_py_enable(PyObject *module, PyObject *const *args, Py_ssize_t nargs goto skip_optional_pos; } } - c_stack = PyObject_IsTrue(args[2]); - if (c_stack < 0) { - goto exit; + if (args[2]) { + c_stack = PyObject_IsTrue(args[2]); + if (c_stack < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - return_value = faulthandler_py_enable_impl(module, file, all_threads, c_stack); + if (!noptargs) { + goto skip_optional_kwonly; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[3]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + max_threads = ival; + } +skip_optional_kwonly: + return_value = faulthandler_py_enable_impl(module, file, all_threads, c_stack, max_threads); exit: return return_value; @@ -280,13 +329,14 @@ exit: PyDoc_STRVAR(faulthandler_dump_traceback_later__doc__, "dump_traceback_later($module, /, timeout, repeat=False,\n" -" file=sys.stderr, exit=False)\n" +" file=sys.stderr, exit=False, *, max_threads=100)\n" "--\n" "\n" "Dump the traceback of all threads in timeout seconds.\n" "\n" "If repeat is true, the tracebacks of all threads are dumped every timeout\n" -"seconds. If exit is true, call _exit(1) which is not safe."); +"seconds. If exit is true, call _exit(1) which is not safe. max_threads\n" +"caps the number of threads dumped."); #define FAULTHANDLER_DUMP_TRACEBACK_LATER_METHODDEF \ {"dump_traceback_later", _PyCFunction_CAST(faulthandler_dump_traceback_later), METH_FASTCALL|METH_KEYWORDS, faulthandler_dump_traceback_later__doc__}, @@ -294,7 +344,8 @@ PyDoc_STRVAR(faulthandler_dump_traceback_later__doc__, static PyObject * faulthandler_dump_traceback_later_impl(PyObject *module, PyObject *timeout_obj, int repeat, - PyObject *file, int exit); + PyObject *file, int exit, + Py_ssize_t max_threads); static PyObject * faulthandler_dump_traceback_later(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -302,7 +353,7 @@ faulthandler_dump_traceback_later(PyObject *module, PyObject *const *args, Py_ss PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 5 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -311,7 +362,7 @@ faulthandler_dump_traceback_later(PyObject *module, PyObject *const *args, Py_ss } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(timeout), &_Py_ID(repeat), &_Py_ID(file), &_Py_ID(exit), }, + .ob_item = { &_Py_ID(timeout), &_Py_ID(repeat), &_Py_ID(file), &_Py_ID(exit), &_Py_ID(max_threads), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -320,19 +371,20 @@ faulthandler_dump_traceback_later(PyObject *module, PyObject *const *args, Py_ss # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"timeout", "repeat", "file", "exit", NULL}; + static const char * const _keywords[] = {"timeout", "repeat", "file", "exit", "max_threads", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "dump_traceback_later", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; PyObject *timeout_obj; int repeat = 0; PyObject *file = NULL; int exit = 0; + Py_ssize_t max_threads = 100; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 4, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -358,12 +410,33 @@ faulthandler_dump_traceback_later(PyObject *module, PyObject *const *args, Py_ss goto skip_optional_pos; } } - exit = PyObject_IsTrue(args[3]); - if (exit < 0) { - goto exit; + if (args[3]) { + exit = PyObject_IsTrue(args[3]); + if (exit < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - return_value = faulthandler_dump_traceback_later_impl(module, timeout_obj, repeat, file, exit); + if (!noptargs) { + goto skip_optional_kwonly; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[4]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + max_threads = ival; + } +skip_optional_kwonly: + return_value = faulthandler_dump_traceback_later_impl(module, timeout_obj, repeat, file, exit, max_threads); exit: return return_value; @@ -391,20 +464,22 @@ faulthandler_cancel_dump_traceback_later_py(PyObject *module, PyObject *Py_UNUSE PyDoc_STRVAR(faulthandler_register_py__doc__, "register($module, /, signum, file=sys.stderr, all_threads=True,\n" -" chain=False)\n" +" chain=False, *, max_threads=100)\n" "--\n" "\n" "Register a handler for the signal \'signum\'.\n" "\n" "Dump the traceback of the current thread, or of all threads if\n" -"all_threads is True, into file."); +"all_threads is True, into file. max_threads caps the number of threads\n" +"dumped."); #define FAULTHANDLER_REGISTER_PY_METHODDEF \ {"register", _PyCFunction_CAST(faulthandler_register_py), METH_FASTCALL|METH_KEYWORDS, faulthandler_register_py__doc__}, static PyObject * faulthandler_register_py_impl(PyObject *module, int signum, PyObject *file, - int all_threads, int chain); + int all_threads, int chain, + Py_ssize_t max_threads); static PyObject * faulthandler_register_py(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -412,7 +487,7 @@ faulthandler_register_py(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 5 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -421,7 +496,7 @@ faulthandler_register_py(PyObject *module, PyObject *const *args, Py_ssize_t nar } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(signum), &_Py_ID(file), &_Py_ID(all_threads), &_Py_ID(chain), }, + .ob_item = { &_Py_ID(signum), &_Py_ID(file), &_Py_ID(all_threads), &_Py_ID(chain), &_Py_ID(max_threads), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -430,19 +505,20 @@ faulthandler_register_py(PyObject *module, PyObject *const *args, Py_ssize_t nar # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"signum", "file", "all_threads", "chain", NULL}; + static const char * const _keywords[] = {"signum", "file", "all_threads", "chain", "max_threads", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "register", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; int signum; PyObject *file = NULL; int all_threads = 1; int chain = 0; + Py_ssize_t max_threads = 100; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 1, /*maxpos*/ 4, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -471,12 +547,33 @@ faulthandler_register_py(PyObject *module, PyObject *const *args, Py_ssize_t nar goto skip_optional_pos; } } - chain = PyObject_IsTrue(args[3]); - if (chain < 0) { - goto exit; + if (args[3]) { + chain = PyObject_IsTrue(args[3]); + if (chain < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - return_value = faulthandler_register_py_impl(module, signum, file, all_threads, chain); + if (!noptargs) { + goto skip_optional_kwonly; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[4]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + max_threads = ival; + } +skip_optional_kwonly: + return_value = faulthandler_register_py_impl(module, signum, file, all_threads, chain, max_threads); exit: return return_value; @@ -685,4 +782,4 @@ exit: #ifndef FAULTHANDLER__RAISE_EXCEPTION_METHODDEF #define FAULTHANDLER__RAISE_EXCEPTION_METHODDEF #endif /* !defined(FAULTHANDLER__RAISE_EXCEPTION_METHODDEF) */ -/*[clinic end generated code: output=31bf0149d0d02ccf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2452d767c85130a6 input=a9049054013a1b77]*/ diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index bc7731c2588..923f6f5b56d 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -185,7 +185,8 @@ get_thread_state(void) static void faulthandler_dump_traceback(int fd, int all_threads, - PyInterpreterState *interp) + PyInterpreterState *interp, + Py_ssize_t max_threads) { static volatile int reentrant = 0; @@ -205,7 +206,7 @@ faulthandler_dump_traceback(int fd, int all_threads, PyThreadState *tstate = PyGILState_GetThisThreadState(); if (all_threads == 1) { - (void)_Py_DumpTracebackThreads(fd, NULL, tstate); + (void)_Py_DumpTracebackThreads(fd, NULL, tstate, max_threads); } else { if (all_threads == FT_IGNORE_ALL_THREADS) { @@ -243,16 +244,19 @@ faulthandler.dump_traceback as faulthandler_dump_traceback_py file: object(py_default="sys.stderr") = NULL all_threads: bool = True + * + max_threads: Py_ssize_t = 100 Dump the traceback of the current thread into file. -Dump the traceback of all threads if all_threads is true. +Dump the traceback of all threads if all_threads is true. max_threads +caps the number of threads dumped. [clinic start generated code]*/ static PyObject * faulthandler_dump_traceback_py_impl(PyObject *module, PyObject *file, - int all_threads) -/*[clinic end generated code: output=34efece0ca18314f input=b832ec55e27a7898]*/ + int all_threads, Py_ssize_t max_threads) +/*[clinic end generated code: output=ee1bbc2668e56e77 input=38630eb40e641de6]*/ { PyThreadState *tstate; const char *errmsg; @@ -273,7 +277,7 @@ faulthandler_dump_traceback_py_impl(PyObject *module, PyObject *file, /* gh-128400: Accessing other thread states while they're running * isn't safe if those threads are running. */ _PyEval_StopTheWorld(interp); - errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate); + errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate, max_threads); _PyEval_StartTheWorld(interp); if (errmsg != NULL) { PyErr_SetString(PyExc_RuntimeError, errmsg); @@ -409,7 +413,8 @@ faulthandler_fatal_error(int signum) } faulthandler_dump_traceback(fd, deduce_all_threads(), - fatal_error.interp); + fatal_error.interp, + fatal_error.max_threads); faulthandler_dump_c_stack(fd); _Py_DumpExtensionModules(fd, fatal_error.interp); @@ -485,7 +490,8 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) } faulthandler_dump_traceback(fd, deduce_all_threads(), - fatal_error.interp); + fatal_error.interp, + fatal_error.max_threads); faulthandler_dump_c_stack(fd); /* call the next exception handler */ @@ -590,14 +596,17 @@ faulthandler.enable as faulthandler_py_enable file: object(py_default="sys.stderr") = NULL all_threads: bool = True c_stack: bool = True + * + max_threads: Py_ssize_t = 100 Enable the fault handler. [clinic start generated code]*/ static PyObject * faulthandler_py_enable_impl(PyObject *module, PyObject *file, - int all_threads, int c_stack) -/*[clinic end generated code: output=580d89b5eb62f1cb input=77277746a88b25ca]*/ + int all_threads, int c_stack, + Py_ssize_t max_threads) +/*[clinic end generated code: output=7ee655332317c47a input=e64759714f27b466]*/ { int fd; PyThreadState *tstate; @@ -617,6 +626,7 @@ faulthandler_py_enable_impl(PyObject *module, PyObject *file, fatal_error.all_threads = all_threads; fatal_error.interp = PyThreadState_GetInterpreter(tstate); fatal_error.c_stack = c_stack; + fatal_error.max_threads = max_threads; if (faulthandler_enable() < 0) { return NULL; @@ -703,7 +713,8 @@ faulthandler_thread(void *unused) (void)_Py_write_noraise(thread.fd, thread.header, (int)thread.header_len); - errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, NULL); + errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, NULL, + thread.max_threads); ok = (errmsg == NULL); if (thread.exit) @@ -777,18 +788,22 @@ faulthandler.dump_traceback_later repeat: bool = False file: object(py_default="sys.stderr") = NULL exit: bool = False + * + max_threads: Py_ssize_t = 100 Dump the traceback of all threads in timeout seconds. If repeat is true, the tracebacks of all threads are dumped every timeout -seconds. If exit is true, call _exit(1) which is not safe. +seconds. If exit is true, call _exit(1) which is not safe. max_threads +caps the number of threads dumped. [clinic start generated code]*/ static PyObject * faulthandler_dump_traceback_later_impl(PyObject *module, PyObject *timeout_obj, int repeat, - PyObject *file, int exit) -/*[clinic end generated code: output=a24d80d694d25ba2 input=fd005625ecc2ba9a]*/ + PyObject *file, int exit, + Py_ssize_t max_threads) +/*[clinic end generated code: output=543a0f3807113394 input=6836555ee157ddb4]*/ { PyTime_t timeout, timeout_us; int fd; @@ -861,6 +876,7 @@ faulthandler_dump_traceback_later_impl(PyObject *module, thread.exit = exit; thread.header = header; thread.header_len = header_len; + thread.max_threads = max_threads; /* Arm these locks to serve as events when released */ PyThread_acquire_lock(thread.running, 1); @@ -945,7 +961,8 @@ faulthandler_user(int signum) if (!user->enabled) return; - faulthandler_dump_traceback(user->fd, user->all_threads, user->interp); + faulthandler_dump_traceback(user->fd, user->all_threads, user->interp, + user->max_threads); #ifdef HAVE_SIGACTION if (user->chain) { @@ -995,17 +1012,21 @@ faulthandler.register as faulthandler_register_py file: object(py_default="sys.stderr") = NULL all_threads: bool = True chain: bool = False + * + max_threads: Py_ssize_t = 100 Register a handler for the signal 'signum'. Dump the traceback of the current thread, or of all threads if -all_threads is True, into file. +all_threads is True, into file. max_threads caps the number of threads +dumped. [clinic start generated code]*/ static PyObject * faulthandler_register_py_impl(PyObject *module, int signum, PyObject *file, - int all_threads, int chain) -/*[clinic end generated code: output=1f770cee150a56cd input=ae9de829e850907b]*/ + int all_threads, int chain, + Py_ssize_t max_threads) +/*[clinic end generated code: output=d63a5b4f388dee5f input=c75096a20de502fe]*/ { int fd; user_signal_t *user; @@ -1056,6 +1077,7 @@ faulthandler_register_py_impl(PyObject *module, int signum, PyObject *file, user->all_threads = all_threads; user->chain = chain; user->interp = PyThreadState_GetInterpreter(tstate); + user->max_threads = max_threads; user->enabled = 1; Py_RETURN_NONE; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 0a88e32bb6b..57ce519c3c1 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -3342,7 +3342,7 @@ _Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp, /* display the current Python stack */ #ifndef Py_GIL_DISABLED - _Py_DumpTracebackThreads(fd, interp, tstate); + _Py_DumpTracebackThreads(fd, interp, tstate, 0); #else _Py_DumpTraceback(fd, tstate); #endif diff --git a/Python/traceback.c b/Python/traceback.c index 1e8c9c879f9..f0e0df7101b 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -55,7 +55,7 @@ #define MAX_STRING_LENGTH 500 #define MAX_FRAME_DEPTH 100 -#define MAX_NTHREADS 100 +#define DEFAULT_MAX_NTHREADS 100 /* Function from Parser/tokenizer/file_tokenizer.c */ extern char* _PyTokenizer_FindEncodingFilename(int, PyObject *); @@ -1265,8 +1265,13 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current) handlers if signals were received. */ const char* _Py_NO_SANITIZE_THREAD _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, - PyThreadState *current_tstate) + PyThreadState *current_tstate, + Py_ssize_t max_threads) { + if (max_threads == 0) { + max_threads = DEFAULT_MAX_NTHREADS; + } + if (current_tstate == NULL) { /* _Py_DumpTracebackThreads() is called from signal handlers by faulthandler. @@ -1310,13 +1315,13 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, return "unable to get the thread head state"; /* Dump the traceback of each thread */ - unsigned int nthreads = 0; + Py_ssize_t nthreads = 0; _Py_BEGIN_SUPPRESS_IPH do { if (nthreads != 0) PUTS(fd, "\n"); - if (nthreads >= MAX_NTHREADS) { + if (nthreads >= max_threads) { PUTS(fd, "...\n"); break; } From 9d41e2a534aab460dd656ef251adaed5d2d64b93 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 30 Apr 2026 16:33:13 +0200 Subject: [PATCH 712/775] gh-111264: Add a note about untrusted input to tomllib docs (GH-146209) Co-authored-by: Stan Ulbrych --- Doc/library/tomllib.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/library/tomllib.rst b/Doc/library/tomllib.rst index 2bac968c2be..55610784362 100644 --- a/Doc/library/tomllib.rst +++ b/Doc/library/tomllib.rst @@ -19,6 +19,12 @@ support writing TOML. Added TOML 1.1.0 support. See the :ref:`What's New ` for details. +.. warning:: + + Be cautious when parsing data from untrusted sources. + A malicious TOML string may cause the decoder to consume considerable + CPU and memory resources. + Limiting the size of data to be parsed is recommended. .. seealso:: From f0e90d78eb115da99e4ce0d1425593f3b71fd975 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 30 Apr 2026 16:57:29 +0200 Subject: [PATCH 713/775] gh-148829: Move sentinelobject.h to Include/cpython/ (#149186) This C API is not part of the limited C API, so move it to the CPython C API. --- Include/Python.h | 2 +- Include/{ => cpython}/sentinelobject.h | 4 ++-- Makefile.pre.in | 2 +- PCbuild/pythoncore.vcxproj | 2 +- PCbuild/pythoncore.vcxproj.filters | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) rename Include/{ => cpython}/sentinelobject.h (93%) diff --git a/Include/Python.h b/Include/Python.h index 1272e2464f9..d5e38b8b020 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -117,7 +117,7 @@ __pragma(warning(disable: 4201)) #include "cpython/genobject.h" #include "descrobject.h" #include "genericaliasobject.h" -#include "sentinelobject.h" +#include "cpython/sentinelobject.h" #include "warnings.h" #include "weakrefobject.h" #include "structseq.h" diff --git a/Include/sentinelobject.h b/Include/cpython/sentinelobject.h similarity index 93% rename from Include/sentinelobject.h rename to Include/cpython/sentinelobject.h index 9d8577767b7..0b6ff0f17e6 100644 --- a/Include/sentinelobject.h +++ b/Include/cpython/sentinelobject.h @@ -1,12 +1,12 @@ /* Sentinel object interface */ +#ifndef Py_LIMITED_API #ifndef Py_SENTINELOBJECT_H #define Py_SENTINELOBJECT_H #ifdef __cplusplus extern "C" { #endif -#ifndef Py_LIMITED_API PyAPI_DATA(PyTypeObject) PySentinel_Type; #define PySentinel_Check(op) Py_IS_TYPE((op), &PySentinel_Type) @@ -14,9 +14,9 @@ PyAPI_DATA(PyTypeObject) PySentinel_Type; PyAPI_FUNC(PyObject *) PySentinel_New( const char *name, const char *module_name); -#endif #ifdef __cplusplus } #endif #endif /* !Py_SENTINELOBJECT_H */ +#endif /* !Py_LIMITED_API */ diff --git a/Makefile.pre.in b/Makefile.pre.in index 2ce53c6a816..0edf55d991a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1241,7 +1241,6 @@ PYTHON_HEADERS= \ $(srcdir)/Include/pytypedefs.h \ $(srcdir)/Include/rangeobject.h \ $(srcdir)/Include/refcount.h \ - $(srcdir)/Include/sentinelobject.h \ $(srcdir)/Include/setobject.h \ $(srcdir)/Include/sliceobject.h \ $(srcdir)/Include/structmember.h \ @@ -1309,6 +1308,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/cpython/pystats.h \ $(srcdir)/Include/cpython/pythonrun.h \ $(srcdir)/Include/cpython/pythread.h \ + $(srcdir)/Include/cpython/sentinelobject.h \ $(srcdir)/Include/cpython/setobject.h \ $(srcdir)/Include/cpython/sliceobject.h \ $(srcdir)/Include/cpython/structseq.h \ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index fb9217fee8b..fae4a90b453 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -195,6 +195,7 @@ + @@ -384,7 +385,6 @@ - diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 1e1d085cd75..04b6641ae30 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -222,9 +222,6 @@ Include - - Include - Include @@ -522,6 +519,9 @@ Include\cpython + + Include + Include\cpython From cc5f8b5434c8b2a2d7858ef9a8d182344bc781b8 Mon Sep 17 00:00:00 2001 From: John Comeau Date: Thu, 30 Apr 2026 08:00:48 -0700 Subject: [PATCH 714/775] gh-113471: Add custom default Content-Type to http.server (#113475) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Serhiy Storchaka Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: donBarbos Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Doc/library/http.server.rst | 20 +++++++++++++++++++ Doc/whatsnew/3.15.rst | 6 ++++++ Lib/http/server.py | 12 +++++++++-- Lib/test/test_httpservers.py | 11 ++++++++++ ...-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst | 2 ++ 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index 33ecaae5c87..5f325df5570 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -390,6 +390,14 @@ instantiation, of which this module provides three different variants: This will be ``"SimpleHTTP/" + __version__``, where ``__version__`` is defined at the module level. + .. attribute:: default_content_type + + Specifies the Content-Type header value sent when the MIME type + cannot be guessed from the file extension of the requested URL. + By default, it is set to ``'application/octet-stream'``. + + .. versionadded:: next + .. attribute:: extensions_map A dictionary mapping suffixes into MIME types, contains custom overrides @@ -528,6 +536,18 @@ The following options are accepted: .. versionadded:: 3.11 +.. option:: --content-type + + Specifies the default Content-Type HTTP header used when the MIME type + cannot be guessed from the URL's file extension. By default, the server + uses ``'application/octet-stream'``: + + .. code-block:: bash + + python -m http.server --content-type text/html + + .. versionadded:: next + .. option:: --tls-cert Specifies a TLS certificate chain for HTTPS connections: diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 59b9688c18e..90d24bf96af 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -964,6 +964,12 @@ http.server `. (Contributed by Hugo van Kemenade in :gh:`146292`.) +* Added :attr:`~http.server.SimpleHTTPRequestHandler.default_content_type` + and the :option:`--content-type ` command-line + option to allow customizing the default ``Content-Type`` header + for files with unknown extensions. + (Contributed by John Comeau and Hugo van Kemenade in :gh:`113471`.) + inspect ------- diff --git a/Lib/http/server.py b/Lib/http/server.py index 568d3bb38de..27ab37303a0 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -727,6 +727,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): """ server_version = "SimpleHTTP" + default_content_type = "application/octet-stream" index_pages = ("index.html", "index.htm") extensions_map = _encodings_map_default = { '.gz': 'application/gzip', @@ -974,7 +975,7 @@ def guess_type(self, path): guess, _ = mimetypes.guess_file_type(path) if guess: return guess - return 'application/octet-stream' + return self.default_content_type nobody = None @@ -1010,9 +1011,10 @@ def _get_best_family(*address): return family, sockaddr -def test(HandlerClass=BaseHTTPRequestHandler, +def test(HandlerClass=SimpleHTTPRequestHandler, ServerClass=ThreadingHTTPServer, protocol="HTTP/1.0", port=8000, bind=None, + content_type=SimpleHTTPRequestHandler.default_content_type, tls_cert=None, tls_key=None, tls_password=None): """Test the HTTP request handler class. @@ -1021,6 +1023,7 @@ def test(HandlerClass=BaseHTTPRequestHandler, """ ServerClass.address_family, addr = _get_best_family(bind, port) HandlerClass.protocol_version = protocol + HandlerClass.default_content_type = content_type if tls_cert: server = ServerClass(addr, HandlerClass, certfile=tls_cert, @@ -1060,6 +1063,10 @@ def _main(args=None): default='HTTP/1.0', help='conform to this HTTP version ' '(default: %(default)s)') + parser.add_argument('--content-type', + default=SimpleHTTPRequestHandler.default_content_type, + help='default content type for unknown extensions ' + '(default: %(default)s)') parser.add_argument('--tls-cert', metavar='PATH', help='path to the TLS certificate chain file') parser.add_argument('--tls-key', metavar='PATH', @@ -1112,6 +1119,7 @@ class HTTPSDualStackServer(DualStackServerMixin, ThreadingHTTPSServer): port=args.port, bind=args.bind, protocol=args.protocol, + content_type=args.content_type, tls_cert=args.tls_cert, tls_key=args.tls_key, tls_password=tls_key_password, diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index d78b94e3a37..1f7a5a42fda 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -1379,6 +1379,7 @@ class CommandLineTestCase(unittest.TestCase): 'protocol': default_protocol, 'port': default_port, 'bind': default_bind, + 'content_type': 'application/octet-stream', 'tls_cert': None, 'tls_key': None, 'tls_password': None, @@ -1447,6 +1448,16 @@ def test_protocol_flag(self, mock_func): mock_func.assert_called_once_with(**call_args) mock_func.reset_mock() + @mock.patch('http.server.test') + def test_content_type_flag(self, mock_func): + content_types = ['text/html', 'text/plain', 'application/json'] + for content_type in content_types: + with self.subTest(content_type=content_type): + self.invoke_httpd('--content-type', content_type) + call_args = self.args | dict(content_type=content_type) + mock_func.assert_called_once_with(**call_args) + mock_func.reset_mock() + @unittest.skipIf(ssl is None, "requires ssl") @mock.patch('http.server.test') def test_tls_cert_and_key_flags(self, mock_func): diff --git a/Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst b/Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst new file mode 100644 index 00000000000..99ba9bd1820 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst @@ -0,0 +1,2 @@ +Allow :mod:`http.server` to set a default content-type when serving +files with an unknown or missing extension. From bf424816d0643a4c4566f2e33dc4e1beb5ec875c Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 30 Apr 2026 19:18:56 +0300 Subject: [PATCH 715/775] gh-149083: Use `sentinel` in `functools.rst` docs (#149176) --- Doc/library/functools.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 265610db3ca..7da59cba517 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -468,7 +468,7 @@ The :mod:`!functools` module defines the following functions: Roughly equivalent to:: - initial_missing = object() + initial_missing = sentinel('initial_missing') def reduce(function, iterable, /, initial=initial_missing): it = iter(iterable) From a60520da3cb0c571a361b9d0b8d998e78f38b836 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 30 Apr 2026 18:25:32 +0200 Subject: [PATCH 716/775] gh-147991: Speed up tomllib import time (GH-147992) - Use lazy import for regular expressions. - Use frozendict for string escapes Co-authored-by: Taneli Hukkinen Co-authored-by: Petr Viktorin --- Lib/test/test_tomllib/test_misc.py | 19 +++++++++++++++++++ Lib/tomllib/_parser.py | 11 +++++++++-- ...-04-02-05-06-34.gh-issue-147991.2ANtR5.rst | 2 ++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-02-05-06-34.gh-issue-147991.2ANtR5.rst diff --git a/Lib/test/test_tomllib/test_misc.py b/Lib/test/test_tomllib/test_misc.py index 118fde24d88..abd0842d10b 100644 --- a/Lib/test/test_tomllib/test_misc.py +++ b/Lib/test/test_tomllib/test_misc.py @@ -9,8 +9,10 @@ from pathlib import Path import sys import tempfile +import textwrap import unittest from test import support +from test.support.script_helper import assert_python_ok from . import tomllib @@ -124,3 +126,20 @@ def test_types_import(self): never imported by tests. """ importlib.import_module(f"{tomllib.__name__}._types") + + def test_lazy_import(self): + # Test the TOML file can be parsed without importing regular + # expressions (tomllib._re) + code = textwrap.dedent(""" + import sys, tomllib, textwrap + document = textwrap.dedent(''' + [metadata] + key = "text" + array = ["array", "of", "text"] + booleans = [true, false] + ''') + tomllib.loads(document) + print("lazy import?", 'tomllib._re' not in sys.modules) + """) + proc = assert_python_ok("-c", code) + self.assertIn(b"lazy import? True", proc.out) diff --git a/Lib/tomllib/_parser.py b/Lib/tomllib/_parser.py index b59d0f7d54b..8aa01301dce 100644 --- a/Lib/tomllib/_parser.py +++ b/Lib/tomllib/_parser.py @@ -4,7 +4,11 @@ from __future__ import annotations -from types import MappingProxyType +# Defer loading regular expressions until we actually need them in +# parse_value(). +__lazy_modules__ = ["tomllib._re"] + +import sys from ._re import ( RE_DATETIME, @@ -15,6 +19,9 @@ match_to_number, ) +if sys.version_info < (3, 15): + from types import MappingProxyType as frozendict + TYPE_CHECKING = False if TYPE_CHECKING: from collections.abc import Iterable @@ -42,7 +49,7 @@ KEY_INITIAL_CHARS: Final = BARE_KEY_CHARS | frozenset("\"'") HEXDIGIT_CHARS: Final = frozenset("abcdef" "ABCDEF" "0123456789") -BASIC_STR_ESCAPE_REPLACEMENTS: Final = MappingProxyType( +BASIC_STR_ESCAPE_REPLACEMENTS: Final = frozendict( { "\\b": "\u0008", # backspace "\\t": "\u0009", # tab diff --git a/Misc/NEWS.d/next/Library/2026-04-02-05-06-34.gh-issue-147991.2ANtR5.rst b/Misc/NEWS.d/next/Library/2026-04-02-05-06-34.gh-issue-147991.2ANtR5.rst new file mode 100644 index 00000000000..581c52926c3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-02-05-06-34.gh-issue-147991.2ANtR5.rst @@ -0,0 +1,2 @@ +Improve :mod:`tomllib` import time (up to 10x faster). Patch by Victor +Stinner. From b413bc7a1f0946f734d9660239b4e2e8ddc48522 Mon Sep 17 00:00:00 2001 From: elenril Date: Thu, 30 Apr 2026 18:24:23 +0100 Subject: [PATCH 717/775] bpo-39100: _header_value_parser: do not treat a Group as invalid-mailbox (#24872) When an address in an address-list has garbage at the end, the code will currently: 1. change the mailbox in the last parsed address into invalid-mailbox by overriding its token_type; 2. wrap the trailing garbage into another invalid-mailbox and append it to the last parsed address. However, that does not take into account that an address may also contain a Group instead of a single mailbox. In that case, overwriting token_type leads to undesirable results, e.g. parsing an email with the following 'To' header: unlisted-recipients:; (no To-header on input) raises an AttributeError from trying to treat the Group as a Mailbox. Moreover it is questionable whether the previously parsed mailbox should be treated as invalid in addition to the trailing garbage. Address both of the above by wrapping the trailing garbage in a new Address with a single invalid-mailbox, and append it to the AddressList directly. Changes the results of the test_get_address_list_mailboxes_invalid_addresses test, where the address list is now parsed into 4 mailboxes instead of 3 (all but the first one are invalid). --- Lib/email/_header_value_parser.py | 8 +++----- Lib/test/test_email/test__header_value_parser.py | 16 +++++++++++++--- ...2023-09-08-13-10-32.gh-issue-83281.2Plpcj.rst | 2 ++ 3 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-09-08-13-10-32.gh-issue-83281.2Plpcj.rst diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 4c5394ab635..f6b45e13271 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2063,12 +2063,10 @@ def get_address_list(value): address_list.defects.append(errors.InvalidHeaderDefect( "invalid address in address-list")) if value and value[0] != ',': - # Crap after address; treat it as an invalid mailbox. - # The mailbox info will still be available. - mailbox = address_list[-1][0] - mailbox.token_type = 'invalid-mailbox' + # Crap after address: add it to the address list + # as an invalid mailbox token, value = get_invalid_mailbox(value, ',') - mailbox.extend(token) + address_list.append(Address([token])) address_list.defects.append(errors.InvalidHeaderDefect( "invalid address in address-list")) if value: # Must be a , at this point. diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index e28fe389201..f3c03062572 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2617,7 +2617,7 @@ def test_get_address_list_mailboxes_invalid_addresses(self): '') self.assertEqual(address_list.token_type, 'address-list') self.assertEqual(len(address_list.mailboxes), 1) - self.assertEqual(len(address_list.all_mailboxes), 3) + self.assertEqual(len(address_list.all_mailboxes), 4) self.assertEqual([str(x) for x in address_list.all_mailboxes], [str(x) for x in address_list.addresses]) self.assertEqual(address_list.mailboxes[0].domain, 'example.com') @@ -2626,11 +2626,13 @@ def test_get_address_list_mailboxes_invalid_addresses(self): self.assertEqual(address_list.addresses[1].token_type, 'address') self.assertEqual(len(address_list.addresses[0].mailboxes), 1) self.assertEqual(len(address_list.addresses[1].mailboxes), 0) - self.assertEqual(len(address_list.addresses[1].mailboxes), 0) + self.assertEqual(len(address_list.addresses[2].mailboxes), 0) + self.assertEqual(len(address_list.addresses[3].mailboxes), 0) self.assertEqual( address_list.addresses[1].all_mailboxes[0].local_part, 'Foo x') + self.assertEqual(address_list.addresses[2].all_mailboxes[0].value, '[]') self.assertEqual( - address_list.addresses[2].all_mailboxes[0].display_name, + address_list.addresses[3].all_mailboxes[0].display_name, "Nobody Is. Special") def test_get_address_list_group_empty(self): @@ -2695,6 +2697,14 @@ def test_get_address_list_group_and_mailboxes(self): self.assertEqual(str(address_list.addresses[1]), str(address_list.mailboxes[2])) + def test_get_address_list_trailing_garbage(self): + address_list = self._test_get_x(parser.get_address_list, + 'unlisted-recipients:; (no To-header on input)', + 'unlisted-recipients:; (no To-header on input)', + 'unlisted-recipients:; ', + [errors.InvalidHeaderDefect]*2 + [errors.ObsoleteHeaderDefect], + '') + def test_invalid_content_disposition(self): content_disp = self._test_parse_x( parser.parse_content_disposition_header, diff --git a/Misc/NEWS.d/next/Library/2023-09-08-13-10-32.gh-issue-83281.2Plpcj.rst b/Misc/NEWS.d/next/Library/2023-09-08-13-10-32.gh-issue-83281.2Plpcj.rst new file mode 100644 index 00000000000..cf2ae770bd1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-09-08-13-10-32.gh-issue-83281.2Plpcj.rst @@ -0,0 +1,2 @@ +:mod:`email`: improve handling trailing garbage in address lists to avoid throwing +AttributeError in certain edge cases From 1575a81bf200f8eda5eaa6af6520361240201d82 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Fri, 1 May 2026 00:19:13 +0500 Subject: [PATCH 718/775] GH-148726: Forward-port generational GC. (GH-148746) The replaces the incremental GC with a forward port (from 3.13) of the generational GC. Co-Authored-By: Neil Schemenauer Co-Authored-By: Zanie Blue Co-Authored-By: Sergey Miryanov Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Doc/library/gc.rst | 53 +- Include/internal/pycore_gc.h | 43 +- Include/internal/pycore_interp_structs.h | 49 +- Include/internal/pycore_runtime_init.h | 8 +- InternalDocs/garbage_collector.md | 191 +-- Lib/test/_test_gc_fast_cycles.py | 48 - Lib/test/test_gc.py | 75 +- ...4-17-11-30-00.gh-issue-142516.GcGen315.rst | 1 + Modules/_testinternalcapi.c | 3 +- Modules/gcmodule.c | 30 +- Python/gc.c | 1200 ++++++----------- 11 files changed, 576 insertions(+), 1125 deletions(-) delete mode 100644 Lib/test/_test_gc_fast_cycles.py create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-11-30-00.gh-issue-142516.GcGen315.rst diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst index 652475886fc..701af579453 100644 --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -37,18 +37,11 @@ The :mod:`!gc` module provides the following functions: .. function:: collect(generation=2) - Perform a collection. The optional argument *generation* + With no arguments, run a full collection. The optional argument *generation* may be an integer specifying which generation to collect (from 0 to 2). A :exc:`ValueError` is raised if the generation number is invalid. The sum of collected objects and uncollectable objects is returned. - Calling ``gc.collect(0)`` will perform a GC collection on the young generation. - - Calling ``gc.collect(1)`` will perform a GC collection on the young generation - and an increment of the old generation. - - Calling ``gc.collect(2)`` or ``gc.collect()`` performs a full collection - The free lists maintained for a number of built-in types are cleared whenever a full collection or collection of the highest generation (2) is run. Not all items in some free lists may be freed due to the @@ -60,6 +53,9 @@ The :mod:`!gc` module provides the following functions: .. versionchanged:: 3.14 ``generation=1`` performs an increment of collection. + .. versionchanged:: 3.14.5 + ``generation=1`` performs collection of the middle generation. + .. function:: set_debug(flags) @@ -75,13 +71,9 @@ The :mod:`!gc` module provides the following functions: .. function:: get_objects(generation=None) - Returns a list of all objects tracked by the collector, excluding the list - returned. If *generation* is not ``None``, return only the objects as follows: - - * 0: All objects in the young generation - * 1: No objects, as there is no generation 1 (as of Python 3.14) - * 2: All objects in the old generation + returned. If *generation* is not ``None``, return only the objects tracked by + the collector that are in that generation. .. versionchanged:: 3.8 New *generation* parameter. @@ -89,6 +81,9 @@ The :mod:`!gc` module provides the following functions: .. versionchanged:: 3.14 Generation 1 is removed + .. versionchanged:: 3.14.5 + Generation 1 is reintroduced to maintain GC behavior from 3.13. + .. audit-event:: gc.get_objects generation gc.get_objects .. function:: get_stats() @@ -124,33 +119,33 @@ The :mod:`!gc` module provides the following functions: Set the garbage collection thresholds (the collection frequency). Setting *threshold0* to zero disables collection. - The GC classifies objects into two generations depending on whether they have - survived a collection. New objects are placed in the young generation. If an - object survives a collection it is moved into the old generation. - - In order to decide when to run, the collector keeps track of the number of object + The GC classifies objects into three generations depending on how many + collection sweeps they have survived. New objects are placed in the youngest + generation (generation ``0``). If an object survives a collection it is moved + into the next older generation. Since generation ``2`` is the oldest + generation, objects in that generation remain there after a collection. In + order to decide when to run, the collector keeps track of the number object allocations and deallocations since the last collection. When the number of allocations minus the number of deallocations exceeds *threshold0*, collection - starts. For each collection, all the objects in the young generation and some - fraction of the old generation is collected. + starts. Initially only generation ``0`` is examined. If generation ``0`` has + been examined more than *threshold1* times since generation ``1`` has been + examined, then generation ``1`` is examined as well. + With the third generation, things are a bit more complicated, + see `Collecting the oldest generation `_ for more information. In the free-threaded build, the increase in process memory usage is also checked before running the collector. If the memory usage has not increased by 10% since the last collection and the net number of object allocations has not exceeded 40 times *threshold0*, the collection is not run. - The fraction of the old generation that is collected is **inversely** proportional - to *threshold1*. The larger *threshold1* is, the slower objects in the old generation - are collected. - For the default value of 10, 1% of the old generation is scanned during each collection. - - *threshold2* is ignored. - - See `Garbage collector design `_ for more information. + See `Garbage collector design `_ for more information. .. versionchanged:: 3.14 *threshold2* is ignored + .. versionchanged:: 3.14.5 + *threshold2* is restored to match Python 3.13 behavior. + .. function:: get_count() diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index fd284d0e4ec..e105677cd2e 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -118,21 +118,6 @@ static inline void _PyObject_GC_SET_SHARED(PyObject *op) { /* Bit 1 is set when the object is in generation which is GCed currently. */ #define _PyGC_PREV_MASK_COLLECTING ((uintptr_t)2) -/* Bit 0 in _gc_next is the old space bit. - * It is set as follows: - * Young: gcstate->visited_space - * old[0]: 0 - * old[1]: 1 - * permanent: 0 - * - * During a collection all objects handled should have the bit set to - * gcstate->visited_space, as objects are moved from the young gen - * and the increment into old[gcstate->visited_space]. - * When object are moved from the pending space, old[gcstate->visited_space^1] - * into the increment, the old space bit is flipped. -*/ -#define _PyGC_NEXT_MASK_OLD_SPACE_1 1 - #define _PyGC_PREV_SHIFT 2 #define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT) @@ -159,13 +144,11 @@ typedef enum { // Lowest bit of _gc_next is used for flags only in GC. // But it is always 0 for normal code. static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) { - uintptr_t next = gc->_gc_next & _PyGC_PREV_MASK; + uintptr_t next = gc->_gc_next; return (PyGC_Head*)next; } static inline void _PyGCHead_SET_NEXT(PyGC_Head *gc, PyGC_Head *next) { - uintptr_t unext = (uintptr_t)next; - assert((unext & ~_PyGC_PREV_MASK) == 0); - gc->_gc_next = (gc->_gc_next & ~_PyGC_PREV_MASK) | unext; + gc->_gc_next = (uintptr_t)next; } // Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags. @@ -207,10 +190,6 @@ static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) { extern void _Py_ScheduleGC(PyThreadState *tstate); -#ifndef Py_GIL_DISABLED -extern void _Py_TriggerGC(struct _gc_runtime_state *gcstate); -#endif - /* Tell the GC to track this object. * @@ -220,7 +199,7 @@ extern void _Py_TriggerGC(struct _gc_runtime_state *gcstate); * ob_traverse method. * * Internal note: interp->gc.generation0->_gc_prev doesn't have any bit flags - * because it's not object header. So we don't use _PyGCHead_PREV() and + * because it's not an object header. So we don't use _PyGCHead_PREV() and * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations. * * See also the public PyObject_GC_Track() function. @@ -244,19 +223,12 @@ static inline void _PyObject_GC_TRACK( "object is in generation which is garbage collected", filename, lineno, __func__); - struct _gc_runtime_state *gcstate = &_PyInterpreterState_GET()->gc; - PyGC_Head *generation0 = &gcstate->young.head; + PyGC_Head *generation0 = _PyInterpreterState_GET()->gc.generation0; PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev); _PyGCHead_SET_NEXT(last, gc); _PyGCHead_SET_PREV(gc, last); - uintptr_t not_visited = 1 ^ gcstate->visited_space; - gc->_gc_next = ((uintptr_t)generation0) | not_visited; + _PyGCHead_SET_NEXT(gc, generation0); generation0->_gc_prev = (uintptr_t)gc; - gcstate->young.count++; /* number of tracked GC objects */ - gcstate->heap_size++; - if (gcstate->young.count > gcstate->young.threshold) { - _Py_TriggerGC(gcstate); - } #endif } @@ -291,11 +263,6 @@ static inline void _PyObject_GC_UNTRACK( _PyGCHead_SET_PREV(next, prev); gc->_gc_next = 0; gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED; - struct _gc_runtime_state *gcstate = &_PyInterpreterState_GET()->gc; - if (gcstate->young.count > 0) { - gcstate->young.count--; - } - gcstate->heap_size--; #endif } diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index fb810c82a5a..349044116b9 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -181,29 +181,14 @@ struct gc_generation { struct gc_generation_stats { PyTime_t ts_start; PyTime_t ts_stop; - - /* heap_size on the start of the collection */ - Py_ssize_t heap_size; - - /* work_to_do on the start of the collection */ - Py_ssize_t work_to_do; - /* total number of collections */ Py_ssize_t collections; - - /* total number of visited objects */ - Py_ssize_t object_visits; - /* total number of collected objects */ Py_ssize_t collected; /* total number of uncollectable objects (put into gc.garbage) */ Py_ssize_t uncollectable; // Total number of objects considered for collection and traversed: Py_ssize_t candidates; - - Py_ssize_t objects_transitively_reachable; - Py_ssize_t objects_not_transitively_reachable; - // Total duration of the collection in seconds: double duration; }; @@ -225,11 +210,6 @@ struct gc_old_stats_buffer { int8_t index; }; -enum _GCPhase { - GC_PHASE_MARK = 0, - GC_PHASE_COLLECT = 1 -}; - /* If we change this, we need to change the default value in the signature of gc.collect and change the size of PyStats.gc_stats */ #define NUM_GENERATIONS 3 @@ -244,8 +224,13 @@ struct _gc_runtime_state { int enabled; int debug; /* linked lists of container objects */ +#ifndef Py_GIL_DISABLED + struct gc_generation generations[NUM_GENERATIONS]; + PyGC_Head *generation0; +#else struct gc_generation young; struct gc_generation old[2]; +#endif /* a permanent generation which won't be collected */ struct gc_generation permanent_generation; struct gc_stats *generation_stats; @@ -259,13 +244,6 @@ struct _gc_runtime_state { /* a list of callbacks to be invoked when collection is performed */ PyObject *callbacks; - Py_ssize_t heap_size; - Py_ssize_t work_to_do; - /* Which of the old spaces is the visited space */ - int visited_space; - int phase; - -#ifdef Py_GIL_DISABLED /* This is the number of objects that survived the last full collection. It approximates the number of long lived objects tracked by the GC. @@ -278,6 +256,7 @@ struct _gc_runtime_state { the first time. */ Py_ssize_t long_lived_pending; +#ifdef Py_GIL_DISABLED /* True if gc.freeze() has been used. */ int freeze_active; @@ -293,6 +272,22 @@ struct _gc_runtime_state { #endif }; +#ifndef Py_GIL_DISABLED +#define GC_GENERATION_INIT \ + .generations = { \ + { .threshold = 2000, }, \ + { .threshold = 10, }, \ + { .threshold = 10, }, \ + }, +#else +#define GC_GENERATION_INIT \ + .young = { .threshold = 2000, }, \ + .old = { \ + { .threshold = 10, }, \ + { .threshold = 10, }, \ + }, +#endif + #include "pycore_gil.h" // struct _gil_runtime_state /**** Import ********/ diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index e8d1098c207..6c48ac0dccf 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -130,13 +130,7 @@ extern PyTypeObject _PyExc_MemoryError; }, \ .gc = { \ .enabled = 1, \ - .young = { .threshold = 2000, }, \ - .old = { \ - { .threshold = 10, }, \ - { .threshold = 0, }, \ - }, \ - .work_to_do = -5000, \ - .phase = GC_PHASE_MARK, \ + GC_GENERATION_INIT \ }, \ .qsbr = { \ .wr_seq = QSBR_INITIAL, \ diff --git a/InternalDocs/garbage_collector.md b/InternalDocs/garbage_collector.md index 94e6fb05b68..0ef45ff8e02 100644 --- a/InternalDocs/garbage_collector.md +++ b/InternalDocs/garbage_collector.md @@ -107,7 +107,7 @@ [Optimization: reusing fields to save memory](#optimization-reusing-fields-to-save-memory) section, these two extra fields are normally used to keep doubly linked lists of all the objects tracked by the garbage collector (these lists are the GC generations, more on -that in the [Optimization: incremental collection](#Optimization-incremental-collection) section), but +that in the [Optimization: generations](#Optimization-generations) section), but they are also reused to fulfill other purposes when the full doubly linked list structure is not needed as a memory optimization. @@ -203,22 +203,22 @@ ```pycon >>> import gc ->>> +>>> >>> class Link: ... def __init__(self, next_link=None): ... self.next_link = next_link -... +... >>> link_3 = Link() >>> link_2 = Link(link_3) >>> link_1 = Link(link_2) >>> link_3.next_link = link_1 >>> A = link_1 >>> del link_1, link_2, link_3 ->>> +>>> >>> link_4 = Link() >>> link_4.next_link = link_4 >>> del link_4 ->>> +>>> >>> # Collect the unreachable Link object (and its .__dict__ dict). >>> gc.collect() 2 @@ -360,11 +360,12 @@ the reference counts fall to 0, triggering the destruction of all unreachable objects. -Optimization: incremental collection -==================================== +Optimization: generations +========================= -In order to bound the length of each garbage collection pause, the GC implementation -for the default build uses incremental collection with two generations. +In order to limit the time each garbage collection takes, the GC +implementation for the default build uses a popular optimization: +generations. Generational garbage collection takes advantage of what is known as the weak generational hypothesis: Most objects die young. @@ -372,76 +373,29 @@ programs as many temporary objects are created and destroyed very quickly. To take advantage of this fact, all container objects are segregated into -two generations: young and old. Every new object starts in the young generation. -Each garbage collection scans the entire young generation and part of the old generation. - -The time taken to scan the young generation can be controlled by controlling its -size, but the size of the old generation cannot be controlled. -In order to keep pause times down, scanning of the old generation of the heap -occurs in increments. - -To keep track of what has been scanned, the old generation contains two lists: - -* Those objects that have not yet been scanned, referred to as the `pending` list. -* Those objects that have been scanned, referred to as the `visited` list. - -To detect and collect all unreachable objects in the heap, the garbage collector -must scan the whole heap. This whole heap scan is called a full scavenge. - -Increments ----------- - -Each full scavenge is performed in a series of increments. -For each full scavenge, the combined increments will cover the whole heap. - -Each increment is made up of: - -* The young generation -* The old generation's least recently scanned objects -* All objects reachable from those objects that have not yet been scanned this full scavenge - -The surviving objects (those that are not collected) are moved to the back of the -`visited` list in the old generation. - -When a full scavenge starts, no objects in the heap are considered to have been scanned, -so all objects in the old generation must be in the `pending` space. -When all objects in the heap have been scanned a cycle ends, and all objects are moved -to the `pending` list again. To avoid having to traverse the entire list, which list is -`pending` and which is `visited` is determined by a field in the `GCState` struct. -The `visited` and `pending` lists can be swapped by toggling this bit. - -Correctness ------------ - -The [algorithm for identifying cycles](#Identifying-reference-cycles) will find all -unreachable cycles in a list of objects, but will not find any cycles that are -even partly outside of that list. -Therefore, to be guaranteed that a full scavenge will find all unreachable cycles, -each cycle must be fully contained within a single increment. - -To make sure that no partial cycles are included in the increment we perform a -[transitive closure](https://en.wikipedia.org/wiki/Transitive_closure) -over reachable, unscanned objects from the initial increment. -Since the transitive closure of objects reachable from an object must be a (non-strict) -superset of any unreachable cycle including that object, we are guaranteed that a -transitive closure cannot contain any partial cycles. -We can exclude scanned objects, as they must have been reachable when scanned. -If a scanned object becomes part of an unreachable cycle after being scanned, it will -not be collected at this time, but it will be collected in the next full scavenge. +three spaces/generations. Every new +object starts in the first generation (generation 0). The previous algorithm is +executed only over the objects of a particular generation and if an object +survives a collection of its generation it will be moved to the next one +(generation 1), where it will be surveyed for collection less often. If +the same object survives another GC round in this new generation (generation 1) +it will be moved to the last generation (generation 2) where it will be +surveyed the least often. > [!NOTE] -> The GC implementation for the free-threaded build does not use incremental collection. -> Every collection operates on the entire heap. +> The GC implementation for the free-threaded build does not use generational +> collection. Every collection operates on the entire heap. + In order to decide when to run, the collector keeps track of the number of object allocations and deallocations since the last collection. When the number of allocations minus the number of deallocations exceeds `threshold0`, -collection starts. `threshold1` determines the fraction of the old -collection that is included in the increment. -The fraction is inversely proportional to `threshold1`, -as historically a larger `threshold1` meant that old generation -collections were performed less frequently. -`threshold2` is ignored. +collection starts. Initially only generation 0 is examined. If generation 0 has +been examined more than `threshold_1` times since generation 1 has been +examined, then generation 1 is examined as well. With generation 2, +things are a bit more complicated; see +[Collecting the oldest generation](#Collecting-the-oldest-generation) for +more information. These thresholds can be examined using the [`gc.get_threshold()`](https://docs.python.org/3/library/gc.html#gc.get_threshold) @@ -450,7 +404,7 @@ ```pycon >>> import gc >>> gc.get_threshold() -(700, 10, 10) +(2000, 10, 10) ``` The content of these generations can be examined using the @@ -463,84 +417,61 @@ ... pass ... >>> # Move everything to the old generation so it's easier to inspect ->>> # the young generation. +>>> # the younger generation. >>> gc.collect() 0 >>> # Create a reference cycle. >>> x = MyObj() >>> x.self = x ->>> ->>> # Initially the object is in the young generation. +>>> +>>> # Initially the object is in the youngest generation. >>> gc.get_objects(generation=0) [..., <__main__.MyObj object at 0x7fbcc12a3400>, ...] ->>> +>>> >>> # After a collection of the youngest generation the object ->>> # moves to the old generation. +>>> # moves to the next generation. >>> gc.collect(generation=0) 0 >>> gc.get_objects(generation=0) [] >>> gc.get_objects(generation=1) -[] ->>> gc.get_objects(generation=2) [..., <__main__.MyObj object at 0x7fbcc12a3400>, ...] ``` +Collecting the oldest generation +-------------------------------- + +In addition to the various configurable thresholds, the GC only triggers a full +collection of the oldest generation if the ratio `long_lived_pending / long_lived_total` +is above a given value (hardwired to 25%). The reason is that, while "non-full" +collections (that is, collections of the young and middle generations) will always +examine roughly the same number of objects (determined by the aforementioned +thresholds) the cost of a full collection is proportional to the total +number of long-lived objects, which is virtually unbounded. Indeed, it has +been remarked that doing a full collection every of object +creations entails a dramatic performance degradation in workloads which consist +of creating and storing lots of long-lived objects (for example, building a large list +of GC-tracked objects would show quadratic performance, instead of linear as +expected). Using the above ratio, instead, yields amortized linear performance +in the total number of objects (the effect of which can be summarized thusly: +"each full garbage collection is more and more costly as the number of objects +grows, but we do fewer and fewer of them"). + Optimization: excluding reachable objects ========================================= An object cannot be garbage if it can be reached. To avoid having to identify -reference cycles across the whole heap, we can reduce the amount of work done -considerably by first identifying objects reachable from objects known to be -alive. These objects are excluded from the normal cyclic detection process. - -The default and free-threaded build both implement this optimization but in -slightly different ways. - -Finding reachable objects for the default build GC --------------------------------------------------- - -This works by first moving most reachable objects to the `visited` space. -Empirically, most reachable objects can be reached from a small set of global -objects and local variables. This step does much less work per object, so -reduces the time spent performing garbage collection by at least half. - -> [!NOTE] -> Objects that are not determined to be reachable by this pass are not necessarily -> unreachable. We still need to perform the main algorithm to determine which objects -> are actually unreachable. -We use the same technique of forming a transitive closure as the incremental -collector does to find reachable objects, seeding the list with some global -objects and the currently executing frames. - -This phase moves objects to the `visited` space, as follows: - -1. All objects directly referred to by any builtin class, the `sys` module, the `builtins` -module and all objects directly referred to from stack frames are added to a working -set of reachable objects. -2. Until this working set is empty: - 1. Pop an object from the set and move it to the `visited` space - 2. For each object directly reachable from that object: - * If it is not already in `visited` space and it is a GC object, - add it to the working set - - -Before each increment of collection is performed, the stacks are scanned -to check for any new stack frames that have been created since the last -increment. All objects directly referred to from those stack frames are -added to the working set. -Then the above algorithm is repeated, starting from step 2. - +reference cycles across the whole heap, the free-threaded build first identifies +objects reachable from objects known to be alive. These objects are excluded +from the normal cyclic detection process. Finding reachable objects for the free-threaded GC -------------------------------------------------- Within the `gc_free_threading.c` implementation, this is known as the "mark -alive" pass or phase. It is similar in concept to what is done for the default -build GC. Rather than moving objects between double-linked lists, the -free-threaded GC uses a flag in `ob_gc_bits` to track if an object is -found to be definitely alive (not garbage). +alive" pass or phase. The free-threaded GC uses a flag in `ob_gc_bits` to track +if an object is found to be definitely alive (not garbage). To find objects reachable from known alive objects, known as the "roots", the `gc_mark_alive_from_roots()` function is used. Root objects include @@ -771,6 +702,14 @@ already not tracked. Tuples are examined for untracking in all garbage collection cycles. +Dictionaries are always tracked from creation and are not untracked by the +garbage collector. Earlier versions (up to 3.13) used lazy tracking: empty or +atomic-only dicts were untracked on creation and re-tracked when a trackable +value was inserted (via `MAINTAIN_TRACKING`), and full collections called +`_PyDict_MaybeUntrack` to prune dicts whose values had become atomic. That +machinery was removed in 3.14 (GH-127010) because the per-set-item cost of +checking the tracking invariant outweighed the savings on full collections. + The garbage collector module provides the Python function `is_tracked(obj)`, which returns the current tracking status of the object. Subsequent garbage collections may change the tracking status of the object. diff --git a/Lib/test/_test_gc_fast_cycles.py b/Lib/test/_test_gc_fast_cycles.py deleted file mode 100644 index 4e2c7d72a02..00000000000 --- a/Lib/test/_test_gc_fast_cycles.py +++ /dev/null @@ -1,48 +0,0 @@ -# Run by test_gc. -from test import support -import _testinternalcapi -import gc -import unittest - -class IncrementalGCTests(unittest.TestCase): - - # Use small increments to emulate longer running process in a shorter time - @support.gc_threshold(200, 10) - def test_incremental_gc_handles_fast_cycle_creation(self): - - class LinkedList: - - #Use slots to reduce number of implicit objects - __slots__ = "next", "prev", "surprise" - - def __init__(self, next=None, prev=None): - self.next = next - if next is not None: - next.prev = self - self.prev = prev - if prev is not None: - prev.next = self - - def make_ll(depth): - head = LinkedList() - for i in range(depth): - head = LinkedList(head, head.prev) - return head - - head = make_ll(1000) - - assert(gc.isenabled()) - olds = [] - initial_heap_size = _testinternalcapi.get_tracked_heap_size() - for i in range(20_000): - newhead = make_ll(20) - newhead.surprise = head - olds.append(newhead) - if len(olds) == 20: - new_objects = _testinternalcapi.get_tracked_heap_size() - initial_heap_size - self.assertLess(new_objects, 27_000, f"Heap growing. Reached limit after {i} iterations") - del olds[:] - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 6aa6361d5d0..88d265cbc21 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -7,7 +7,7 @@ Py_GIL_DISABLED) from test.support.import_helper import import_module from test.support.os_helper import temp_dir, TESTFN, unlink -from test.support.script_helper import assert_python_ok, make_script, run_test_script +from test.support.script_helper import assert_python_ok, make_script from test.support import threading_helper, gc_threshold import gc @@ -419,11 +419,19 @@ def test_collect_generations(self): # each call to collect(N) x = [] gc.collect(0) - # x is now in the old gen + # x is now in gen 1 a, b, c = gc.get_count() - # We don't check a since its exact values depends on + gc.collect(1) + # x is now in gen 2 + d, e, f = gc.get_count() + gc.collect(2) + # x is now in gen 3 + g, h, i = gc.get_count() + # We don't check a, d, g since their exact values depends on # internal implementation details of the interpreter. self.assertEqual((b, c), (1, 0)) + self.assertEqual((e, f), (0, 1)) + self.assertEqual((h, i), (0, 0)) def test_trashcan(self): class Ouch: @@ -907,10 +915,42 @@ def test_get_objects_generations(self): self.assertTrue( any(l is element for element in gc.get_objects(generation=0)) ) - gc.collect() + self.assertFalse( + any(l is element for element in gc.get_objects(generation=1)) + ) + self.assertFalse( + any(l is element for element in gc.get_objects(generation=2)) + ) + gc.collect(generation=0) self.assertFalse( any(l is element for element in gc.get_objects(generation=0)) ) + self.assertTrue( + any(l is element for element in gc.get_objects(generation=1)) + ) + self.assertFalse( + any(l is element for element in gc.get_objects(generation=2)) + ) + gc.collect(generation=1) + self.assertFalse( + any(l is element for element in gc.get_objects(generation=0)) + ) + self.assertFalse( + any(l is element for element in gc.get_objects(generation=1)) + ) + self.assertTrue( + any(l is element for element in gc.get_objects(generation=2)) + ) + gc.collect(generation=2) + self.assertFalse( + any(l is element for element in gc.get_objects(generation=0)) + ) + self.assertFalse( + any(l is element for element in gc.get_objects(generation=1)) + ) + self.assertTrue( + any(l is element for element in gc.get_objects(generation=2)) + ) del l gc.collect() @@ -1249,17 +1289,6 @@ def test_tuple_untrack_counts(self): self.assertTrue(new_count - count > (n // 2)) -class IncrementalGCTests(unittest.TestCase): - @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") - @requires_gil_enabled("Free threading does not support incremental GC") - def test_incremental_gc_handles_fast_cycle_creation(self): - # Run this test in a fresh process. The number of alive objects (which can - # be from unit tests run before this one) can influence how quickly cyclic - # garbage is found. - script = support.findfile("_test_gc_fast_cycles.py") - run_test_script(script) - - class GCCallbackTests(unittest.TestCase): def setUp(self): # Save gc state and disable it. @@ -1514,8 +1543,8 @@ def callback(ignored): assert not detector.gc_happened while not detector.gc_happened: i += 1 - if i > 100000: - self.fail("gc didn't happen after 100000 iterations") + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") self.assertEqual(len(ouch), 0) junk.append([]) # this will eventually trigger gc @@ -1587,8 +1616,8 @@ def __del__(self): gc.collect() while not detector.gc_happened: i += 1 - if i > 50000: - self.fail("gc didn't happen after 50000 iterations") + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") self.assertEqual(len(ouch), 0) junk.append([]) # this will eventually trigger gc @@ -1605,8 +1634,8 @@ def test_indirect_calls_with_gc_disabled(self): detector = GC_Detector() while not detector.gc_happened: i += 1 - if i > 100000: - self.fail("gc didn't happen after 100000 iterations") + if i > 10000: + self.fail("gc didn't happen after 10000 iterations") junk.append([]) # this will eventually trigger gc try: @@ -1616,11 +1645,11 @@ def test_indirect_calls_with_gc_disabled(self): detector = GC_Detector() while not detector.gc_happened: i += 1 - if i > 100000: + if i > 10000: break junk.append([]) # this may eventually trigger gc (if it is enabled) - self.assertEqual(i, 100001) + self.assertEqual(i, 10001) finally: gc.enable() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-11-30-00.gh-issue-142516.GcGen315.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-11-30-00.gh-issue-142516.GcGen315.rst new file mode 100644 index 00000000000..5abb2485c20 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-17-11-30-00.gh-issue-142516.GcGen315.rst @@ -0,0 +1 @@ +Forward-port the generational cycle garbage collector to the default 3.15 build, replacing the incremental collector while leaving the free-threaded collector unchanged. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 619f9f50574..5319d9c7a48 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -2725,7 +2725,8 @@ has_deferred_refcount(PyObject *self, PyObject *op) static PyObject * get_tracked_heap_size(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return PyLong_FromInt64(PyInterpreterState_Get()->gc.heap_size); + // Generational GC doesn't track heap_size, return -1. + return PyLong_FromInt64(-1); } static PyObject * diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 8da28130e9d..18bddf46a74 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -158,6 +158,15 @@ gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, { GCState *gcstate = get_gc_state(); +#ifndef Py_GIL_DISABLED + gcstate->generations[0].threshold = threshold0; + if (group_right_1) { + gcstate->generations[1].threshold = threshold1; + } + if (group_right_2) { + gcstate->generations[2].threshold = threshold2; + } +#else gcstate->young.threshold = threshold0; if (group_right_1) { gcstate->old[0].threshold = threshold1; @@ -165,6 +174,7 @@ gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, if (group_right_2) { gcstate->old[1].threshold = threshold2; } +#endif Py_RETURN_NONE; } @@ -179,10 +189,17 @@ gc_get_threshold_impl(PyObject *module) /*[clinic end generated code: output=7902bc9f41ecbbd8 input=286d79918034d6e6]*/ { GCState *gcstate = get_gc_state(); +#ifndef Py_GIL_DISABLED + return Py_BuildValue("(iii)", + gcstate->generations[0].threshold, + gcstate->generations[1].threshold, + gcstate->generations[2].threshold); +#else return Py_BuildValue("(iii)", gcstate->young.threshold, gcstate->old[0].threshold, - 0); + gcstate->old[1].threshold); +#endif } /*[clinic input] @@ -206,10 +223,17 @@ gc_get_count_impl(PyObject *module) gc->alloc_count = 0; #endif +#ifndef Py_GIL_DISABLED + return Py_BuildValue("(iii)", + gcstate->generations[0].count, + gcstate->generations[1].count, + gcstate->generations[2].count); +#else return Py_BuildValue("(iii)", gcstate->young.count, - gcstate->old[gcstate->visited_space].count, - gcstate->old[gcstate->visited_space^1].count); + gcstate->old[0].count, + gcstate->old[1].count); +#endif } /*[clinic input] diff --git a/Python/gc.c b/Python/gc.c index 284ac725d37..59bed10c1fb 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -6,17 +6,18 @@ #include "pycore_ceval.h" // _Py_set_eval_breaker_bit() #include "pycore_dict.h" // _PyInlineValuesSize() #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_context.h" #include "pycore_interp.h" // PyInterpreterState.gc #include "pycore_interpframe.h" // _PyFrame_GetLocalsArray() +#include "pycore_object.h" #include "pycore_object_alloc.h" // _PyObject_MallocWithType() +#include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_tuple.h" // _PyTuple_MaybeUntrack() #include "pycore_weakref.h" // _PyWeakref_ClearRef() - #include "pydtrace.h" - -#ifndef Py_GIL_DISABLED +#if !defined(Py_GIL_DISABLED) typedef struct _gc_runtime_state GCState; @@ -24,10 +25,6 @@ typedef struct _gc_runtime_state GCState; # define GC_DEBUG #endif -// Define this when debugging the GC -// #define GC_EXTRA_DEBUG - - #define GC_NEXT _PyGCHead_NEXT #define GC_PREV _PyGCHead_PREV @@ -50,7 +47,7 @@ typedef struct _gc_runtime_state GCState; // move_legacy_finalizers() removes this flag instead. // Between them, unreachable list is not normal list and we can not use // most gc_list_* functions for it. -#define NEXT_MASK_UNREACHABLE 2 +#define NEXT_MASK_UNREACHABLE (1) #define AS_GC(op) _Py_AS_GC(op) #define FROM_GC(gc) _Py_FROM_GC(gc) @@ -100,48 +97,9 @@ gc_decref(PyGC_Head *g) g->_gc_prev -= 1 << _PyGC_PREV_SHIFT; } -static inline int -gc_old_space(PyGC_Head *g) -{ - return g->_gc_next & _PyGC_NEXT_MASK_OLD_SPACE_1; -} -static inline int -other_space(int space) -{ - assert(space == 0 || space == 1); - return space ^ _PyGC_NEXT_MASK_OLD_SPACE_1; -} +#define GEN_HEAD(gcstate, n) (&(gcstate)->generations[n].head) -static inline void -gc_flip_old_space(PyGC_Head *g) -{ - g->_gc_next ^= _PyGC_NEXT_MASK_OLD_SPACE_1; -} - -static inline void -gc_set_old_space(PyGC_Head *g, int space) -{ - assert(space == 0 || space == _PyGC_NEXT_MASK_OLD_SPACE_1); - g->_gc_next &= ~_PyGC_NEXT_MASK_OLD_SPACE_1; - g->_gc_next |= space; -} - -static PyGC_Head * -GEN_HEAD(GCState *gcstate, int n) -{ - assert((gcstate->visited_space & (~1)) == 0); - switch(n) { - case 0: - return &gcstate->young.head; - case 1: - return &gcstate->old[gcstate->visited_space].head; - case 2: - return &gcstate->old[gcstate->visited_space^1].head; - default: - Py_UNREACHABLE(); - } -} static GCState * get_gc_state(void) @@ -160,12 +118,11 @@ _PyGC_InitState(GCState *gcstate) GEN.head._gc_prev = (uintptr_t)&GEN.head; \ } while (0) - assert(gcstate->young.count == 0); - assert(gcstate->old[0].count == 0); - assert(gcstate->old[1].count == 0); - INIT_HEAD(gcstate->young); - INIT_HEAD(gcstate->old[0]); - INIT_HEAD(gcstate->old[1]); + for (int i = 0; i < NUM_GENERATIONS; i++) { + assert(gcstate->generations[i].count == 0); + INIT_HEAD(gcstate->generations[i]); + }; + gcstate->generation0 = GEN_HEAD(gcstate, 0); INIT_HEAD(gcstate->permanent_generation); #undef INIT_HEAD @@ -191,7 +148,6 @@ _PyGC_Init(PyInterpreterState *interp) if (gcstate->callbacks == NULL) { return _PyStatus_NO_MEMORY(); } - gcstate->heap_size = 0; return _PyStatus_OK(); } @@ -269,7 +225,6 @@ gc_list_is_empty(PyGC_Head *list) static inline void gc_list_append(PyGC_Head *node, PyGC_Head *list) { - assert((list->_gc_prev & ~_PyGC_PREV_MASK) == 0); PyGC_Head *last = (PyGC_Head *)list->_gc_prev; // last <-> node @@ -327,8 +282,6 @@ gc_list_merge(PyGC_Head *from, PyGC_Head *to) PyGC_Head *from_tail = GC_PREV(from); assert(from_head != from); assert(from_tail != from); - assert(gc_list_is_empty(to) || - gc_old_space(to_tail) == gc_old_space(from_tail)); _PyGCHead_SET_NEXT(to_tail, from_head); _PyGCHead_SET_PREV(from_head, to_tail); @@ -397,8 +350,8 @@ enum flagstates {collecting_clear_unreachable_clear, static void validate_list(PyGC_Head *head, enum flagstates flags) { - assert((head->_gc_prev & ~_PyGC_PREV_MASK) == 0); - assert((head->_gc_next & ~_PyGC_PREV_MASK) == 0); + assert((head->_gc_prev & PREV_MASK_COLLECTING) == 0); + assert((head->_gc_next & NEXT_MASK_UNREACHABLE) == 0); uintptr_t prev_value = 0, next_value = 0; switch (flags) { case collecting_clear_unreachable_clear: @@ -420,7 +373,7 @@ validate_list(PyGC_Head *head, enum flagstates flags) PyGC_Head *gc = GC_NEXT(head); while (gc != head) { PyGC_Head *trueprev = GC_PREV(gc); - PyGC_Head *truenext = GC_NEXT(gc); + PyGC_Head *truenext = (PyGC_Head *)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE); assert(truenext != NULL); assert(trueprev == prev); assert((gc->_gc_prev & PREV_MASK_COLLECTING) == prev_value); @@ -430,58 +383,10 @@ validate_list(PyGC_Head *head, enum flagstates flags) } assert(prev == GC_PREV(head)); } - #else #define validate_list(x, y) do{}while(0) #endif -#ifdef GC_EXTRA_DEBUG - - -static void -gc_list_validate_space(PyGC_Head *head, int space) { - PyGC_Head *gc = GC_NEXT(head); - while (gc != head) { - assert(gc_old_space(gc) == space); - gc = GC_NEXT(gc); - } -} - -static void -validate_spaces(GCState *gcstate) -{ - int visited = gcstate->visited_space; - int not_visited = other_space(visited); - gc_list_validate_space(&gcstate->young.head, not_visited); - for (int space = 0; space < 2; space++) { - gc_list_validate_space(&gcstate->old[space].head, space); - } - gc_list_validate_space(&gcstate->permanent_generation.head, visited); -} - -static void -validate_consistent_old_space(PyGC_Head *head) -{ - PyGC_Head *gc = GC_NEXT(head); - if (gc == head) { - return; - } - int old_space = gc_old_space(gc); - while (gc != head) { - PyGC_Head *truenext = GC_NEXT(gc); - assert(truenext != NULL); - assert(gc_old_space(gc) == old_space); - gc = truenext; - } -} - - -#else -#define validate_spaces(g) do{}while(0) -#define validate_consistent_old_space(l) do{}while(0) -#define gc_list_validate_space(l, s) do{}while(0) -#endif - /*** end of list stuff ***/ @@ -501,8 +406,8 @@ update_refs(PyGC_Head *containers) if (_Py_IsImmortal(op)) { assert(!_Py_IsStaticImmortal(op)); _PyObject_GC_UNTRACK(op); - gc = next; - continue; + gc = next; + continue; } gc_reset_refs(gc, Py_REFCNT(op)); /* Python's cyclic gc should never see an incoming refcount @@ -530,19 +435,12 @@ update_refs(PyGC_Head *containers) return candidates; } -struct visit_decref_context { - PyObject *parent; - struct gc_generation_stats *stats; -}; - /* A traversal callback for subtract_refs. */ static int -visit_decref(PyObject *op, void *arg) +visit_decref(PyObject *op, void *parent) { OBJECT_STAT_INC(object_visits); - struct visit_decref_context *ctx = (struct visit_decref_context *)arg; - ctx->stats->object_visits += 1; - _PyObject_ASSERT(ctx->parent, !_PyObject_IsFreed(op)); + _PyObject_ASSERT(_PyObject_CAST(parent), !_PyObject_IsFreed(op)); if (_PyObject_IS_GC(op)) { PyGC_Head *gc = AS_GC(op); @@ -589,35 +487,24 @@ _PyGC_VisitFrameStack(_PyInterpreterFrame *frame, visitproc visit, void *arg) * reachable from outside containers, and so can't be collected. */ static void -subtract_refs(PyGC_Head *containers, struct gc_generation_stats *stats) +subtract_refs(PyGC_Head *containers) { traverseproc traverse; PyGC_Head *gc = GC_NEXT(containers); for (; gc != containers; gc = GC_NEXT(gc)) { PyObject *op = FROM_GC(gc); traverse = Py_TYPE(op)->tp_traverse; - struct visit_decref_context ctx = { - .parent = op, - .stats = stats - }; (void) traverse(op, visit_decref, - &ctx); + op); } } -struct visit_reachable_context { - PyGC_Head *head; - struct gc_generation_stats *stats; -}; - /* A traversal callback for move_unreachable. */ static int visit_reachable(PyObject *op, void *arg) { - struct visit_reachable_context *ctx = (struct visit_reachable_context *)arg; - ctx->stats->object_visits += 1; - PyGC_Head *reachable = ctx->head; + PyGC_Head *reachable = arg; OBJECT_STAT_INC(object_visits); if (!_PyObject_IS_GC(op)) { return 0; @@ -647,13 +534,12 @@ visit_reachable(PyObject *op, void *arg) // Manually unlink gc from unreachable list because the list functions // don't work right in the presence of NEXT_MASK_UNREACHABLE flags. PyGC_Head *prev = GC_PREV(gc); - PyGC_Head *next = GC_NEXT(gc); + PyGC_Head *next = (PyGC_Head*)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE); _PyObject_ASSERT(FROM_GC(prev), prev->_gc_next & NEXT_MASK_UNREACHABLE); _PyObject_ASSERT(FROM_GC(next), next->_gc_next & NEXT_MASK_UNREACHABLE); - prev->_gc_next = gc->_gc_next; // copy flag bits - gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; + prev->_gc_next = gc->_gc_next; // copy NEXT_MASK_UNREACHABLE _PyGCHead_SET_PREV(next, prev); gc_list_append(gc, reachable); @@ -690,7 +576,7 @@ visit_reachable(PyObject *op, void *arg) * So we can not gc_list_* functions for unreachable until we remove the flag. */ static void -move_unreachable(PyGC_Head *young, PyGC_Head *unreachable, struct gc_generation_stats *stats) +move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) { // previous elem in the young list, used for restore gc_prev. PyGC_Head *prev = young; @@ -705,14 +591,6 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable, struct gc_generation_ * or to the right have been scanned yet. */ - struct visit_reachable_context ctx = { - .head = young, - .stats = stats - }; - - validate_consistent_old_space(young); - /* Record which old space we are in, and set NEXT_MASK_UNREACHABLE bit for convenience */ - uintptr_t flags = NEXT_MASK_UNREACHABLE | (gc->_gc_next & _PyGC_NEXT_MASK_OLD_SPACE_1); while (gc != young) { if (gc_get_refs(gc)) { /* gc is definitely reachable from outside the @@ -731,7 +609,7 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable, struct gc_generation_ // young->_gc_prev == gc. Don't do gc = GC_NEXT(gc) before! (void) traverse(op, visit_reachable, - &ctx); + (void *)young); // relink gc_prev to prev element. _PyGCHead_SET_PREV(gc, prev); // gc is not COLLECTING state after here. @@ -758,18 +636,17 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable, struct gc_generation_ // But this may pollute the unreachable list head's 'next' pointer // too. That's semantically senseless but expedient here - the // damage is repaired when this function ends. - last->_gc_next = flags | (uintptr_t)gc; + last->_gc_next = (NEXT_MASK_UNREACHABLE | (uintptr_t)gc); _PyGCHead_SET_PREV(gc, last); - gc->_gc_next = flags | (uintptr_t)unreachable; + gc->_gc_next = (NEXT_MASK_UNREACHABLE | (uintptr_t)unreachable); unreachable->_gc_prev = (uintptr_t)gc; } - gc = _PyGCHead_NEXT(prev); + gc = (PyGC_Head*)prev->_gc_next; } // young->_gc_prev must be last element remained in the list. young->_gc_prev = (uintptr_t)prev; - young->_gc_next &= _PyGC_PREV_MASK; // don't let the pollution of the list head's next pointer leak - unreachable->_gc_next &= _PyGC_PREV_MASK; + unreachable->_gc_next &= ~NEXT_MASK_UNREACHABLE; } /* In theory, all tuples should be younger than the @@ -825,8 +702,8 @@ move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) PyObject *op = FROM_GC(gc); _PyObject_ASSERT(op, gc->_gc_next & NEXT_MASK_UNREACHABLE); - next = GC_NEXT(gc); gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; + next = (PyGC_Head*)gc->_gc_next; if (has_legacy_finalizer(op)) { gc_clear_collecting(gc); @@ -849,8 +726,8 @@ clear_unreachable_mask(PyGC_Head *unreachable) PyGC_Head *gc, *next; for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { _PyObject_ASSERT((PyObject*)FROM_GC(gc), gc->_gc_next & NEXT_MASK_UNREACHABLE); - next = GC_NEXT(gc); gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; + next = (PyGC_Head*)gc->_gc_next; } validate_list(unreachable, collecting_set_unreachable_clear); } @@ -859,9 +736,7 @@ clear_unreachable_mask(PyGC_Head *unreachable) static int visit_move(PyObject *op, void *arg) { - struct visit_reachable_context *ctx = (struct visit_reachable_context *)arg; - PyGC_Head *tolist = ctx->head; - ctx->stats->object_visits += 1; + PyGC_Head *tolist = arg; OBJECT_STAT_INC(object_visits); if (_PyObject_IS_GC(op)) { PyGC_Head *gc = AS_GC(op); @@ -877,12 +752,8 @@ visit_move(PyObject *op, void *arg) * into finalizers set. */ static void -move_legacy_finalizer_reachable(PyGC_Head *finalizers, struct gc_generation_stats *stats) +move_legacy_finalizer_reachable(PyGC_Head *finalizers) { - struct visit_reachable_context ctx = { - .head = finalizers, - .stats = stats - }; traverseproc traverse; PyGC_Head *gc = GC_NEXT(finalizers); for (; gc != finalizers; gc = GC_NEXT(gc)) { @@ -890,7 +761,7 @@ move_legacy_finalizer_reachable(PyGC_Head *finalizers, struct gc_generation_stat traverse = Py_TYPE(FROM_GC(gc))->tp_traverse; (void) traverse(FROM_GC(gc), visit_move, - &ctx); + (void *)finalizers); } } @@ -1035,7 +906,6 @@ handle_weakref_callbacks(PyGC_Head *unreachable, PyGC_Head *old) /* Invoke the callbacks we decided to honor. It's safe to invoke them * because they can't reference unreachable objects. */ - int visited_space = get_gc_state()->visited_space; while (! gc_list_is_empty(&wrcb_to_call)) { PyObject *temp; PyObject *callback; @@ -1071,7 +941,6 @@ handle_weakref_callbacks(PyGC_Head *unreachable, PyGC_Head *old) Py_DECREF(op); if (wrcb_to_call._gc_next == (uintptr_t)gc) { /* object is still alive -- move it */ - gc_set_old_space(gc, visited_space); gc_list_move(gc, old); } else { @@ -1250,6 +1119,25 @@ delete_garbage(PyThreadState *tstate, GCState *gcstate, } +// Show stats for objects in each generations +static void +show_stats_each_generations(GCState *gcstate) +{ + char buf[100]; + size_t pos = 0; + + for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) { + pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos, + " %zd", + gc_list_size(GEN_HEAD(gcstate, i))); + } + + PySys_FormatStderr( + "gc: objects in each generation:%s\n" + "gc: objects in permanent generation: %zd\n", + buf, gc_list_size(&gcstate->permanent_generation.head)); +} + /* Deduce which objects among "base" are unreachable from outside the list and move them to 'unreachable'. The process consist in the following steps: @@ -1278,7 +1166,7 @@ flag is cleared (for example, by using 'clear_unreachable_mask' function or by a call to 'move_legacy_finalizers'), the 'unreachable' list is not a normal list and we can not use most gc_list_* functions for it. */ static inline Py_ssize_t -deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable, struct gc_generation_stats *stats) { +deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable) { validate_list(base, collecting_clear_unreachable_clear); /* Using ob_refcnt and gc_refs, calculate which objects in the * container set are reachable from outside the set (i.e., have a @@ -1286,7 +1174,7 @@ deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable, struct gc_generation * set are taken into account). */ Py_ssize_t candidates = update_refs(base); // gc_prev is used for gc_refs - subtract_refs(base, stats); + subtract_refs(base); /* Leave everything reachable from outside base in base, and move * everything else (in base) to unreachable. @@ -1323,7 +1211,8 @@ deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable, struct gc_generation * the reachable objects instead. But this is a one-time cost, probably not * worth complicating the code to speed just a little. */ - move_unreachable(base, unreachable, stats); // gc_prev is pointer again + gc_list_init(unreachable); + move_unreachable(base, unreachable); // gc_prev is pointer again validate_list(base, collecting_clear_unreachable_clear); validate_list(unreachable, collecting_set_unreachable_set); return candidates; @@ -1344,8 +1233,7 @@ PREV_MARK_COLLECTING set, but the objects in this set are going to be removed so we can skip the expense of clearing the flag to avoid extra iteration. */ static inline void handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable, - PyGC_Head *old_generation, - struct gc_generation_stats *stats) + PyGC_Head *old_generation) { // Remove the PREV_MASK_COLLECTING from unreachable // to prepare it for a new call to 'deduce_unreachable' @@ -1355,49 +1243,126 @@ handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable, // have the PREV_MARK_COLLECTING set, but the objects are going to be // removed so we can skip the expense of clearing the flag. PyGC_Head* resurrected = unreachable; - deduce_unreachable(resurrected, still_unreachable, stats); + deduce_unreachable(resurrected, still_unreachable); clear_unreachable_mask(still_unreachable); // Move the resurrected objects to the old generation for future collection. gc_list_merge(resurrected, old_generation); } -static void -gc_collect_region(PyThreadState *tstate, - PyGC_Head *from, - PyGC_Head *to, - struct gc_generation_stats *stats); -static inline Py_ssize_t -gc_list_set_space(PyGC_Head *list, int space) +/* Invoke progress callbacks to notify clients that garbage collection + * is starting or stopping + */ +static void +invoke_gc_callback(PyThreadState *tstate, const char *phase, + int generation, struct gc_generation_stats *stats) { - Py_ssize_t size = 0; - PyGC_Head *gc; - for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(gc)) { - gc_set_old_space(gc, space); - size++; + assert(!_PyErr_Occurred(tstate)); + + /* we may get called very early */ + GCState *gcstate = &tstate->interp->gc; + if (gcstate->callbacks == NULL) { + return; } - return size; + + /* The local variable cannot be rebound, check it for sanity */ + assert(PyList_CheckExact(gcstate->callbacks)); + PyObject *info = NULL; + if (PyList_GET_SIZE(gcstate->callbacks) != 0) { + info = Py_BuildValue("{sisnsnsnsd}", + "generation", generation, + "collected", stats->collected, + "uncollectable", stats->uncollectable, + "candidates", stats->candidates, + "duration", stats->duration); + if (info == NULL) { + PyErr_FormatUnraisable("Exception ignored on invoking gc callbacks"); + return; + } + } + + PyObject *phase_obj = PyUnicode_FromString(phase); + if (phase_obj == NULL) { + Py_XDECREF(info); + PyErr_FormatUnraisable("Exception ignored on invoking gc callbacks"); + return; + } + + PyObject *stack[] = {phase_obj, info}; + for (Py_ssize_t i=0; icallbacks); i++) { + PyObject *r, *cb = PyList_GET_ITEM(gcstate->callbacks, i); + Py_INCREF(cb); /* make sure cb doesn't go away */ + r = PyObject_Vectorcall(cb, stack, 2, NULL); + if (r == NULL) { + PyErr_FormatUnraisable("Exception ignored while " + "calling GC callback %R", cb); + } + else { + Py_DECREF(r); + } + Py_DECREF(cb); + } + Py_DECREF(phase_obj); + Py_XDECREF(info); + assert(!_PyErr_Occurred(tstate)); } -/* Making progress in the incremental collector - * In order to eventually collect all cycles - * the incremental collector must progress through the old - * space faster than objects are added to the old space. - * - * Each young or incremental collection adds a number of - * objects, S (for survivors) to the old space, and - * incremental collectors scan I objects from the old space. - * I > S must be true. We also want I > S * N to be where - * N > 1. Higher values of N mean that the old space is - * scanned more rapidly. - * The default incremental threshold of 10 translates to - * N == 1.4 (1 + 4/threshold) - */ -/* Divide by 10, so that the default incremental threshold of 10 - * scans objects at 1% of the heap size */ -#define SCAN_RATE_DIVISOR 10 +/* Find the oldest generation (highest numbered) where the count + * exceeds the threshold. Objects in the that generation and + * generations younger than it will be collected. */ +static int +gc_select_generation(GCState *gcstate) +{ + for (int i = NUM_GENERATIONS-1; i >= 0; i--) { + if (gcstate->generations[i].count > gcstate->generations[i].threshold) { + /* Avoid quadratic performance degradation in number + of tracked objects (see also issue #4074): + + To limit the cost of garbage collection, there are two strategies; + - make each collection faster, e.g. by scanning fewer objects + - do less collections + This heuristic is about the latter strategy. + + In addition to the various configurable thresholds, we only trigger a + full collection if the ratio + + long_lived_pending / long_lived_total + + is above a given value (hardwired to 25%). + + The reason is that, while "non-full" collections (i.e., collections of + the young and middle generations) will always examine roughly the same + number of objects -- determined by the aforementioned thresholds --, + the cost of a full collection is proportional to the total number of + long-lived objects, which is virtually unbounded. + + Indeed, it has been remarked that doing a full collection every + of object creations entails a dramatic performance + degradation in workloads which consist in creating and storing lots of + long-lived objects (e.g. building a large list of GC-tracked objects would + show quadratic performance, instead of linear as expected: see issue #4074). + + Using the above ratio, instead, yields amortized linear performance in + the total number of objects (the effect of which can be summarized + thusly: "each full garbage collection is more and more costly as the + number of objects grows, but we do fewer and fewer of them"). + + This heuristic was suggested by Martin von Löwis on python-dev in + June 2008. His original analysis and proposal can be found at: + http://mail.python.org/pipermail/python-dev/2008-June/080579.html + */ + if (i == NUM_GENERATIONS - 1 + && gcstate->long_lived_pending < gcstate->long_lived_total / 4) + { + continue; + } + return i; + } + } + return -1; +} static struct gc_generation_stats * gc_get_stats(GCState *gcstate, int gen) @@ -1441,421 +1406,120 @@ add_stats(GCState *gcstate, int gen, struct gc_generation_stats *stats) cur_stats->ts_start = stats->ts_start; cur_stats->ts_stop = stats->ts_stop; - cur_stats->heap_size = stats->heap_size; - cur_stats->work_to_do = stats->work_to_do; cur_stats->collections += 1; - cur_stats->object_visits += stats->object_visits; cur_stats->collected += stats->collected; cur_stats->uncollectable += stats->uncollectable; cur_stats->candidates += stats->candidates; - cur_stats->objects_transitively_reachable += stats->objects_transitively_reachable; - cur_stats->objects_not_transitively_reachable += stats->objects_not_transitively_reachable; - cur_stats->duration += stats->duration; } -static void -gc_collect_young(PyThreadState *tstate, - struct gc_generation_stats *stats) -{ - GCState *gcstate = &tstate->interp->gc; - validate_spaces(gcstate); - PyGC_Head *young = &gcstate->young.head; - PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head; - untrack_tuples(young); - - PyGC_Head survivors; - gc_list_init(&survivors); - gc_list_set_space(young, gcstate->visited_space); - gc_collect_region(tstate, young, &survivors, stats); - gc_list_merge(&survivors, visited); - validate_spaces(gcstate); - gcstate->young.count = 0; - gcstate->old[gcstate->visited_space].count++; - validate_spaces(gcstate); -} - -#ifndef NDEBUG -static inline int -IS_IN_VISITED(PyGC_Head *gc, int visited_space) -{ - assert(visited_space == 0 || other_space(visited_space) == 0); - return gc_old_space(gc) == visited_space; -} -#endif - -struct container_and_flag { - PyGC_Head *container; - int visited_space; - intptr_t size; - struct gc_generation_stats *stats; -}; - -/* A traversal callback for adding to container) */ -static int -visit_add_to_container(PyObject *op, void *arg) -{ - OBJECT_STAT_INC(object_visits); - struct container_and_flag *cf = (struct container_and_flag *)arg; - cf->stats->object_visits += 1; - int visited = cf->visited_space; - assert(visited == get_gc_state()->visited_space); - if (!_Py_IsImmortal(op) && _PyObject_IS_GC(op)) { - PyGC_Head *gc = AS_GC(op); - if (_PyObject_GC_IS_TRACKED(op) && - gc_old_space(gc) != visited) { - gc_flip_old_space(gc); - gc_list_move(gc, cf->container); - cf->size++; - } - } - return 0; -} - -static intptr_t -expand_region_transitively_reachable(PyGC_Head *container, - PyGC_Head *gc, - GCState *gcstate, - struct gc_generation_stats *stats) -{ - struct container_and_flag arg = { - .container = container, - .visited_space = gcstate->visited_space, - .size = 0, - .stats = stats - }; - assert(GC_NEXT(gc) == container); - while (gc != container) { - /* Survivors will be moved to visited space, so they should - * have been marked as visited */ - assert(IS_IN_VISITED(gc, gcstate->visited_space)); - PyObject *op = FROM_GC(gc); - assert(_PyObject_GC_IS_TRACKED(op)); - if (_Py_IsImmortal(op)) { - PyGC_Head *next = GC_NEXT(gc); - gc_list_move(gc, &gcstate->permanent_generation.head); - gc = next; - continue; - } - traverseproc traverse = Py_TYPE(op)->tp_traverse; - (void) traverse(op, - visit_add_to_container, - &arg); - gc = GC_NEXT(gc); - } - return arg.size; -} - -/* Do bookkeeping for a completed GC cycle */ -static void -completed_scavenge(GCState *gcstate) -{ - /* We must observe two invariants: - * 1. Members of the permanent generation must be marked visited. - * 2. We cannot touch members of the permanent generation. */ - int visited; - if (gc_list_is_empty(&gcstate->permanent_generation.head)) { - /* Permanent generation is empty so we can flip spaces bit */ - int not_visited = gcstate->visited_space; - visited = other_space(not_visited); - gcstate->visited_space = visited; - /* Make sure all objects have visited bit set correctly */ - gc_list_set_space(&gcstate->young.head, not_visited); - } - else { - /* We must move the objects from visited to pending space. */ - visited = gcstate->visited_space; - int not_visited = other_space(visited); - assert(gc_list_is_empty(&gcstate->old[not_visited].head)); - gc_list_merge(&gcstate->old[visited].head, &gcstate->old[not_visited].head); - gc_list_set_space(&gcstate->old[not_visited].head, not_visited); - } - assert(gc_list_is_empty(&gcstate->old[visited].head)); - gcstate->work_to_do = 0; - gcstate->phase = GC_PHASE_MARK; -} - -static intptr_t -move_to_reachable(PyObject *op, PyGC_Head *reachable, int visited_space) -{ - if (op != NULL && !_Py_IsImmortal(op) && _PyObject_IS_GC(op)) { - PyGC_Head *gc = AS_GC(op); - if (_PyObject_GC_IS_TRACKED(op) && - gc_old_space(gc) != visited_space) { - gc_flip_old_space(gc); - gc_list_move(gc, reachable); - return 1; - } - } - return 0; -} - -static intptr_t -mark_all_reachable(PyGC_Head *reachable, PyGC_Head *visited, int visited_space, struct gc_generation_stats *stats) -{ - // Transitively traverse all objects from reachable, until empty - struct container_and_flag arg = { - .container = reachable, - .visited_space = visited_space, - .size = 0, - .stats = stats - }; - while (!gc_list_is_empty(reachable)) { - PyGC_Head *gc = _PyGCHead_NEXT(reachable); - assert(gc_old_space(gc) == visited_space); - gc_list_move(gc, visited); - PyObject *op = FROM_GC(gc); - traverseproc traverse = Py_TYPE(op)->tp_traverse; - (void) traverse(op, - visit_add_to_container, - &arg); - } - gc_list_validate_space(visited, visited_space); - return arg.size; -} - -static intptr_t -mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, bool start, struct gc_generation_stats *stats) -{ - PyGC_Head reachable; - gc_list_init(&reachable); - Py_ssize_t objects_marked = 0; - // Move all objects on stacks to reachable - _PyRuntimeState *runtime = &_PyRuntime; - HEAD_LOCK(runtime); - PyThreadState* ts = PyInterpreterState_ThreadHead(interp); - HEAD_UNLOCK(runtime); - while (ts) { - _PyInterpreterFrame *frame = ts->current_frame; - while (frame) { - if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) { - frame = frame->previous; - continue; - } - _PyStackRef *locals = frame->localsplus; - _PyStackRef *sp = frame->stackpointer; - objects_marked += move_to_reachable(frame->f_locals, &reachable, visited_space); - PyObject *func = PyStackRef_AsPyObjectBorrow(frame->f_funcobj); - objects_marked += move_to_reachable(func, &reachable, visited_space); - while (sp > locals) { - sp--; - if (PyStackRef_IsNullOrInt(*sp)) { - continue; - } - PyObject *op = PyStackRef_AsPyObjectBorrow(*sp); - if (_Py_IsImmortal(op)) { - continue; - } - if (_PyObject_IS_GC(op)) { - PyGC_Head *gc = AS_GC(op); - if (_PyObject_GC_IS_TRACKED(op) && - gc_old_space(gc) != visited_space) { - gc_flip_old_space(gc); - objects_marked++; - gc_list_move(gc, &reachable); - } - } - } - if (!start && frame->visited) { - // If this frame has already been visited, then the lower frames - // will have already been visited and will not have changed - break; - } - frame->visited = 1; - frame = frame->previous; - } - HEAD_LOCK(runtime); - ts = PyThreadState_Next(ts); - HEAD_UNLOCK(runtime); - } - objects_marked += mark_all_reachable(&reachable, visited, visited_space, stats); - assert(gc_list_is_empty(&reachable)); - return objects_marked; -} - -static intptr_t -mark_global_roots(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, struct gc_generation_stats *stats) -{ - PyGC_Head reachable; - gc_list_init(&reachable); - Py_ssize_t objects_marked = 0; - objects_marked += move_to_reachable(interp->sysdict, &reachable, visited_space); - objects_marked += move_to_reachable(interp->builtins, &reachable, visited_space); - objects_marked += move_to_reachable(interp->dict, &reachable, visited_space); - struct types_state *types = &interp->types; - for (int i = 0; i < _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES; i++) { - objects_marked += move_to_reachable(types->builtins.initialized[i].tp_dict, &reachable, visited_space); - objects_marked += move_to_reachable(types->builtins.initialized[i].tp_subclasses, &reachable, visited_space); - } - for (int i = 0; i < _Py_MAX_MANAGED_STATIC_EXT_TYPES; i++) { - objects_marked += move_to_reachable(types->for_extensions.initialized[i].tp_dict, &reachable, visited_space); - objects_marked += move_to_reachable(types->for_extensions.initialized[i].tp_subclasses, &reachable, visited_space); - } - objects_marked += mark_all_reachable(&reachable, visited, visited_space, stats); - assert(gc_list_is_empty(&reachable)); - return objects_marked; -} - -static intptr_t -mark_at_start(PyThreadState *tstate, struct gc_generation_stats *stats) -{ - // TO DO -- Make this incremental - GCState *gcstate = &tstate->interp->gc; - PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head; - Py_ssize_t objects_marked = mark_global_roots(tstate->interp, visited, gcstate->visited_space, stats); - objects_marked += mark_stacks(tstate->interp, visited, gcstate->visited_space, true, stats); - gcstate->work_to_do -= objects_marked; - gcstate->phase = GC_PHASE_COLLECT; - validate_spaces(gcstate); - return objects_marked; -} - -static intptr_t -assess_work_to_do(GCState *gcstate) -{ - /* The amount of work we want to do depends on three things. - * 1. The number of new objects created - * 2. The growth in heap size since the last collection - * 3. The heap size (up to the number of new objects, to avoid quadratic effects) - * - * For a steady state heap, the amount of work to do is three times the number - * of new objects added to the heap. This ensures that we stay ahead in the - * worst case of all new objects being garbage. - * - * This could be improved by tracking survival rates, but it is still a - * large improvement on the non-marking approach. - */ - intptr_t scale_factor = gcstate->old[0].threshold; - if (scale_factor < 2) { - scale_factor = 2; - } - intptr_t new_objects = gcstate->young.count; - intptr_t max_heap_fraction = new_objects*2; - intptr_t heap_fraction = gcstate->heap_size / SCAN_RATE_DIVISOR / scale_factor; - if (heap_fraction > max_heap_fraction) { - heap_fraction = max_heap_fraction; - } - gcstate->young.count = 0; - return new_objects + heap_fraction; -} - -static void -gc_collect_increment(PyThreadState *tstate, struct gc_generation_stats *stats) -{ - GCState *gcstate = &tstate->interp->gc; - gcstate->work_to_do += assess_work_to_do(gcstate); - if (gcstate->work_to_do < 0) { - return; - } - untrack_tuples(&gcstate->young.head); - if (gcstate->phase == GC_PHASE_MARK) { - Py_ssize_t objects_marked = mark_at_start(tstate, stats); - stats->objects_transitively_reachable += objects_marked; - stats->candidates += objects_marked; - gcstate->work_to_do -= objects_marked; - validate_spaces(gcstate); - return; - } - PyGC_Head *not_visited = &gcstate->old[gcstate->visited_space^1].head; - PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head; - PyGC_Head increment; - gc_list_init(&increment); - int scale_factor = gcstate->old[0].threshold; - if (scale_factor < 2) { - scale_factor = 2; - } - intptr_t objects_marked = mark_stacks(tstate->interp, visited, gcstate->visited_space, false, stats); - stats->objects_transitively_reachable += objects_marked; - gcstate->work_to_do -= objects_marked; - gc_list_set_space(&gcstate->young.head, gcstate->visited_space); - gc_list_merge(&gcstate->young.head, &increment); - gc_list_validate_space(&increment, gcstate->visited_space); - Py_ssize_t increment_size = gc_list_size(&increment); - while (increment_size < gcstate->work_to_do) { - if (gc_list_is_empty(not_visited)) { - break; - } - PyGC_Head *gc = _PyGCHead_NEXT(not_visited); - gc_list_move(gc, &increment); - increment_size++; - assert(!_Py_IsImmortal(FROM_GC(gc))); - gc_set_old_space(gc, gcstate->visited_space); - increment_size += expand_region_transitively_reachable(&increment, gc, gcstate, stats); - } - stats->objects_not_transitively_reachable += increment_size; - validate_list(&increment, collecting_clear_unreachable_clear); - gc_list_validate_space(&increment, gcstate->visited_space); - PyGC_Head survivors; - gc_list_init(&survivors); - gc_collect_region(tstate, &increment, &survivors, stats); - gc_list_merge(&survivors, visited); - assert(gc_list_is_empty(&increment)); - gcstate->work_to_do -= increment_size; - - if (gc_list_is_empty(not_visited)) { - completed_scavenge(gcstate); - } - validate_spaces(gcstate); -} - -static void -gc_collect_full(PyThreadState *tstate, - struct gc_generation_stats *stats) -{ - GCState *gcstate = &tstate->interp->gc; - validate_spaces(gcstate); - PyGC_Head *young = &gcstate->young.head; - PyGC_Head *pending = &gcstate->old[gcstate->visited_space^1].head; - PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head; - untrack_tuples(young); - /* merge all generations into visited */ - gc_list_merge(young, pending); - gc_list_validate_space(pending, 1-gcstate->visited_space); - gc_list_set_space(pending, gcstate->visited_space); - gcstate->young.count = 0; - gc_list_merge(pending, visited); - validate_spaces(gcstate); - - gc_collect_region(tstate, visited, visited, - stats); - validate_spaces(gcstate); - gcstate->young.count = 0; - gcstate->old[0].count = 0; - gcstate->old[1].count = 0; - completed_scavenge(gcstate); - _PyGC_ClearAllFreeLists(tstate->interp); - validate_spaces(gcstate); -} - -/* This is the main function. Read this to understand how the +/* This is the main function. Read this to understand how the * collection process works. */ -static void -gc_collect_region(PyThreadState *tstate, - PyGC_Head *from, - PyGC_Head *to, - struct gc_generation_stats *stats) +static Py_ssize_t +gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason) { + int i; + PyGC_Head *young; /* the generation we are examining */ + PyGC_Head *old; /* next older generation */ PyGC_Head unreachable; /* non-problematic unreachable trash */ PyGC_Head finalizers; /* objects with, & reachable from, __del__ */ - PyGC_Head *gc; /* initialize to prevent a compiler warning */ + PyGC_Head *gc; GCState *gcstate = &tstate->interp->gc; + // gc_collect_main() must not be called before _PyGC_Init + // or after _PyGC_Fini() assert(gcstate->garbage != NULL); assert(!_PyErr_Occurred(tstate)); - gc_list_init(&unreachable); - stats->candidates = deduce_unreachable(from, &unreachable, stats); - validate_consistent_old_space(from); - untrack_tuples(from); - - /* Move reachable objects to next generation. */ - validate_consistent_old_space(to); - if (from != to) { - gc_list_merge(from, to); + int expected = 0; + if (!_Py_atomic_compare_exchange_int(&gcstate->collecting, &expected, 1)) { + // Don't start a garbage collection if one is already in progress. + return 0; + } + gcstate->frame = tstate->current_frame; + + if (generation == GENERATION_AUTO) { + // Select the oldest generation that needs collecting. We will collect + // objects from that generation and all generations younger than it. + generation = gc_select_generation(gcstate); + if (generation < 0) { + // No generation needs to be collected. + _Py_atomic_store_int(&gcstate->collecting, 0); + return 0; + } + } + + assert(generation >= 0 && generation < NUM_GENERATIONS); + +#ifdef Py_STATS + if (_Py_stats) { + _Py_stats->object_stats.object_visits = 0; + } +#endif + GC_STAT_ADD(generation, collections, 1); + + struct gc_generation_stats stats = { 0 }; + if (reason != _Py_GC_REASON_SHUTDOWN) { + invoke_gc_callback(tstate, "start", generation, &stats); + } + + // ignore error: don't interrupt the GC if reading the clock fails + (void)PyTime_PerfCounterRaw(&stats.ts_start); + if (gcstate->debug & _PyGC_DEBUG_STATS) { + PySys_WriteStderr("gc: collecting generation %d...\n", generation); + show_stats_each_generations(gcstate); + } + + if (PyDTrace_GC_START_ENABLED()) { + PyDTrace_GC_START(generation); + } + + /* update collection and allocation counters */ + if (generation+1 < NUM_GENERATIONS) { + gcstate->generations[generation+1].count += 1; + } + for (i = 0; i <= generation; i++) { + gcstate->generations[i].count = 0; + } + + /* merge younger generations with one we are currently collecting */ + for (i = 0; i < generation; i++) { + gc_list_merge(GEN_HEAD(gcstate, i), GEN_HEAD(gcstate, generation)); + } + + /* handy references */ + young = GEN_HEAD(gcstate, generation); + if (generation < NUM_GENERATIONS-1) { + old = GEN_HEAD(gcstate, generation+1); + } + else { + old = young; + } + validate_list(old, collecting_clear_unreachable_clear); + + stats.candidates = deduce_unreachable(young, &unreachable); + + untrack_tuples(young); + /* Move reachable objects to next generation. */ + if (young != old) { + if (generation == NUM_GENERATIONS - 2) { + gcstate->long_lived_pending += gc_list_size(young); + } + gc_list_merge(young, old); + } + else { + // In Python <= 3.13, we called untrack_dicts(young) here to untrack + // atomic-only dicts (see issue #14775). Python 3.14 removed the lazy + // dict tracking machinery entirely (GH-127010) -- dicts are always + // tracked from creation and never untracked by GC. That way, we don't + // have to restore MAINTAIN_TRACKING across every PyDict_SetItem call + // site; the cost is slightly more work for full collections on dicts + // with only atomic values. + gcstate->long_lived_pending = 0; + gcstate->long_lived_total = gc_list_size(young); } - validate_consistent_old_space(to); /* All objects in unreachable are trash, but objects reachable from * legacy finalizers (e.g. tp_del) can't safely be deleted. @@ -1868,9 +1532,11 @@ gc_collect_region(PyThreadState *tstate, * unreachable objects reachable *from* those are also uncollectable, * and we move those into the finalizers list too. */ - move_legacy_finalizer_reachable(&finalizers, stats); + move_legacy_finalizer_reachable(&finalizers); + validate_list(&finalizers, collecting_clear_unreachable_clear); validate_list(&unreachable, collecting_set_unreachable_clear); + /* Print debugging information. */ if (gcstate->debug & _PyGC_DEBUG_COLLECTABLE) { for (gc = GC_NEXT(&unreachable); gc != &unreachable; gc = GC_NEXT(gc)) { @@ -1878,23 +1544,25 @@ gc_collect_region(PyThreadState *tstate, } } - /* Invoke weakref callbacks as necessary. */ - stats->collected += handle_weakref_callbacks(&unreachable, to); - gc_list_validate_space(to, gcstate->visited_space); - validate_list(to, collecting_clear_unreachable_clear); + /* Clear weakrefs and invoke callbacks as necessary. */ + stats.collected += handle_weakref_callbacks(&unreachable, old); + validate_list(old, collecting_clear_unreachable_clear); validate_list(&unreachable, collecting_set_unreachable_clear); /* Call tp_finalize on objects which have one. */ finalize_garbage(tstate, &unreachable); + /* Handle any objects that may have resurrected after the call * to 'finalize_garbage' and continue the collection with the * objects that are still unreachable */ PyGC_Head final_unreachable; - gc_list_init(&final_unreachable); - handle_resurrected_objects(&unreachable, &final_unreachable, to, stats); + handle_resurrected_objects(&unreachable, &final_unreachable, old); - /* Clear weakrefs to objects in the unreachable set. See the comments - * above handle_weakref_callbacks() for details. + /* Clear weakrefs to objects in the unreachable set. No Python-level + * code must be allowed to access those unreachable objects. During + * delete_garbage(), finalizers outside the unreachable set might run + * and create new weakrefs. If those weakrefs were not cleared, they + * could reveal unreachable objects. Callbacks are not executed. */ clear_weakrefs(&final_unreachable); @@ -1902,8 +1570,8 @@ gc_collect_region(PyThreadState *tstate, * the reference cycles to be broken. It may also cause some objects * in finalizers to be freed. */ - stats->collected += gc_list_size(&final_unreachable); - delete_garbage(tstate, gcstate, &final_unreachable, to); + stats.collected += gc_list_size(&final_unreachable); + delete_garbage(tstate, gcstate, &final_unreachable, old); /* Collect statistics on uncollectable objects found and print * debugging information. */ @@ -1913,75 +1581,61 @@ gc_collect_region(PyThreadState *tstate, if (gcstate->debug & _PyGC_DEBUG_UNCOLLECTABLE) debug_cycle("uncollectable", FROM_GC(gc)); } - stats->uncollectable = n; + stats.uncollectable = n; + (void)PyTime_PerfCounterRaw(&stats.ts_stop); + stats.duration = PyTime_AsSecondsDouble(stats.ts_stop - stats.ts_start); + if (gcstate->debug & _PyGC_DEBUG_STATS) { + PySys_WriteStderr( + "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", + stats.uncollectable+stats.collected, stats.uncollectable, + stats.duration); + } + /* Append instances in the uncollectable set to a Python * reachable list of garbage. The programmer has to deal with * this if they insist on creating this type of structure. */ - handle_legacy_finalizers(tstate, gcstate, &finalizers, to); - gc_list_validate_space(to, gcstate->visited_space); - validate_list(to, collecting_clear_unreachable_clear); -} + handle_legacy_finalizers(tstate, gcstate, &finalizers, old); + validate_list(old, collecting_clear_unreachable_clear); -/* Invoke progress callbacks to notify clients that garbage collection - * is starting or stopping - */ -static void -do_gc_callback(GCState *gcstate, const char *phase, - int generation, struct gc_generation_stats *stats) -{ - assert(!PyErr_Occurred()); - - /* The local variable cannot be rebound, check it for sanity */ - assert(PyList_CheckExact(gcstate->callbacks)); - PyObject *info = NULL; - if (PyList_GET_SIZE(gcstate->callbacks) != 0) { - info = Py_BuildValue("{sisnsnsnsd}", - "generation", generation, - "collected", stats->collected, - "uncollectable", stats->uncollectable, - "candidates", stats->candidates, - "duration", stats->duration); - if (info == NULL) { - PyErr_FormatUnraisable("Exception ignored while invoking gc callbacks"); - return; - } + /* Clear free list only during the collection of the highest + * generation */ + if (generation == NUM_GENERATIONS-1) { + _PyGC_ClearAllFreeLists(tstate->interp); } - PyObject *phase_obj = PyUnicode_FromString(phase); - if (phase_obj == NULL) { - Py_XDECREF(info); - PyErr_FormatUnraisable("Exception ignored while invoking gc callbacks"); - return; - } - - PyObject *stack[] = {phase_obj, info}; - for (Py_ssize_t i=0; icallbacks); i++) { - PyObject *r, *cb = PyList_GET_ITEM(gcstate->callbacks, i); - Py_INCREF(cb); /* make sure cb doesn't go away */ - r = PyObject_Vectorcall(cb, stack, 2, NULL); - if (r == NULL) { - PyErr_FormatUnraisable("Exception ignored while " - "calling GC callback %R", cb); + if (_PyErr_Occurred(tstate)) { + if (reason == _Py_GC_REASON_SHUTDOWN) { + _PyErr_Clear(tstate); } else { - Py_DECREF(r); + PyErr_FormatUnraisable("Exception ignored in garbage collection"); } - Py_DECREF(cb); } - Py_DECREF(phase_obj); - Py_XDECREF(info); - assert(!PyErr_Occurred()); -} -static void -invoke_gc_callback(GCState *gcstate, const char *phase, - int generation, struct gc_generation_stats *stats) -{ - if (gcstate->callbacks == NULL) { - return; + /* Update stats */ + add_stats(gcstate, generation, &stats); + GC_STAT_ADD(generation, objects_collected, m); +#ifdef Py_STATS + if (_Py_stats) { + GC_STAT_ADD(generation, object_visits, + _Py_stats->object_stats.object_visits); + _Py_stats->object_stats.object_visits = 0; } - do_gc_callback(gcstate, phase, generation, stats); +#endif + + if (PyDTrace_GC_DONE_ENABLED()) { + PyDTrace_GC_DONE(stats.uncollectable + stats.collected); + } + + if (reason != _Py_GC_REASON_SHUTDOWN) { + invoke_gc_callback(tstate, "stop", generation, &stats); + } + + assert(!_PyErr_Occurred(tstate)); + gcstate->frame = NULL; + _Py_atomic_store_int(&gcstate->collecting, 0); + return stats.uncollectable + stats.collected; } static int @@ -2043,25 +1697,20 @@ _PyGC_GetObjects(PyInterpreterState *interp, int generation) GCState *gcstate = &interp->gc; PyObject *result = PyList_New(0); - /* Generation: - * -1: Return all objects - * 0: All young objects - * 1: No objects - * 2: All old objects - */ - if (result == NULL || generation == 1) { - return result; + if (result == NULL) { + return NULL; } - if (generation <= 0) { - if (append_objects(result, &gcstate->young.head)) { - goto error; + + if (generation == -1) { + /* If generation is -1, get all objects from all generations */ + for (int i = 0; i < NUM_GENERATIONS; i++) { + if (append_objects(result, GEN_HEAD(gcstate, i))) { + goto error; + } } } - if (generation != 0) { - if (append_objects(result, &gcstate->old[0].head)) { - goto error; - } - if (append_objects(result, &gcstate->old[1].head)) { + else { + if (append_objects(result, GEN_HEAD(gcstate, generation))) { goto error; } } @@ -2076,23 +1725,10 @@ void _PyGC_Freeze(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; - /* The permanent_generation must be visited */ - gc_list_set_space(&gcstate->young.head, gcstate->visited_space); - gc_list_merge(&gcstate->young.head, &gcstate->permanent_generation.head); - gcstate->young.count = 0; - PyGC_Head*old0 = &gcstate->old[0].head; - PyGC_Head*old1 = &gcstate->old[1].head; - if (gcstate->visited_space) { - gc_list_set_space(old0, 1); + for (int i = 0; i < NUM_GENERATIONS; ++i) { + gc_list_merge(GEN_HEAD(gcstate, i), &gcstate->permanent_generation.head); + gcstate->generations[i].count = 0; } - else { - gc_list_set_space(old1, 0); - } - gc_list_merge(old0, &gcstate->permanent_generation.head); - gcstate->old[0].count = 0; - gc_list_merge(old1, &gcstate->permanent_generation.head); - gcstate->old[1].count = 0; - validate_spaces(gcstate); } void @@ -2100,8 +1736,7 @@ _PyGC_Unfreeze(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; gc_list_merge(&gcstate->permanent_generation.head, - &gcstate->old[gcstate->visited_space].head); - validate_spaces(gcstate); + GEN_HEAD(gcstate, NUM_GENERATIONS-1)); } Py_ssize_t @@ -2137,103 +1772,29 @@ PyGC_IsEnabled(void) return gcstate->enabled; } -// Show stats for objects in each generations -static void -show_stats_each_generations(GCState *gcstate) +/* Public API to invoke gc.collect() from C */ +Py_ssize_t +PyGC_Collect(void) { - char buf[100]; - size_t pos = 0; + PyThreadState *tstate = _PyThreadState_GET(); + GCState *gcstate = &tstate->interp->gc; - for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) { - pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos, - " %zd", - gc_list_size(GEN_HEAD(gcstate, i))); + if (!gcstate->enabled) { + return 0; } - PySys_FormatStderr( - "gc: objects in each generation:%s\n" - "gc: objects in permanent generation: %zd\n", - buf, gc_list_size(&gcstate->permanent_generation.head)); + + Py_ssize_t n; + PyObject *exc = _PyErr_GetRaisedException(tstate); + n = gc_collect_main(tstate, NUM_GENERATIONS - 1, _Py_GC_REASON_MANUAL); + _PyErr_SetRaisedException(tstate, exc); + + return n; } Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason) { - GCState *gcstate = &tstate->interp->gc; - assert(tstate->current_frame == NULL || tstate->current_frame->stackpointer != NULL); - - int expected = 0; - if (!_Py_atomic_compare_exchange_int(&gcstate->collecting, &expected, 1)) { - // Don't start a garbage collection if one is already in progress. - return 0; - } - gcstate->frame = tstate->current_frame; - - struct gc_generation_stats stats = { 0 }; - if (reason != _Py_GC_REASON_SHUTDOWN) { - invoke_gc_callback(gcstate, "start", generation, &stats); - } - if (gcstate->debug & _PyGC_DEBUG_STATS) { - PySys_WriteStderr("gc: collecting generation %d...\n", generation); - show_stats_each_generations(gcstate); - } - if (PyDTrace_GC_START_ENABLED()) { - PyDTrace_GC_START(generation); - } - stats.heap_size = gcstate->heap_size; - stats.work_to_do = gcstate->work_to_do; - (void)PyTime_PerfCounterRaw(&stats.ts_start); - PyObject *exc = _PyErr_GetRaisedException(tstate); - switch(generation) { - case 0: - gc_collect_young(tstate, &stats); - break; - case 1: - gc_collect_increment(tstate, &stats); - break; - case 2: - gc_collect_full(tstate, &stats); - break; - default: - Py_UNREACHABLE(); - } - (void)PyTime_PerfCounterRaw(&stats.ts_stop); - stats.duration = PyTime_AsSecondsDouble(stats.ts_stop - stats.ts_start); - add_stats(gcstate, generation, &stats); - if (PyDTrace_GC_DONE_ENABLED()) { - PyDTrace_GC_DONE(stats.uncollectable + stats.collected); - } - if (reason != _Py_GC_REASON_SHUTDOWN) { - invoke_gc_callback(gcstate, "stop", generation, &stats); - } - _PyErr_SetRaisedException(tstate, exc); - GC_STAT_ADD(generation, objects_collected, stats.collected); -#ifdef Py_STATS - PyStats *s = _PyStats_GET(); - if (s) { - GC_STAT_ADD(generation, object_visits, - s->object_stats.object_visits); - s->object_stats.object_visits = 0; - } -#endif - validate_spaces(gcstate); - gcstate->frame = NULL; - _Py_atomic_store_int(&gcstate->collecting, 0); - - if (gcstate->debug & _PyGC_DEBUG_STATS) { - PySys_WriteStderr( - "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", - stats.collected + stats.uncollectable, stats.uncollectable, stats.duration - ); - } - - return stats.uncollectable + stats.collected; -} - -/* Public API to invoke gc.collect() from C */ -Py_ssize_t -PyGC_Collect(void) -{ - return _PyGC_Collect(_PyThreadState_GET(), 2, _Py_GC_REASON_MANUAL); + return gc_collect_main(tstate, generation, reason); } void @@ -2245,7 +1806,7 @@ _PyGC_CollectNoFail(PyThreadState *tstate) during interpreter shutdown (and then never finish it). See http://bugs.python.org/issue8713#msg195178 for an example. */ - _PyGC_Collect(_PyThreadState_GET(), 2, _Py_GC_REASON_SHUTDOWN); + gc_collect_main(tstate, NUM_GENERATIONS - 1, _Py_GC_REASON_SHUTDOWN); } void @@ -2304,8 +1865,6 @@ _PyGC_Fini(PyInterpreterState *interp) GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); - PyMem_RawFree(gcstate->generation_stats); - gcstate->generation_stats = NULL; /* Prevent a subtle bug that affects sub-interpreters that use basic * single-phase init extensions (m_size == -1). Those extensions cause objects @@ -2322,9 +1881,9 @@ _PyGC_Fini(PyInterpreterState *interp) * This bug was originally fixed when reported as gh-90228. The bug was * re-introduced in gh-94673. */ - finalize_unlink_gc_head(&gcstate->young.head); - finalize_unlink_gc_head(&gcstate->old[0].head); - finalize_unlink_gc_head(&gcstate->old[1].head); + for (int i = 0; i < NUM_GENERATIONS; i++) { + finalize_unlink_gc_head(&gcstate->generations[i].head); + } finalize_unlink_gc_head(&gcstate->permanent_generation.head); } @@ -2399,11 +1958,20 @@ _Py_ScheduleGC(PyThreadState *tstate) } void -_Py_TriggerGC(struct _gc_runtime_state *gcstate) +_PyObject_GC_Link(PyObject *op) { + PyGC_Head *gc = AS_GC(op); + // gc must be correctly aligned + _PyObject_ASSERT(op, ((uintptr_t)gc & (sizeof(uintptr_t)-1)) == 0); + PyThreadState *tstate = _PyThreadState_GET(); - if (gcstate->enabled && - gcstate->young.threshold != 0 && + GCState *gcstate = &tstate->interp->gc; + gc->_gc_next = 0; + gc->_gc_prev = 0; + gcstate->generations[0].count++; /* number of allocated GC objects */ + if (gcstate->generations[0].count > gcstate->generations[0].threshold && + gcstate->enabled && + gcstate->generations[0].threshold && !_Py_atomic_load_int_relaxed(&gcstate->collecting) && !_PyErr_Occurred(tstate)) { @@ -2411,23 +1979,14 @@ _Py_TriggerGC(struct _gc_runtime_state *gcstate) } } -void -_PyObject_GC_Link(PyObject *op) -{ - PyGC_Head *gc = AS_GC(op); - // gc must be correctly aligned - _PyObject_ASSERT(op, ((uintptr_t)gc & (sizeof(uintptr_t)-1)) == 0); - gc->_gc_next = 0; - gc->_gc_prev = 0; - -} - void _Py_RunGC(PyThreadState *tstate) { - if (tstate->interp->gc.enabled) { - _PyGC_Collect(tstate, 1, _Py_GC_REASON_HEAP); + GCState *gcstate = get_gc_state(); + if (!gcstate->enabled) { + return; } + gc_collect_main(tstate, GENERATION_AUTO, _Py_GC_REASON_HEAP); } static PyObject * @@ -2528,11 +2087,6 @@ PyObject_GC_Del(void *op) PyGC_Head *g = AS_GC(op); if (_PyObject_GC_IS_TRACKED(op)) { gc_list_remove(g); - GCState *gcstate = get_gc_state(); - if (gcstate->young.count > 0) { - gcstate->young.count--; - } - gcstate->heap_size--; #ifdef Py_DEBUG PyObject *exc = PyErr_GetRaisedException(); if (PyErr_WarnExplicitFormat(PyExc_ResourceWarning, "gc", 0, @@ -2546,6 +2100,10 @@ PyObject_GC_Del(void *op) PyErr_SetRaisedException(exc); #endif } + GCState *gcstate = get_gc_state(); + if (gcstate->generations[0].count > 0) { + gcstate->generations[0].count--; + } PyObject_Free(((char *)op)-presize); } @@ -2590,18 +2148,14 @@ PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg) GCState *gcstate = get_gc_state(); int original_state = gcstate->enabled; gcstate->enabled = 0; - if (visit_generation(callback, arg, &gcstate->young) < 0) { - goto done; - } - if (visit_generation(callback, arg, &gcstate->old[0]) < 0) { - goto done; - } - if (visit_generation(callback, arg, &gcstate->old[1]) < 0) { - goto done; + for (size_t i = 0; i < NUM_GENERATIONS; i++) { + if (visit_generation(callback, arg, &gcstate->generations[i]) < 0) { + goto done; + } } visit_generation(callback, arg, &gcstate->permanent_generation); done: gcstate->enabled = original_state; } -#endif // Py_GIL_DISABLED +#endif // !Py_GIL_DISABLED From c80e446e6b91fb64e1cbfed8986869accd1fafb6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 30 Apr 2026 22:19:46 +0300 Subject: [PATCH 719/775] gh-149028: Revert gh-92936 changes (GH-149182) * Revert "gh-92936: update `http.cookies` docs post GH-113663 (#137566)" This reverts commit d86c2257a69a8d6c650c0db470499463131a569f. * Revert "gh-92936: allow double quote in cookie values (#113663)" This reverts commit d7dbde895884d58e3da7ed4107fd33171afad7cb. --- Doc/library/http.cookies.rst | 11 +---------- Doc/whatsnew/3.15.rst | 7 ------- Lib/http/cookies.py | 2 +- Lib/test/test_http_cookies.py | 23 ----------------------- 4 files changed, 2 insertions(+), 41 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index b3fcd21c7e2..1122b30d29d 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -25,10 +25,8 @@ The character set, :data:`string.ascii_letters`, :data:`string.digits` and in a cookie name (as :attr:`~Morsel.key`). .. versionchanged:: 3.3 - Allowed '``:``' as a valid cookie name character. + Allowed ':' as a valid cookie name character. -.. versionchanged:: 3.15 - Allowed '``"``' as a valid cookie value character. .. note:: @@ -313,10 +311,3 @@ The following example demonstrates how to use the :mod:`!http.cookies` module. >>> print(C) Set-Cookie: number=7 Set-Cookie: string=seven - >>> import json - >>> C = cookies.SimpleCookie() - >>> C.load(f'cookies=7; mixins="{json.dumps({"chips": "dark chocolate"})}"; state=gooey') - >>> print(C) - Set-Cookie: cookies=7 - Set-Cookie: mixins="{"chips": "dark chocolate"}" - Set-Cookie: state=gooey diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 90d24bf96af..a687ee5115b 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -947,13 +947,6 @@ http.client (Contributed by Alexander Enrique Urieles Nieto in :gh:`131724`.) -http.cookies ------------- - -* Allow '``"``' double quotes in cookie values. - (Contributed by Nick Burns and Senthil Kumaran in :gh:`92936`.) - - http.server ----------- diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 660fec4f1be..5c5b14788dc 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -462,7 +462,7 @@ def OutputString(self, attrs=None): ( # Optional group: there may not be a value. \s*=\s* # Equal Sign (?P # Start of group 'val' - "(?:\\"|.)*?" # Any double-quoted string + "(?:[^\\"]|\\.)*" # Any double-quoted string | # or # Special case for "expires" attr (\w{3,6}day|\w{3}),\s # Day of the week or abbreviated day diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index cfcbc17bd6d..4884b07c95b 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -48,29 +48,6 @@ def test_basic(self): 'Set-Cookie: d=r', 'Set-Cookie: f=h' )) - }, - - # gh-92936: allow double quote in cookie values - { - 'data': 'cookie="{"key": "value"}"', - 'dict': {'cookie': '{"key": "value"}'}, - 'repr': "", - 'output': 'Set-Cookie: cookie="{"key": "value"}"', - }, - { - 'data': 'key="some value; surrounded by quotes"', - 'dict': {'key': 'some value; surrounded by quotes'}, - 'repr': "", - 'output': 'Set-Cookie: key="some value; surrounded by quotes"', - }, - { - 'data': 'session="user123"; preferences="{"theme": "dark"}"', - 'dict': {'session': 'user123', 'preferences': '{"theme": "dark"}'}, - 'repr': "", - 'output': '\n'.join(( - 'Set-Cookie: preferences="{"theme": "dark"}"', - 'Set-Cookie: session="user123"', - )) } ] From 51107387797887b91f0dd69090a30c88a7997aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurycy=20Paw=C5=82owski-Wiero=C5=84ski?= Date: Thu, 30 Apr 2026 23:18:07 +0200 Subject: [PATCH 720/775] gh-144319: Use transparent huge pages via `madvise(MADV_HUGEPAGE)` in pymalloc (#144353) --- Objects/obmalloc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index e2d5b012955..1809bd30451 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -665,6 +665,9 @@ _PyMem_ArenaAlloc(void *Py_UNUSED(ctx), size_t size) if (ptr == MAP_FAILED) return NULL; assert(ptr != NULL); +#ifdef MADV_HUGEPAGE + (void)madvise(ptr, size, MADV_HUGEPAGE); +#endif (void)_PyAnnotateMemoryMap(ptr, size, "cpython:pymalloc"); return ptr; #else From bdbb55c403d2ab6b4b0a3e994d21b623fee4a544 Mon Sep 17 00:00:00 2001 From: "R. David Murray" Date: Thu, 30 Apr 2026 17:41:43 -0400 Subject: [PATCH 721/775] gh-148518 fix index error in local part attribute (#148522) As part of fixing bpo-27931 code was introduced to get_bare_quoted_string that added an empty Terminal if the quoted string was empty. This isn't the best answer in terms of the parse tree; we really want the token list to be empty in that case. But having it be empty resulted in local_part raising the index error. We find that same problem if we try to parse an address consisting of a single dquote. By fixing local_part to not raise on an empty token list, we can have the bare_quoted_string code correctly return an empty token list for the empty string cases (two dquotes or a single dquote as the entire addrespec, at the end of a line). --- Lib/email/_header_value_parser.py | 7 ++-- Lib/test/test_email/test_headerregistry.py | 41 ++++++++++++++++++- ...-04-13-15-59-44.gh-issue-148518.RQdvsu.rst | 4 ++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-13-15-59-44.gh-issue-148518.RQdvsu.rst diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index f6b45e13271..a53903a197f 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -639,11 +639,11 @@ def local_part(self): for tok in self[0] + [DOT]: if tok.token_type == 'cfws': continue - if (last_is_tl and tok.token_type == 'dot' and + if (last_is_tl and tok.token_type == 'dot' and last and last[-1].token_type == 'cfws'): res[-1] = TokenList(last[:-1]) is_tl = isinstance(tok, TokenList) - if (is_tl and last.token_type == 'dot' and + if (is_tl and last.token_type == 'dot' and tok and tok[0].token_type == 'cfws'): res.append(TokenList(tok[1:])) else: @@ -1249,8 +1249,7 @@ def get_bare_quoted_string(value): bare_quoted_string = BareQuotedString() value = value[1:] if value and value[0] == '"': - token, value = get_qcontent(value) - bare_quoted_string.append(token) + return bare_quoted_string, value[1:] while value and value[0] != '"': if value[0] in WSP: token, value = get_fws(value) diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index c9c63951597..2aaa7d68ca3 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1271,12 +1271,12 @@ class TestAddressHeader(TestHeaderBase): 'example.com', None), - } - # XXX: Need many more examples, and in particular some with names in # trailing comments, which aren't currently handled. comments in # general are not handled yet. + } + def example_as_address(self, source, defects, decoded, display_name, addr_spec, username, domain, comment): h = self.make_header('sender', source) @@ -1294,6 +1294,43 @@ def example_as_address(self, source, defects, decoded, display_name, # XXX: we have no comment support yet. #self.assertEqual(a.comment, comment) + example_broken_header_params = { + + 'just_dquote': + ('"', + [errors.InvalidHeaderDefect]*2, + '<>', + '', + '<>', + '', + '', + ), + + } + + def example_broken_header_as_address( + self, + source, + defects, + decoded, + display_name, + addr_spec, + username, + domain, + ): + h = self.make_header('sender', source) + self.assertEqual(h, decoded) + self.assertDefectsEqual(h.defects, defects) + a = h.address + self.assertEqual(str(a), decoded) + self.assertEqual(len(h.groups), 1) + self.assertEqual([a], list(h.groups[0].addresses)) + self.assertEqual([a], list(h.addresses)) + self.assertEqual(a.display_name, display_name) + self.assertEqual(a.addr_spec, addr_spec) + self.assertEqual(a.username, username) + self.assertEqual(a.domain, domain) + def example_as_group(self, source, defects, decoded, display_name, addr_spec, username, domain, comment): source = 'foo: {};'.format(source) diff --git a/Misc/NEWS.d/next/Library/2026-04-13-15-59-44.gh-issue-148518.RQdvsu.rst b/Misc/NEWS.d/next/Library/2026-04-13-15-59-44.gh-issue-148518.RQdvsu.rst new file mode 100644 index 00000000000..994e4ad7446 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-13-15-59-44.gh-issue-148518.RQdvsu.rst @@ -0,0 +1,4 @@ +If an email containing an address header that ended in an open double quote +was parsed with a non-``compat32`` policy, accessing the ``username`` attribute +of the mailbox accessed through that header object would result in an +``IndexError``. It now correctly returns an empty string as the result. From c0e064003954142b4ba820dfe149f893227c4f11 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Thu, 30 Apr 2026 15:09:36 -0700 Subject: [PATCH 722/775] GH-146475: Block Apple Clang for building JIT stencils (#149188) --- .../next/Build/2026-04-30-08-43-47.gh-issue-146475.1cL4hX.rst | 2 ++ Tools/jit/_llvm.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Build/2026-04-30-08-43-47.gh-issue-146475.1cL4hX.rst diff --git a/Misc/NEWS.d/next/Build/2026-04-30-08-43-47.gh-issue-146475.1cL4hX.rst b/Misc/NEWS.d/next/Build/2026-04-30-08-43-47.gh-issue-146475.1cL4hX.rst new file mode 100644 index 00000000000..225c659393f --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-30-08-43-47.gh-issue-146475.1cL4hX.rst @@ -0,0 +1,2 @@ +Block Apple Clang from being used to build the JIT as it ships without +required LLVM tools. diff --git a/Tools/jit/_llvm.py b/Tools/jit/_llvm.py index 601752bf1f6..96cf5fc4714 100644 --- a/Tools/jit/_llvm.py +++ b/Tools/jit/_llvm.py @@ -69,7 +69,9 @@ async def _check_tool_version( name: str, llvm_version: str, *, echo: bool = False ) -> bool: output = await _run(name, ["--version"], echo=echo) - _llvm_version_pattern = re.compile(rf"version\s+{llvm_version}\.\d+\.\d+\S*\s+") + _llvm_version_pattern = re.compile( + rf"(? Date: Fri, 1 May 2026 13:32:57 +0800 Subject: [PATCH 723/775] gh-149173: Fix inverted PYTHON_BASIC_REPL environment check in _pyrepl_available() (#149174) --- Lib/pdb.py | 2 +- Lib/test/test_pdb.py | 10 ++++++++++ .../2026-04-30-14-21-26.gh-issue-149173.KJqZm0.rst | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-30-14-21-26.gh-issue-149173.KJqZm0.rst diff --git a/Lib/pdb.py b/Lib/pdb.py index c4bc0020646..4dd974b375c 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -376,7 +376,7 @@ def get_default_backend(): def _pyrepl_available(): """return whether pdb should use _pyrepl for input""" - if not os.getenv("PYTHON_BASIC_REPL"): + if os.getenv("PYTHON_BASIC_REPL"): CAN_USE_PYREPL = False else: try: diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index c5171f3388c..db900199755 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -4753,6 +4753,16 @@ def foo(self): stdout, stderr = self.run_pdb_script(script, commands) self.assertIn("The specified object 'C.foo' is not a function", stdout) + def test_pyrepl_available(self): + with patch.dict(os.environ, {"PYTHON_BASIC_REPL": "1"}): + self.assertFalse(pdb._pyrepl_available()) + + with patch.dict(os.environ, {}, clear=True): + mod = types.ModuleType("_pyrepl.main") + mod.CAN_USE_PYREPL = True + with patch.dict("sys.modules", {"_pyrepl.main": mod}): + self.assertTrue(pdb._pyrepl_available()) + class ChecklineTests(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS.d/next/Library/2026-04-30-14-21-26.gh-issue-149173.KJqZm0.rst b/Misc/NEWS.d/next/Library/2026-04-30-14-21-26.gh-issue-149173.KJqZm0.rst new file mode 100644 index 00000000000..019ab76b863 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-30-14-21-26.gh-issue-149173.KJqZm0.rst @@ -0,0 +1,2 @@ +Fix inverted :envvar:`PYTHON_BASIC_REPL` environment check in +``pdb._pyrepl_available``. From fcd53b68726e147a5604848573494a5fd8958b45 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 1 May 2026 09:41:28 +0200 Subject: [PATCH 724/775] gh-145497: Use same size of static_types array in all builds (GH-149139) When someone adds a new type but doesn't increment `_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES` or `_Py_MAX_MANAGED_STATIC_EXT_TYPES`, JIT tests fail, because JIT builds define an extra type. But the JIT tests don't necessarily run for the commit that causes the failure. As a workaround, use the same size for the array for all builds, potentially with an empty spot. --- Include/internal/pycore_interp_structs.h | 9 +++++++-- Objects/object.c | 11 ++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 349044116b9..cccfe3565db 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -525,8 +525,13 @@ struct _py_func_state { /****** type state *********/ /* For now we hard-code this to a value for which we are confident - all the static builtin types will fit (for all builds). */ -#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 203 + all the static builtin types will fit (for all builds). + If you add a new static type to the standard library, you may have to + update one of these numbers. + */ +#define _Py_NUM_MANAGED_PREINITIALIZED_TYPES 120 +#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES \ + (_Py_NUM_MANAGED_PREINITIALIZED_TYPES + 83) #define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10 #define _Py_MAX_MANAGED_STATIC_TYPES \ (_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES + _Py_MAX_MANAGED_STATIC_EXT_TYPES) diff --git a/Objects/object.c b/Objects/object.c index e6a764435bc..e0e26bb50d3 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2526,7 +2526,7 @@ extern PyTypeObject _PyMemoryIter_Type; extern PyTypeObject _PyPositionsIterator; extern PyTypeObject _Py_GenericAliasIterType; -static PyTypeObject* static_types[] = { +static PyTypeObject* static_types[_Py_NUM_MANAGED_PREINITIALIZED_TYPES] = { // The two most important base types: must be initialized first and // deallocated last. &PyBaseObject_Type, @@ -2644,6 +2644,9 @@ static PyTypeObject* static_types[] = { &_PyUnion_Type, #ifdef _Py_TIER2 &_PyUOpExecutor_Type, +#else + // The array should have the same size on all builds; see gh-149139 + NULL, #endif &_PyWeakref_CallableProxyType, &_PyWeakref_ProxyType, @@ -2668,6 +2671,9 @@ _PyTypes_InitTypes(PyInterpreterState *interp) // All other static types (unless initialized elsewhere) for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { PyTypeObject *type = static_types[i]; + if (type == NULL) { + continue; + } if (_PyStaticType_InitBuiltin(interp, type) < 0) { return _PyStatus_ERR("Can't initialize builtin type"); } @@ -2708,6 +2714,9 @@ _PyTypes_FiniTypes(PyInterpreterState *interp) // their base classes. for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) { PyTypeObject *type = static_types[i]; + if (type == NULL) { + continue; + } _PyStaticType_FiniBuiltin(interp, type); } } From f4f82f0ab6431837f4aca19c20fd1d25913b70c5 Mon Sep 17 00:00:00 2001 From: chemelnucfin <3982092+chemelnucfin@users.noreply.github.com> Date: Fri, 1 May 2026 01:11:53 -0700 Subject: [PATCH 725/775] gh-133560: Clarified `parser.md` doc for pegen parser issue in using the existing `Grammar/python.gram` file. (GH-139194) Co-authored-by: Petr Viktorin --- InternalDocs/parser.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/InternalDocs/parser.md b/InternalDocs/parser.md index 1d0ffe6d40d..1bb4cdea543 100644 --- a/InternalDocs/parser.md +++ b/InternalDocs/parser.md @@ -819,6 +819,13 @@ $ python -m pegen python ``` +> [!CAUTION] +> Python's grammar (the `Grammar/python.gram` file) is written for the +> C backend. To experiment, you will need to write a grammar +> without C-specific parts like actions and the trailer. +> See [#133560](https://github.com/python/cpython/issues/133560) +> and [#96424](https://github.com/python/cpython/issues/96424) for more information. + This will generate a file called `parse.py` in the same directory that you can use to parse some input: From 0102c1d9b98ce74be174838600410c9bd75239f4 Mon Sep 17 00:00:00 2001 From: Neko Asakura Date: Fri, 1 May 2026 19:35:31 +0800 Subject: [PATCH 726/775] gh-149204: add `_RROT_3` uop to reduce stack moves (GH-149205) --- Include/internal/pycore_uop_ids.h | 2049 +++++++++--------- Include/internal/pycore_uop_metadata.h | 21 + Python/bytecodes.c | 7 + Python/executor_cases.c.h | 96 + Python/optimizer_bytecodes.c | 7 + Python/optimizer_cases.c.h | 72 +- Tools/cases_generator/optimizer_generator.py | 3 +- 7 files changed, 1198 insertions(+), 1057 deletions(-) diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 9e54cb5f06a..bd1440a89bd 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -375,1040 +375,1045 @@ extern "C" { #define _RESUME_CHECK 601 #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE 602 -#define _SAVE_RETURN_OFFSET 603 -#define _SEND 604 -#define _SEND_GEN_FRAME 605 +#define _RROT_3 603 +#define _SAVE_RETURN_OFFSET 604 +#define _SEND 605 +#define _SEND_GEN_FRAME 606 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 606 -#define _SPILL_OR_RELOAD 607 -#define _START_EXECUTOR 608 -#define _STORE_ATTR 609 -#define _STORE_ATTR_INSTANCE_VALUE 610 -#define _STORE_ATTR_SLOT 611 -#define _STORE_ATTR_WITH_HINT 612 +#define _SET_UPDATE 607 +#define _SPILL_OR_RELOAD 608 +#define _START_EXECUTOR 609 +#define _STORE_ATTR 610 +#define _STORE_ATTR_INSTANCE_VALUE 611 +#define _STORE_ATTR_SLOT 612 +#define _STORE_ATTR_WITH_HINT 613 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 613 -#define _STORE_SUBSCR 614 -#define _STORE_SUBSCR_DICT 615 -#define _STORE_SUBSCR_DICT_KNOWN_HASH 616 -#define _STORE_SUBSCR_LIST_INT 617 -#define _SWAP 618 -#define _SWAP_2 619 -#define _SWAP_3 620 -#define _SWAP_FAST 621 -#define _SWAP_FAST_0 622 -#define _SWAP_FAST_1 623 -#define _SWAP_FAST_2 624 -#define _SWAP_FAST_3 625 -#define _SWAP_FAST_4 626 -#define _SWAP_FAST_5 627 -#define _SWAP_FAST_6 628 -#define _SWAP_FAST_7 629 -#define _TIER2_RESUME_CHECK 630 -#define _TO_BOOL 631 +#define _STORE_SLICE 614 +#define _STORE_SUBSCR 615 +#define _STORE_SUBSCR_DICT 616 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 617 +#define _STORE_SUBSCR_LIST_INT 618 +#define _SWAP 619 +#define _SWAP_2 620 +#define _SWAP_3 621 +#define _SWAP_FAST 622 +#define _SWAP_FAST_0 623 +#define _SWAP_FAST_1 624 +#define _SWAP_FAST_2 625 +#define _SWAP_FAST_3 626 +#define _SWAP_FAST_4 627 +#define _SWAP_FAST_5 628 +#define _SWAP_FAST_6 629 +#define _SWAP_FAST_7 630 +#define _TIER2_RESUME_CHECK 631 +#define _TO_BOOL 632 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 632 -#define _TO_BOOL_LIST 633 +#define _TO_BOOL_INT 633 +#define _TO_BOOL_LIST 634 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 634 +#define _TO_BOOL_STR 635 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 635 -#define _UNARY_NEGATIVE 636 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 637 +#define _UNARY_INVERT 636 +#define _UNARY_NEGATIVE 637 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 638 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 638 -#define _UNPACK_SEQUENCE_LIST 639 -#define _UNPACK_SEQUENCE_TUPLE 640 -#define _UNPACK_SEQUENCE_TWO_TUPLE 641 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 642 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 643 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 644 +#define _UNPACK_SEQUENCE 639 +#define _UNPACK_SEQUENCE_LIST 640 +#define _UNPACK_SEQUENCE_TUPLE 641 +#define _UNPACK_SEQUENCE_TWO_TUPLE 642 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 643 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 644 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 645 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 645 -#define MAX_UOP_ID 645 -#define _ALLOCATE_OBJECT_r00 646 -#define _BINARY_OP_r23 647 -#define _BINARY_OP_ADD_FLOAT_r03 648 -#define _BINARY_OP_ADD_FLOAT_r13 649 -#define _BINARY_OP_ADD_FLOAT_r23 650 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 651 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 652 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 653 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 654 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 655 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 656 -#define _BINARY_OP_ADD_INT_r03 657 -#define _BINARY_OP_ADD_INT_r13 658 -#define _BINARY_OP_ADD_INT_r23 659 -#define _BINARY_OP_ADD_INT_INPLACE_r03 660 -#define _BINARY_OP_ADD_INT_INPLACE_r13 661 -#define _BINARY_OP_ADD_INT_INPLACE_r23 662 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 663 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 664 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 665 -#define _BINARY_OP_ADD_UNICODE_r03 666 -#define _BINARY_OP_ADD_UNICODE_r13 667 -#define _BINARY_OP_ADD_UNICODE_r23 668 -#define _BINARY_OP_EXTEND_r23 669 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 670 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 671 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 672 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 673 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 674 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 675 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 676 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 677 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 678 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 679 -#define _BINARY_OP_MULTIPLY_INT_r03 680 -#define _BINARY_OP_MULTIPLY_INT_r13 681 -#define _BINARY_OP_MULTIPLY_INT_r23 682 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 683 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 684 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 685 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 686 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 687 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 688 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 689 -#define _BINARY_OP_SUBSCR_DICT_r23 690 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 691 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 692 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 693 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 694 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 695 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 696 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 697 -#define _BINARY_OP_SUBSCR_STR_INT_r23 698 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 699 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 700 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 701 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 702 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 703 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 704 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 705 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 706 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 707 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 708 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 709 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 710 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 711 -#define _BINARY_OP_SUBTRACT_INT_r03 712 -#define _BINARY_OP_SUBTRACT_INT_r13 713 -#define _BINARY_OP_SUBTRACT_INT_r23 714 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 715 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 716 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 717 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 718 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 719 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 720 -#define _BINARY_OP_TRUEDIV_FLOAT_r23 721 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 722 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 723 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 724 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 725 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 726 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 727 -#define _BINARY_SLICE_r31 728 -#define _BUILD_INTERPOLATION_r01 729 -#define _BUILD_LIST_r01 730 -#define _BUILD_MAP_r01 731 -#define _BUILD_SET_r01 732 -#define _BUILD_SLICE_r01 733 -#define _BUILD_STRING_r01 734 -#define _BUILD_TEMPLATE_r21 735 -#define _BUILD_TUPLE_r01 736 -#define _CALL_BUILTIN_CLASS_r00 737 -#define _CALL_BUILTIN_FAST_r00 738 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 739 -#define _CALL_BUILTIN_O_r03 740 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 741 -#define _CALL_INTRINSIC_1_r12 742 -#define _CALL_INTRINSIC_2_r23 743 -#define _CALL_ISINSTANCE_r31 744 -#define _CALL_KW_NON_PY_r11 745 -#define _CALL_LEN_r33 746 -#define _CALL_LIST_APPEND_r03 747 -#define _CALL_LIST_APPEND_r13 748 -#define _CALL_LIST_APPEND_r23 749 -#define _CALL_LIST_APPEND_r33 750 -#define _CALL_METHOD_DESCRIPTOR_FAST_r00 751 -#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 752 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 753 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 754 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r03 755 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 756 -#define _CALL_METHOD_DESCRIPTOR_O_r03 757 -#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 758 -#define _CALL_NON_PY_GENERAL_r01 759 -#define _CALL_STR_1_r32 760 -#define _CALL_TUPLE_1_r32 761 -#define _CALL_TYPE_1_r02 762 -#define _CALL_TYPE_1_r12 763 -#define _CALL_TYPE_1_r22 764 -#define _CALL_TYPE_1_r32 765 -#define _CHECK_ATTR_CLASS_r01 766 -#define _CHECK_ATTR_CLASS_r11 767 -#define _CHECK_ATTR_CLASS_r22 768 -#define _CHECK_ATTR_CLASS_r33 769 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 770 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 771 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 772 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 773 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 774 -#define _CHECK_EG_MATCH_r22 775 -#define _CHECK_EXC_MATCH_r22 776 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 777 -#define _CHECK_FUNCTION_VERSION_r00 778 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 779 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 780 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 781 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 782 -#define _CHECK_FUNCTION_VERSION_KW_r11 783 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 784 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 785 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 786 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 787 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 788 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 789 -#define _CHECK_IS_PY_CALLABLE_EX_r03 790 -#define _CHECK_IS_PY_CALLABLE_EX_r13 791 -#define _CHECK_IS_PY_CALLABLE_EX_r23 792 -#define _CHECK_IS_PY_CALLABLE_EX_r33 793 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 794 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 795 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 796 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 797 -#define _CHECK_METHOD_VERSION_r00 798 -#define _CHECK_METHOD_VERSION_KW_r11 799 -#define _CHECK_OBJECT_r00 800 -#define _CHECK_PEP_523_r00 801 -#define _CHECK_PEP_523_r11 802 -#define _CHECK_PEP_523_r22 803 -#define _CHECK_PEP_523_r33 804 -#define _CHECK_PERIODIC_r00 805 -#define _CHECK_PERIODIC_AT_END_r00 806 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 807 -#define _CHECK_RECURSION_LIMIT_r00 808 -#define _CHECK_RECURSION_LIMIT_r11 809 -#define _CHECK_RECURSION_LIMIT_r22 810 -#define _CHECK_RECURSION_LIMIT_r33 811 -#define _CHECK_RECURSION_REMAINING_r00 812 -#define _CHECK_RECURSION_REMAINING_r11 813 -#define _CHECK_RECURSION_REMAINING_r22 814 -#define _CHECK_RECURSION_REMAINING_r33 815 -#define _CHECK_STACK_SPACE_r00 816 -#define _CHECK_STACK_SPACE_OPERAND_r00 817 -#define _CHECK_STACK_SPACE_OPERAND_r11 818 -#define _CHECK_STACK_SPACE_OPERAND_r22 819 -#define _CHECK_STACK_SPACE_OPERAND_r33 820 -#define _CHECK_VALIDITY_r00 821 -#define _CHECK_VALIDITY_r11 822 -#define _CHECK_VALIDITY_r22 823 -#define _CHECK_VALIDITY_r33 824 -#define _COLD_DYNAMIC_EXIT_r00 825 -#define _COLD_EXIT_r00 826 -#define _COMPARE_OP_r21 827 -#define _COMPARE_OP_FLOAT_r03 828 -#define _COMPARE_OP_FLOAT_r13 829 -#define _COMPARE_OP_FLOAT_r23 830 -#define _COMPARE_OP_INT_r23 831 -#define _COMPARE_OP_STR_r23 832 -#define _CONTAINS_OP_r23 833 -#define _CONTAINS_OP_DICT_r23 834 -#define _CONTAINS_OP_SET_r23 835 -#define _CONVERT_VALUE_r11 836 -#define _COPY_r01 837 -#define _COPY_1_r02 838 -#define _COPY_1_r12 839 -#define _COPY_1_r23 840 -#define _COPY_2_r03 841 -#define _COPY_2_r13 842 -#define _COPY_2_r23 843 -#define _COPY_3_r03 844 -#define _COPY_3_r13 845 -#define _COPY_3_r23 846 -#define _COPY_3_r33 847 -#define _COPY_FREE_VARS_r00 848 -#define _COPY_FREE_VARS_r11 849 -#define _COPY_FREE_VARS_r22 850 -#define _COPY_FREE_VARS_r33 851 -#define _CREATE_INIT_FRAME_r01 852 -#define _DELETE_ATTR_r10 853 -#define _DELETE_DEREF_r00 854 -#define _DELETE_FAST_r00 855 -#define _DELETE_GLOBAL_r00 856 -#define _DELETE_NAME_r00 857 -#define _DELETE_SUBSCR_r20 858 -#define _DEOPT_r00 859 -#define _DEOPT_r10 860 -#define _DEOPT_r20 861 -#define _DEOPT_r30 862 -#define _DICT_MERGE_r11 863 -#define _DICT_UPDATE_r11 864 -#define _DO_CALL_r01 865 -#define _DO_CALL_FUNCTION_EX_r31 866 -#define _DO_CALL_KW_r11 867 -#define _DYNAMIC_EXIT_r00 868 -#define _DYNAMIC_EXIT_r10 869 -#define _DYNAMIC_EXIT_r20 870 -#define _DYNAMIC_EXIT_r30 871 -#define _END_FOR_r10 872 -#define _END_SEND_r31 873 -#define _ERROR_POP_N_r00 874 -#define _EXIT_INIT_CHECK_r10 875 -#define _EXIT_TRACE_r00 876 -#define _EXIT_TRACE_r10 877 -#define _EXIT_TRACE_r20 878 -#define _EXIT_TRACE_r30 879 -#define _EXPAND_METHOD_r00 880 -#define _EXPAND_METHOD_KW_r11 881 -#define _FATAL_ERROR_r00 882 -#define _FATAL_ERROR_r11 883 -#define _FATAL_ERROR_r22 884 -#define _FATAL_ERROR_r33 885 -#define _FORMAT_SIMPLE_r11 886 -#define _FORMAT_WITH_SPEC_r21 887 -#define _FOR_ITER_r23 888 -#define _FOR_ITER_GEN_FRAME_r03 889 -#define _FOR_ITER_GEN_FRAME_r13 890 -#define _FOR_ITER_GEN_FRAME_r23 891 -#define _FOR_ITER_TIER_TWO_r23 892 -#define _FOR_ITER_VIRTUAL_r23 893 -#define _FOR_ITER_VIRTUAL_TIER_TWO_r23 894 -#define _GET_AITER_r11 895 -#define _GET_ANEXT_r12 896 -#define _GET_AWAITABLE_r11 897 -#define _GET_ITER_r12 898 -#define _GET_ITER_TRAD_r12 899 -#define _GET_LEN_r12 900 -#define _GUARD_BINARY_OP_EXTEND_r22 901 -#define _GUARD_BINARY_OP_EXTEND_LHS_r02 902 -#define _GUARD_BINARY_OP_EXTEND_LHS_r12 903 -#define _GUARD_BINARY_OP_EXTEND_LHS_r22 904 -#define _GUARD_BINARY_OP_EXTEND_LHS_r33 905 -#define _GUARD_BINARY_OP_EXTEND_RHS_r02 906 -#define _GUARD_BINARY_OP_EXTEND_RHS_r12 907 -#define _GUARD_BINARY_OP_EXTEND_RHS_r22 908 -#define _GUARD_BINARY_OP_EXTEND_RHS_r33 909 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 910 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 911 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 912 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 913 -#define _GUARD_BIT_IS_SET_POP_r00 914 -#define _GUARD_BIT_IS_SET_POP_r10 915 -#define _GUARD_BIT_IS_SET_POP_r21 916 -#define _GUARD_BIT_IS_SET_POP_r32 917 -#define _GUARD_BIT_IS_SET_POP_4_r00 918 -#define _GUARD_BIT_IS_SET_POP_4_r10 919 -#define _GUARD_BIT_IS_SET_POP_4_r21 920 -#define _GUARD_BIT_IS_SET_POP_4_r32 921 -#define _GUARD_BIT_IS_SET_POP_5_r00 922 -#define _GUARD_BIT_IS_SET_POP_5_r10 923 -#define _GUARD_BIT_IS_SET_POP_5_r21 924 -#define _GUARD_BIT_IS_SET_POP_5_r32 925 -#define _GUARD_BIT_IS_SET_POP_6_r00 926 -#define _GUARD_BIT_IS_SET_POP_6_r10 927 -#define _GUARD_BIT_IS_SET_POP_6_r21 928 -#define _GUARD_BIT_IS_SET_POP_6_r32 929 -#define _GUARD_BIT_IS_SET_POP_7_r00 930 -#define _GUARD_BIT_IS_SET_POP_7_r10 931 -#define _GUARD_BIT_IS_SET_POP_7_r21 932 -#define _GUARD_BIT_IS_SET_POP_7_r32 933 -#define _GUARD_BIT_IS_UNSET_POP_r00 934 -#define _GUARD_BIT_IS_UNSET_POP_r10 935 -#define _GUARD_BIT_IS_UNSET_POP_r21 936 -#define _GUARD_BIT_IS_UNSET_POP_r32 937 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 938 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 939 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 940 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 941 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 942 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 943 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 944 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 945 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 946 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 947 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 948 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 949 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 950 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 951 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 952 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 953 -#define _GUARD_CALLABLE_BUILTIN_CLASS_r00 954 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 955 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 956 -#define _GUARD_CALLABLE_BUILTIN_O_r00 957 -#define _GUARD_CALLABLE_ISINSTANCE_r03 958 -#define _GUARD_CALLABLE_ISINSTANCE_r13 959 -#define _GUARD_CALLABLE_ISINSTANCE_r23 960 -#define _GUARD_CALLABLE_ISINSTANCE_r33 961 -#define _GUARD_CALLABLE_LEN_r03 962 -#define _GUARD_CALLABLE_LEN_r13 963 -#define _GUARD_CALLABLE_LEN_r23 964 -#define _GUARD_CALLABLE_LEN_r33 965 -#define _GUARD_CALLABLE_LIST_APPEND_r03 966 -#define _GUARD_CALLABLE_LIST_APPEND_r13 967 -#define _GUARD_CALLABLE_LIST_APPEND_r23 968 -#define _GUARD_CALLABLE_LIST_APPEND_r33 969 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 970 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 971 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 972 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 973 -#define _GUARD_CALLABLE_STR_1_r03 974 -#define _GUARD_CALLABLE_STR_1_r13 975 -#define _GUARD_CALLABLE_STR_1_r23 976 -#define _GUARD_CALLABLE_STR_1_r33 977 -#define _GUARD_CALLABLE_TUPLE_1_r03 978 -#define _GUARD_CALLABLE_TUPLE_1_r13 979 -#define _GUARD_CALLABLE_TUPLE_1_r23 980 -#define _GUARD_CALLABLE_TUPLE_1_r33 981 -#define _GUARD_CALLABLE_TYPE_1_r03 982 -#define _GUARD_CALLABLE_TYPE_1_r13 983 -#define _GUARD_CALLABLE_TYPE_1_r23 984 -#define _GUARD_CALLABLE_TYPE_1_r33 985 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 986 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 987 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 988 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 989 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 990 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 991 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 992 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 993 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 994 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 995 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 996 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 997 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 998 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 999 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 1000 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 1001 -#define _GUARD_DORV_NO_DICT_r01 1002 -#define _GUARD_DORV_NO_DICT_r11 1003 -#define _GUARD_DORV_NO_DICT_r22 1004 -#define _GUARD_DORV_NO_DICT_r33 1005 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 1006 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 1007 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 1008 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 1009 -#define _GUARD_GLOBALS_VERSION_r00 1010 -#define _GUARD_GLOBALS_VERSION_r11 1011 -#define _GUARD_GLOBALS_VERSION_r22 1012 -#define _GUARD_GLOBALS_VERSION_r33 1013 -#define _GUARD_IP_RETURN_GENERATOR_r00 1014 -#define _GUARD_IP_RETURN_GENERATOR_r11 1015 -#define _GUARD_IP_RETURN_GENERATOR_r22 1016 -#define _GUARD_IP_RETURN_GENERATOR_r33 1017 -#define _GUARD_IP_RETURN_VALUE_r00 1018 -#define _GUARD_IP_RETURN_VALUE_r11 1019 -#define _GUARD_IP_RETURN_VALUE_r22 1020 -#define _GUARD_IP_RETURN_VALUE_r33 1021 -#define _GUARD_IP_YIELD_VALUE_r00 1022 -#define _GUARD_IP_YIELD_VALUE_r11 1023 -#define _GUARD_IP_YIELD_VALUE_r22 1024 -#define _GUARD_IP_YIELD_VALUE_r33 1025 -#define _GUARD_IP__PUSH_FRAME_r00 1026 -#define _GUARD_IP__PUSH_FRAME_r11 1027 -#define _GUARD_IP__PUSH_FRAME_r22 1028 -#define _GUARD_IP__PUSH_FRAME_r33 1029 -#define _GUARD_IS_FALSE_POP_r00 1030 -#define _GUARD_IS_FALSE_POP_r10 1031 -#define _GUARD_IS_FALSE_POP_r21 1032 -#define _GUARD_IS_FALSE_POP_r32 1033 -#define _GUARD_IS_NONE_POP_r00 1034 -#define _GUARD_IS_NONE_POP_r10 1035 -#define _GUARD_IS_NONE_POP_r21 1036 -#define _GUARD_IS_NONE_POP_r32 1037 -#define _GUARD_IS_NOT_NONE_POP_r10 1038 -#define _GUARD_IS_TRUE_POP_r00 1039 -#define _GUARD_IS_TRUE_POP_r10 1040 -#define _GUARD_IS_TRUE_POP_r21 1041 -#define _GUARD_IS_TRUE_POP_r32 1042 -#define _GUARD_ITERATOR_r01 1043 -#define _GUARD_ITERATOR_r11 1044 -#define _GUARD_ITERATOR_r22 1045 -#define _GUARD_ITERATOR_r33 1046 -#define _GUARD_ITER_VIRTUAL_r01 1047 -#define _GUARD_ITER_VIRTUAL_r11 1048 -#define _GUARD_ITER_VIRTUAL_r22 1049 -#define _GUARD_ITER_VIRTUAL_r33 1050 -#define _GUARD_KEYS_VERSION_r01 1051 -#define _GUARD_KEYS_VERSION_r11 1052 -#define _GUARD_KEYS_VERSION_r22 1053 -#define _GUARD_KEYS_VERSION_r33 1054 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r03 1055 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r13 1056 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r23 1057 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r33 1058 -#define _GUARD_NOS_ANY_DICT_r02 1059 -#define _GUARD_NOS_ANY_DICT_r12 1060 -#define _GUARD_NOS_ANY_DICT_r22 1061 -#define _GUARD_NOS_ANY_DICT_r33 1062 -#define _GUARD_NOS_COMPACT_ASCII_r02 1063 -#define _GUARD_NOS_COMPACT_ASCII_r12 1064 -#define _GUARD_NOS_COMPACT_ASCII_r22 1065 -#define _GUARD_NOS_COMPACT_ASCII_r33 1066 -#define _GUARD_NOS_DICT_r02 1067 -#define _GUARD_NOS_DICT_r12 1068 -#define _GUARD_NOS_DICT_r22 1069 -#define _GUARD_NOS_DICT_r33 1070 -#define _GUARD_NOS_FLOAT_r02 1071 -#define _GUARD_NOS_FLOAT_r12 1072 -#define _GUARD_NOS_FLOAT_r22 1073 -#define _GUARD_NOS_FLOAT_r33 1074 -#define _GUARD_NOS_INT_r02 1075 -#define _GUARD_NOS_INT_r12 1076 -#define _GUARD_NOS_INT_r22 1077 -#define _GUARD_NOS_INT_r33 1078 -#define _GUARD_NOS_ITER_VIRTUAL_r02 1079 -#define _GUARD_NOS_ITER_VIRTUAL_r12 1080 -#define _GUARD_NOS_ITER_VIRTUAL_r22 1081 -#define _GUARD_NOS_ITER_VIRTUAL_r33 1082 -#define _GUARD_NOS_LIST_r02 1083 -#define _GUARD_NOS_LIST_r12 1084 -#define _GUARD_NOS_LIST_r22 1085 -#define _GUARD_NOS_LIST_r33 1086 -#define _GUARD_NOS_NOT_NULL_r02 1087 -#define _GUARD_NOS_NOT_NULL_r12 1088 -#define _GUARD_NOS_NOT_NULL_r22 1089 -#define _GUARD_NOS_NOT_NULL_r33 1090 -#define _GUARD_NOS_NULL_r02 1091 -#define _GUARD_NOS_NULL_r12 1092 -#define _GUARD_NOS_NULL_r22 1093 -#define _GUARD_NOS_NULL_r33 1094 -#define _GUARD_NOS_OVERFLOWED_r02 1095 -#define _GUARD_NOS_OVERFLOWED_r12 1096 -#define _GUARD_NOS_OVERFLOWED_r22 1097 -#define _GUARD_NOS_OVERFLOWED_r33 1098 -#define _GUARD_NOS_TUPLE_r02 1099 -#define _GUARD_NOS_TUPLE_r12 1100 -#define _GUARD_NOS_TUPLE_r22 1101 -#define _GUARD_NOS_TUPLE_r33 1102 -#define _GUARD_NOS_TYPE_VERSION_r02 1103 -#define _GUARD_NOS_TYPE_VERSION_r12 1104 -#define _GUARD_NOS_TYPE_VERSION_r22 1105 -#define _GUARD_NOS_TYPE_VERSION_r33 1106 -#define _GUARD_NOS_UNICODE_r02 1107 -#define _GUARD_NOS_UNICODE_r12 1108 -#define _GUARD_NOS_UNICODE_r22 1109 -#define _GUARD_NOS_UNICODE_r33 1110 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1111 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1112 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1113 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1114 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1115 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1116 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1117 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1118 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1119 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1120 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1121 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1122 -#define _GUARD_THIRD_NULL_r03 1123 -#define _GUARD_THIRD_NULL_r13 1124 -#define _GUARD_THIRD_NULL_r23 1125 -#define _GUARD_THIRD_NULL_r33 1126 -#define _GUARD_TOS_ANY_DICT_r01 1127 -#define _GUARD_TOS_ANY_DICT_r11 1128 -#define _GUARD_TOS_ANY_DICT_r22 1129 -#define _GUARD_TOS_ANY_DICT_r33 1130 -#define _GUARD_TOS_ANY_SET_r01 1131 -#define _GUARD_TOS_ANY_SET_r11 1132 -#define _GUARD_TOS_ANY_SET_r22 1133 -#define _GUARD_TOS_ANY_SET_r33 1134 -#define _GUARD_TOS_DICT_r01 1135 -#define _GUARD_TOS_DICT_r11 1136 -#define _GUARD_TOS_DICT_r22 1137 -#define _GUARD_TOS_DICT_r33 1138 -#define _GUARD_TOS_FLOAT_r01 1139 -#define _GUARD_TOS_FLOAT_r11 1140 -#define _GUARD_TOS_FLOAT_r22 1141 -#define _GUARD_TOS_FLOAT_r33 1142 -#define _GUARD_TOS_FROZENDICT_r01 1143 -#define _GUARD_TOS_FROZENDICT_r11 1144 -#define _GUARD_TOS_FROZENDICT_r22 1145 -#define _GUARD_TOS_FROZENDICT_r33 1146 -#define _GUARD_TOS_FROZENSET_r01 1147 -#define _GUARD_TOS_FROZENSET_r11 1148 -#define _GUARD_TOS_FROZENSET_r22 1149 -#define _GUARD_TOS_FROZENSET_r33 1150 -#define _GUARD_TOS_INT_r01 1151 -#define _GUARD_TOS_INT_r11 1152 -#define _GUARD_TOS_INT_r22 1153 -#define _GUARD_TOS_INT_r33 1154 -#define _GUARD_TOS_LIST_r01 1155 -#define _GUARD_TOS_LIST_r11 1156 -#define _GUARD_TOS_LIST_r22 1157 -#define _GUARD_TOS_LIST_r33 1158 -#define _GUARD_TOS_OVERFLOWED_r01 1159 -#define _GUARD_TOS_OVERFLOWED_r11 1160 -#define _GUARD_TOS_OVERFLOWED_r22 1161 -#define _GUARD_TOS_OVERFLOWED_r33 1162 -#define _GUARD_TOS_SET_r01 1163 -#define _GUARD_TOS_SET_r11 1164 -#define _GUARD_TOS_SET_r22 1165 -#define _GUARD_TOS_SET_r33 1166 -#define _GUARD_TOS_SLICE_r01 1167 -#define _GUARD_TOS_SLICE_r11 1168 -#define _GUARD_TOS_SLICE_r22 1169 -#define _GUARD_TOS_SLICE_r33 1170 -#define _GUARD_TOS_TUPLE_r01 1171 -#define _GUARD_TOS_TUPLE_r11 1172 -#define _GUARD_TOS_TUPLE_r22 1173 -#define _GUARD_TOS_TUPLE_r33 1174 -#define _GUARD_TOS_UNICODE_r01 1175 -#define _GUARD_TOS_UNICODE_r11 1176 -#define _GUARD_TOS_UNICODE_r22 1177 -#define _GUARD_TOS_UNICODE_r33 1178 -#define _GUARD_TYPE_r01 1179 -#define _GUARD_TYPE_r11 1180 -#define _GUARD_TYPE_r22 1181 -#define _GUARD_TYPE_r33 1182 -#define _GUARD_TYPE_VERSION_r01 1183 -#define _GUARD_TYPE_VERSION_r11 1184 -#define _GUARD_TYPE_VERSION_r22 1185 -#define _GUARD_TYPE_VERSION_r33 1186 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1187 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1188 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1189 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1190 -#define _HANDLE_PENDING_AND_DEOPT_r00 1191 -#define _HANDLE_PENDING_AND_DEOPT_r10 1192 -#define _HANDLE_PENDING_AND_DEOPT_r20 1193 -#define _HANDLE_PENDING_AND_DEOPT_r30 1194 -#define _IMPORT_FROM_r12 1195 -#define _IMPORT_NAME_r21 1196 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1197 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1198 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1199 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1200 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1201 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1202 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1203 -#define _INSERT_NULL_r10 1204 -#define _INSTRUMENTED_FOR_ITER_r23 1205 -#define _INSTRUMENTED_INSTRUCTION_r00 1206 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1207 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1208 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1209 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1210 -#define _INSTRUMENTED_LINE_r00 1211 -#define _INSTRUMENTED_NOT_TAKEN_r00 1212 -#define _INSTRUMENTED_NOT_TAKEN_r11 1213 -#define _INSTRUMENTED_NOT_TAKEN_r22 1214 -#define _INSTRUMENTED_NOT_TAKEN_r33 1215 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1216 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1217 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1218 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1219 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1220 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1221 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1222 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1223 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1224 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1225 -#define _IS_NONE_r11 1226 -#define _IS_OP_r03 1227 -#define _IS_OP_r13 1228 -#define _IS_OP_r23 1229 -#define _ITER_CHECK_LIST_r02 1230 -#define _ITER_CHECK_LIST_r12 1231 -#define _ITER_CHECK_LIST_r22 1232 -#define _ITER_CHECK_LIST_r33 1233 -#define _ITER_CHECK_RANGE_r02 1234 -#define _ITER_CHECK_RANGE_r12 1235 -#define _ITER_CHECK_RANGE_r22 1236 -#define _ITER_CHECK_RANGE_r33 1237 -#define _ITER_CHECK_TUPLE_r02 1238 -#define _ITER_CHECK_TUPLE_r12 1239 -#define _ITER_CHECK_TUPLE_r22 1240 -#define _ITER_CHECK_TUPLE_r33 1241 -#define _ITER_JUMP_LIST_r02 1242 -#define _ITER_JUMP_LIST_r12 1243 -#define _ITER_JUMP_LIST_r22 1244 -#define _ITER_JUMP_LIST_r33 1245 -#define _ITER_JUMP_RANGE_r02 1246 -#define _ITER_JUMP_RANGE_r12 1247 -#define _ITER_JUMP_RANGE_r22 1248 -#define _ITER_JUMP_RANGE_r33 1249 -#define _ITER_JUMP_TUPLE_r02 1250 -#define _ITER_JUMP_TUPLE_r12 1251 -#define _ITER_JUMP_TUPLE_r22 1252 -#define _ITER_JUMP_TUPLE_r33 1253 -#define _ITER_NEXT_LIST_r23 1254 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1255 -#define _ITER_NEXT_RANGE_r03 1256 -#define _ITER_NEXT_RANGE_r13 1257 -#define _ITER_NEXT_RANGE_r23 1258 -#define _ITER_NEXT_TUPLE_r03 1259 -#define _ITER_NEXT_TUPLE_r13 1260 -#define _ITER_NEXT_TUPLE_r23 1261 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1262 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1263 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1264 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1265 -#define _JUMP_TO_TOP_r00 1266 -#define _LIST_APPEND_r10 1267 -#define _LIST_EXTEND_r11 1268 -#define _LOAD_ATTR_r10 1269 -#define _LOAD_ATTR_CLASS_r11 1270 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 1271 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1272 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1273 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1274 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1275 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1276 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1277 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1278 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1279 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1280 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1281 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1282 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1283 -#define _LOAD_ATTR_MODULE_r12 1284 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1285 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1286 -#define _LOAD_ATTR_PROPERTY_FRAME_r01 1287 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1288 -#define _LOAD_ATTR_PROPERTY_FRAME_r22 1289 -#define _LOAD_ATTR_PROPERTY_FRAME_r33 1290 -#define _LOAD_ATTR_SLOT_r02 1291 -#define _LOAD_ATTR_SLOT_r12 1292 -#define _LOAD_ATTR_SLOT_r23 1293 -#define _LOAD_ATTR_WITH_HINT_r12 1294 -#define _LOAD_BUILD_CLASS_r01 1295 -#define _LOAD_BYTECODE_r00 1296 -#define _LOAD_COMMON_CONSTANT_r01 1297 -#define _LOAD_COMMON_CONSTANT_r12 1298 -#define _LOAD_COMMON_CONSTANT_r23 1299 -#define _LOAD_CONST_r01 1300 -#define _LOAD_CONST_r12 1301 -#define _LOAD_CONST_r23 1302 -#define _LOAD_CONST_INLINE_r01 1303 -#define _LOAD_CONST_INLINE_r12 1304 -#define _LOAD_CONST_INLINE_r23 1305 -#define _LOAD_CONST_INLINE_BORROW_r01 1306 -#define _LOAD_CONST_INLINE_BORROW_r12 1307 -#define _LOAD_CONST_INLINE_BORROW_r23 1308 -#define _LOAD_DEREF_r01 1309 -#define _LOAD_FAST_r01 1310 -#define _LOAD_FAST_r12 1311 -#define _LOAD_FAST_r23 1312 -#define _LOAD_FAST_0_r01 1313 -#define _LOAD_FAST_0_r12 1314 -#define _LOAD_FAST_0_r23 1315 -#define _LOAD_FAST_1_r01 1316 -#define _LOAD_FAST_1_r12 1317 -#define _LOAD_FAST_1_r23 1318 -#define _LOAD_FAST_2_r01 1319 -#define _LOAD_FAST_2_r12 1320 -#define _LOAD_FAST_2_r23 1321 -#define _LOAD_FAST_3_r01 1322 -#define _LOAD_FAST_3_r12 1323 -#define _LOAD_FAST_3_r23 1324 -#define _LOAD_FAST_4_r01 1325 -#define _LOAD_FAST_4_r12 1326 -#define _LOAD_FAST_4_r23 1327 -#define _LOAD_FAST_5_r01 1328 -#define _LOAD_FAST_5_r12 1329 -#define _LOAD_FAST_5_r23 1330 -#define _LOAD_FAST_6_r01 1331 -#define _LOAD_FAST_6_r12 1332 -#define _LOAD_FAST_6_r23 1333 -#define _LOAD_FAST_7_r01 1334 -#define _LOAD_FAST_7_r12 1335 -#define _LOAD_FAST_7_r23 1336 -#define _LOAD_FAST_AND_CLEAR_r01 1337 -#define _LOAD_FAST_AND_CLEAR_r12 1338 -#define _LOAD_FAST_AND_CLEAR_r23 1339 -#define _LOAD_FAST_BORROW_r01 1340 -#define _LOAD_FAST_BORROW_r12 1341 -#define _LOAD_FAST_BORROW_r23 1342 -#define _LOAD_FAST_BORROW_0_r01 1343 -#define _LOAD_FAST_BORROW_0_r12 1344 -#define _LOAD_FAST_BORROW_0_r23 1345 -#define _LOAD_FAST_BORROW_1_r01 1346 -#define _LOAD_FAST_BORROW_1_r12 1347 -#define _LOAD_FAST_BORROW_1_r23 1348 -#define _LOAD_FAST_BORROW_2_r01 1349 -#define _LOAD_FAST_BORROW_2_r12 1350 -#define _LOAD_FAST_BORROW_2_r23 1351 -#define _LOAD_FAST_BORROW_3_r01 1352 -#define _LOAD_FAST_BORROW_3_r12 1353 -#define _LOAD_FAST_BORROW_3_r23 1354 -#define _LOAD_FAST_BORROW_4_r01 1355 -#define _LOAD_FAST_BORROW_4_r12 1356 -#define _LOAD_FAST_BORROW_4_r23 1357 -#define _LOAD_FAST_BORROW_5_r01 1358 -#define _LOAD_FAST_BORROW_5_r12 1359 -#define _LOAD_FAST_BORROW_5_r23 1360 -#define _LOAD_FAST_BORROW_6_r01 1361 -#define _LOAD_FAST_BORROW_6_r12 1362 -#define _LOAD_FAST_BORROW_6_r23 1363 -#define _LOAD_FAST_BORROW_7_r01 1364 -#define _LOAD_FAST_BORROW_7_r12 1365 -#define _LOAD_FAST_BORROW_7_r23 1366 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1367 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1368 -#define _LOAD_FAST_CHECK_r01 1369 -#define _LOAD_FAST_CHECK_r12 1370 -#define _LOAD_FAST_CHECK_r23 1371 -#define _LOAD_FAST_LOAD_FAST_r02 1372 -#define _LOAD_FAST_LOAD_FAST_r13 1373 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1374 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1375 -#define _LOAD_GLOBAL_r00 1376 -#define _LOAD_GLOBAL_BUILTINS_r01 1377 -#define _LOAD_GLOBAL_MODULE_r01 1378 -#define _LOAD_LOCALS_r01 1379 -#define _LOAD_LOCALS_r12 1380 -#define _LOAD_LOCALS_r23 1381 -#define _LOAD_NAME_r01 1382 -#define _LOAD_SMALL_INT_r01 1383 -#define _LOAD_SMALL_INT_r12 1384 -#define _LOAD_SMALL_INT_r23 1385 -#define _LOAD_SMALL_INT_0_r01 1386 -#define _LOAD_SMALL_INT_0_r12 1387 -#define _LOAD_SMALL_INT_0_r23 1388 -#define _LOAD_SMALL_INT_1_r01 1389 -#define _LOAD_SMALL_INT_1_r12 1390 -#define _LOAD_SMALL_INT_1_r23 1391 -#define _LOAD_SMALL_INT_2_r01 1392 -#define _LOAD_SMALL_INT_2_r12 1393 -#define _LOAD_SMALL_INT_2_r23 1394 -#define _LOAD_SMALL_INT_3_r01 1395 -#define _LOAD_SMALL_INT_3_r12 1396 -#define _LOAD_SMALL_INT_3_r23 1397 -#define _LOAD_SPECIAL_r00 1398 -#define _LOAD_SUPER_ATTR_ATTR_r31 1399 -#define _LOAD_SUPER_ATTR_METHOD_r32 1400 -#define _LOCK_OBJECT_r01 1401 -#define _LOCK_OBJECT_r11 1402 -#define _LOCK_OBJECT_r22 1403 -#define _LOCK_OBJECT_r33 1404 -#define _MAKE_CALLARGS_A_TUPLE_r33 1405 -#define _MAKE_CELL_r00 1406 -#define _MAKE_FUNCTION_r12 1407 -#define _MAKE_HEAP_SAFE_r01 1408 -#define _MAKE_HEAP_SAFE_r11 1409 -#define _MAKE_HEAP_SAFE_r22 1410 -#define _MAKE_HEAP_SAFE_r33 1411 -#define _MAKE_WARM_r00 1412 -#define _MAKE_WARM_r11 1413 -#define _MAKE_WARM_r22 1414 -#define _MAKE_WARM_r33 1415 -#define _MAP_ADD_r20 1416 -#define _MATCH_CLASS_r33 1417 -#define _MATCH_KEYS_r23 1418 -#define _MATCH_MAPPING_r02 1419 -#define _MATCH_MAPPING_r12 1420 -#define _MATCH_MAPPING_r23 1421 -#define _MATCH_SEQUENCE_r02 1422 -#define _MATCH_SEQUENCE_r12 1423 -#define _MATCH_SEQUENCE_r23 1424 -#define _MAYBE_EXPAND_METHOD_r00 1425 -#define _MAYBE_EXPAND_METHOD_KW_r11 1426 -#define _MONITOR_CALL_r00 1427 -#define _MONITOR_CALL_KW_r11 1428 -#define _MONITOR_JUMP_BACKWARD_r00 1429 -#define _MONITOR_JUMP_BACKWARD_r11 1430 -#define _MONITOR_JUMP_BACKWARD_r22 1431 -#define _MONITOR_JUMP_BACKWARD_r33 1432 -#define _MONITOR_RESUME_r00 1433 -#define _NOP_r00 1434 -#define _NOP_r11 1435 -#define _NOP_r22 1436 -#define _NOP_r33 1437 -#define _POP_EXCEPT_r10 1438 -#define _POP_ITER_r20 1439 -#define _POP_JUMP_IF_FALSE_r00 1440 -#define _POP_JUMP_IF_FALSE_r10 1441 -#define _POP_JUMP_IF_FALSE_r21 1442 -#define _POP_JUMP_IF_FALSE_r32 1443 -#define _POP_JUMP_IF_TRUE_r00 1444 -#define _POP_JUMP_IF_TRUE_r10 1445 -#define _POP_JUMP_IF_TRUE_r21 1446 -#define _POP_JUMP_IF_TRUE_r32 1447 -#define _POP_TOP_r10 1448 -#define _POP_TOP_FLOAT_r00 1449 -#define _POP_TOP_FLOAT_r10 1450 -#define _POP_TOP_FLOAT_r21 1451 -#define _POP_TOP_FLOAT_r32 1452 -#define _POP_TOP_INT_r00 1453 -#define _POP_TOP_INT_r10 1454 -#define _POP_TOP_INT_r21 1455 -#define _POP_TOP_INT_r32 1456 -#define _POP_TOP_NOP_r00 1457 -#define _POP_TOP_NOP_r10 1458 -#define _POP_TOP_NOP_r21 1459 -#define _POP_TOP_NOP_r32 1460 -#define _POP_TOP_OPARG_r00 1461 -#define _POP_TOP_UNICODE_r00 1462 -#define _POP_TOP_UNICODE_r10 1463 -#define _POP_TOP_UNICODE_r21 1464 -#define _POP_TOP_UNICODE_r32 1465 -#define _PUSH_EXC_INFO_r02 1466 -#define _PUSH_EXC_INFO_r12 1467 -#define _PUSH_EXC_INFO_r23 1468 -#define _PUSH_FRAME_r10 1469 -#define _PUSH_NULL_r01 1470 -#define _PUSH_NULL_r12 1471 -#define _PUSH_NULL_r23 1472 -#define _PUSH_NULL_CONDITIONAL_r00 1473 -#define _PUSH_TAGGED_ZERO_r01 1474 -#define _PUSH_TAGGED_ZERO_r12 1475 -#define _PUSH_TAGGED_ZERO_r23 1476 -#define _PY_FRAME_EX_r31 1477 -#define _PY_FRAME_GENERAL_r01 1478 -#define _PY_FRAME_KW_r11 1479 -#define _REPLACE_WITH_TRUE_r02 1480 -#define _REPLACE_WITH_TRUE_r12 1481 -#define _REPLACE_WITH_TRUE_r23 1482 -#define _RESUME_CHECK_r00 1483 -#define _RESUME_CHECK_r11 1484 -#define _RESUME_CHECK_r22 1485 -#define _RESUME_CHECK_r33 1486 -#define _RETURN_GENERATOR_r01 1487 -#define _RETURN_VALUE_r11 1488 -#define _SAVE_RETURN_OFFSET_r00 1489 -#define _SAVE_RETURN_OFFSET_r11 1490 -#define _SAVE_RETURN_OFFSET_r22 1491 -#define _SAVE_RETURN_OFFSET_r33 1492 -#define _SEND_r33 1493 -#define _SEND_GEN_FRAME_r33 1494 -#define _SETUP_ANNOTATIONS_r00 1495 -#define _SET_ADD_r10 1496 -#define _SET_FUNCTION_ATTRIBUTE_r01 1497 -#define _SET_FUNCTION_ATTRIBUTE_r11 1498 -#define _SET_FUNCTION_ATTRIBUTE_r21 1499 -#define _SET_FUNCTION_ATTRIBUTE_r32 1500 -#define _SET_IP_r00 1501 -#define _SET_IP_r11 1502 -#define _SET_IP_r22 1503 -#define _SET_IP_r33 1504 -#define _SET_UPDATE_r11 1505 -#define _SPILL_OR_RELOAD_r01 1506 -#define _SPILL_OR_RELOAD_r02 1507 -#define _SPILL_OR_RELOAD_r03 1508 -#define _SPILL_OR_RELOAD_r10 1509 -#define _SPILL_OR_RELOAD_r12 1510 -#define _SPILL_OR_RELOAD_r13 1511 -#define _SPILL_OR_RELOAD_r20 1512 -#define _SPILL_OR_RELOAD_r21 1513 -#define _SPILL_OR_RELOAD_r23 1514 -#define _SPILL_OR_RELOAD_r30 1515 -#define _SPILL_OR_RELOAD_r31 1516 -#define _SPILL_OR_RELOAD_r32 1517 -#define _START_EXECUTOR_r00 1518 -#define _STORE_ATTR_r20 1519 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1520 -#define _STORE_ATTR_SLOT_r21 1521 -#define _STORE_ATTR_WITH_HINT_r21 1522 -#define _STORE_DEREF_r10 1523 -#define _STORE_FAST_LOAD_FAST_r11 1524 -#define _STORE_FAST_STORE_FAST_r20 1525 -#define _STORE_GLOBAL_r10 1526 -#define _STORE_NAME_r10 1527 -#define _STORE_SLICE_r30 1528 -#define _STORE_SUBSCR_r30 1529 -#define _STORE_SUBSCR_DICT_r31 1530 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1531 -#define _STORE_SUBSCR_LIST_INT_r32 1532 -#define _SWAP_r11 1533 -#define _SWAP_2_r02 1534 -#define _SWAP_2_r12 1535 -#define _SWAP_2_r22 1536 -#define _SWAP_2_r33 1537 -#define _SWAP_3_r03 1538 -#define _SWAP_3_r13 1539 -#define _SWAP_3_r23 1540 -#define _SWAP_3_r33 1541 -#define _SWAP_FAST_r01 1542 -#define _SWAP_FAST_r11 1543 -#define _SWAP_FAST_r22 1544 -#define _SWAP_FAST_r33 1545 -#define _SWAP_FAST_0_r01 1546 -#define _SWAP_FAST_0_r11 1547 -#define _SWAP_FAST_0_r22 1548 -#define _SWAP_FAST_0_r33 1549 -#define _SWAP_FAST_1_r01 1550 -#define _SWAP_FAST_1_r11 1551 -#define _SWAP_FAST_1_r22 1552 -#define _SWAP_FAST_1_r33 1553 -#define _SWAP_FAST_2_r01 1554 -#define _SWAP_FAST_2_r11 1555 -#define _SWAP_FAST_2_r22 1556 -#define _SWAP_FAST_2_r33 1557 -#define _SWAP_FAST_3_r01 1558 -#define _SWAP_FAST_3_r11 1559 -#define _SWAP_FAST_3_r22 1560 -#define _SWAP_FAST_3_r33 1561 -#define _SWAP_FAST_4_r01 1562 -#define _SWAP_FAST_4_r11 1563 -#define _SWAP_FAST_4_r22 1564 -#define _SWAP_FAST_4_r33 1565 -#define _SWAP_FAST_5_r01 1566 -#define _SWAP_FAST_5_r11 1567 -#define _SWAP_FAST_5_r22 1568 -#define _SWAP_FAST_5_r33 1569 -#define _SWAP_FAST_6_r01 1570 -#define _SWAP_FAST_6_r11 1571 -#define _SWAP_FAST_6_r22 1572 -#define _SWAP_FAST_6_r33 1573 -#define _SWAP_FAST_7_r01 1574 -#define _SWAP_FAST_7_r11 1575 -#define _SWAP_FAST_7_r22 1576 -#define _SWAP_FAST_7_r33 1577 -#define _TIER2_RESUME_CHECK_r00 1578 -#define _TIER2_RESUME_CHECK_r11 1579 -#define _TIER2_RESUME_CHECK_r22 1580 -#define _TIER2_RESUME_CHECK_r33 1581 -#define _TO_BOOL_r11 1582 -#define _TO_BOOL_BOOL_r01 1583 -#define _TO_BOOL_BOOL_r11 1584 -#define _TO_BOOL_BOOL_r22 1585 -#define _TO_BOOL_BOOL_r33 1586 -#define _TO_BOOL_INT_r02 1587 -#define _TO_BOOL_INT_r12 1588 -#define _TO_BOOL_INT_r23 1589 -#define _TO_BOOL_LIST_r02 1590 -#define _TO_BOOL_LIST_r12 1591 -#define _TO_BOOL_LIST_r23 1592 -#define _TO_BOOL_NONE_r01 1593 -#define _TO_BOOL_NONE_r11 1594 -#define _TO_BOOL_NONE_r22 1595 -#define _TO_BOOL_NONE_r33 1596 -#define _TO_BOOL_STR_r02 1597 -#define _TO_BOOL_STR_r12 1598 -#define _TO_BOOL_STR_r23 1599 -#define _TRACE_RECORD_r00 1600 -#define _UNARY_INVERT_r12 1601 -#define _UNARY_NEGATIVE_r12 1602 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1603 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1604 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1605 -#define _UNARY_NOT_r01 1606 -#define _UNARY_NOT_r11 1607 -#define _UNARY_NOT_r22 1608 -#define _UNARY_NOT_r33 1609 -#define _UNPACK_EX_r10 1610 -#define _UNPACK_SEQUENCE_r10 1611 -#define _UNPACK_SEQUENCE_LIST_r10 1612 -#define _UNPACK_SEQUENCE_TUPLE_r10 1613 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1614 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1615 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1616 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1617 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1618 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1619 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1620 -#define _WITH_EXCEPT_START_r33 1621 -#define _YIELD_VALUE_r11 1622 -#define MAX_UOP_REGS_ID 1622 +#define _YIELD_VALUE 646 +#define MAX_UOP_ID 646 +#define _ALLOCATE_OBJECT_r00 647 +#define _BINARY_OP_r23 648 +#define _BINARY_OP_ADD_FLOAT_r03 649 +#define _BINARY_OP_ADD_FLOAT_r13 650 +#define _BINARY_OP_ADD_FLOAT_r23 651 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 652 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 653 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 654 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 655 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 656 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 657 +#define _BINARY_OP_ADD_INT_r03 658 +#define _BINARY_OP_ADD_INT_r13 659 +#define _BINARY_OP_ADD_INT_r23 660 +#define _BINARY_OP_ADD_INT_INPLACE_r03 661 +#define _BINARY_OP_ADD_INT_INPLACE_r13 662 +#define _BINARY_OP_ADD_INT_INPLACE_r23 663 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 664 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 665 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 666 +#define _BINARY_OP_ADD_UNICODE_r03 667 +#define _BINARY_OP_ADD_UNICODE_r13 668 +#define _BINARY_OP_ADD_UNICODE_r23 669 +#define _BINARY_OP_EXTEND_r23 670 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 671 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 672 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 673 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 674 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 675 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 676 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 677 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 678 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 679 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 680 +#define _BINARY_OP_MULTIPLY_INT_r03 681 +#define _BINARY_OP_MULTIPLY_INT_r13 682 +#define _BINARY_OP_MULTIPLY_INT_r23 683 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 684 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 685 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 686 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 687 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 688 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 689 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 690 +#define _BINARY_OP_SUBSCR_DICT_r23 691 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 692 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 693 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 694 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 695 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 696 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 697 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 698 +#define _BINARY_OP_SUBSCR_STR_INT_r23 699 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 700 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 701 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 702 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 703 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 704 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 705 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 706 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 707 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 708 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 709 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 710 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 711 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 712 +#define _BINARY_OP_SUBTRACT_INT_r03 713 +#define _BINARY_OP_SUBTRACT_INT_r13 714 +#define _BINARY_OP_SUBTRACT_INT_r23 715 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 716 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 717 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 718 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 719 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 720 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 721 +#define _BINARY_OP_TRUEDIV_FLOAT_r23 722 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 723 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 724 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 725 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 726 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 727 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 728 +#define _BINARY_SLICE_r31 729 +#define _BUILD_INTERPOLATION_r01 730 +#define _BUILD_LIST_r01 731 +#define _BUILD_MAP_r01 732 +#define _BUILD_SET_r01 733 +#define _BUILD_SLICE_r01 734 +#define _BUILD_STRING_r01 735 +#define _BUILD_TEMPLATE_r21 736 +#define _BUILD_TUPLE_r01 737 +#define _CALL_BUILTIN_CLASS_r00 738 +#define _CALL_BUILTIN_FAST_r00 739 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 740 +#define _CALL_BUILTIN_O_r03 741 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 742 +#define _CALL_INTRINSIC_1_r12 743 +#define _CALL_INTRINSIC_2_r23 744 +#define _CALL_ISINSTANCE_r31 745 +#define _CALL_KW_NON_PY_r11 746 +#define _CALL_LEN_r33 747 +#define _CALL_LIST_APPEND_r03 748 +#define _CALL_LIST_APPEND_r13 749 +#define _CALL_LIST_APPEND_r23 750 +#define _CALL_LIST_APPEND_r33 751 +#define _CALL_METHOD_DESCRIPTOR_FAST_r00 752 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 753 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 754 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 755 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r03 756 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 757 +#define _CALL_METHOD_DESCRIPTOR_O_r03 758 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 759 +#define _CALL_NON_PY_GENERAL_r01 760 +#define _CALL_STR_1_r32 761 +#define _CALL_TUPLE_1_r32 762 +#define _CALL_TYPE_1_r02 763 +#define _CALL_TYPE_1_r12 764 +#define _CALL_TYPE_1_r22 765 +#define _CALL_TYPE_1_r32 766 +#define _CHECK_ATTR_CLASS_r01 767 +#define _CHECK_ATTR_CLASS_r11 768 +#define _CHECK_ATTR_CLASS_r22 769 +#define _CHECK_ATTR_CLASS_r33 770 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 771 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 772 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 773 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 774 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 775 +#define _CHECK_EG_MATCH_r22 776 +#define _CHECK_EXC_MATCH_r22 777 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 778 +#define _CHECK_FUNCTION_VERSION_r00 779 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 780 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 781 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 782 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 783 +#define _CHECK_FUNCTION_VERSION_KW_r11 784 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 785 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 786 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 787 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 788 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 789 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 790 +#define _CHECK_IS_PY_CALLABLE_EX_r03 791 +#define _CHECK_IS_PY_CALLABLE_EX_r13 792 +#define _CHECK_IS_PY_CALLABLE_EX_r23 793 +#define _CHECK_IS_PY_CALLABLE_EX_r33 794 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 795 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 796 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 797 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 798 +#define _CHECK_METHOD_VERSION_r00 799 +#define _CHECK_METHOD_VERSION_KW_r11 800 +#define _CHECK_OBJECT_r00 801 +#define _CHECK_PEP_523_r00 802 +#define _CHECK_PEP_523_r11 803 +#define _CHECK_PEP_523_r22 804 +#define _CHECK_PEP_523_r33 805 +#define _CHECK_PERIODIC_r00 806 +#define _CHECK_PERIODIC_AT_END_r00 807 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 808 +#define _CHECK_RECURSION_LIMIT_r00 809 +#define _CHECK_RECURSION_LIMIT_r11 810 +#define _CHECK_RECURSION_LIMIT_r22 811 +#define _CHECK_RECURSION_LIMIT_r33 812 +#define _CHECK_RECURSION_REMAINING_r00 813 +#define _CHECK_RECURSION_REMAINING_r11 814 +#define _CHECK_RECURSION_REMAINING_r22 815 +#define _CHECK_RECURSION_REMAINING_r33 816 +#define _CHECK_STACK_SPACE_r00 817 +#define _CHECK_STACK_SPACE_OPERAND_r00 818 +#define _CHECK_STACK_SPACE_OPERAND_r11 819 +#define _CHECK_STACK_SPACE_OPERAND_r22 820 +#define _CHECK_STACK_SPACE_OPERAND_r33 821 +#define _CHECK_VALIDITY_r00 822 +#define _CHECK_VALIDITY_r11 823 +#define _CHECK_VALIDITY_r22 824 +#define _CHECK_VALIDITY_r33 825 +#define _COLD_DYNAMIC_EXIT_r00 826 +#define _COLD_EXIT_r00 827 +#define _COMPARE_OP_r21 828 +#define _COMPARE_OP_FLOAT_r03 829 +#define _COMPARE_OP_FLOAT_r13 830 +#define _COMPARE_OP_FLOAT_r23 831 +#define _COMPARE_OP_INT_r23 832 +#define _COMPARE_OP_STR_r23 833 +#define _CONTAINS_OP_r23 834 +#define _CONTAINS_OP_DICT_r23 835 +#define _CONTAINS_OP_SET_r23 836 +#define _CONVERT_VALUE_r11 837 +#define _COPY_r01 838 +#define _COPY_1_r02 839 +#define _COPY_1_r12 840 +#define _COPY_1_r23 841 +#define _COPY_2_r03 842 +#define _COPY_2_r13 843 +#define _COPY_2_r23 844 +#define _COPY_3_r03 845 +#define _COPY_3_r13 846 +#define _COPY_3_r23 847 +#define _COPY_3_r33 848 +#define _COPY_FREE_VARS_r00 849 +#define _COPY_FREE_VARS_r11 850 +#define _COPY_FREE_VARS_r22 851 +#define _COPY_FREE_VARS_r33 852 +#define _CREATE_INIT_FRAME_r01 853 +#define _DELETE_ATTR_r10 854 +#define _DELETE_DEREF_r00 855 +#define _DELETE_FAST_r00 856 +#define _DELETE_GLOBAL_r00 857 +#define _DELETE_NAME_r00 858 +#define _DELETE_SUBSCR_r20 859 +#define _DEOPT_r00 860 +#define _DEOPT_r10 861 +#define _DEOPT_r20 862 +#define _DEOPT_r30 863 +#define _DICT_MERGE_r11 864 +#define _DICT_UPDATE_r11 865 +#define _DO_CALL_r01 866 +#define _DO_CALL_FUNCTION_EX_r31 867 +#define _DO_CALL_KW_r11 868 +#define _DYNAMIC_EXIT_r00 869 +#define _DYNAMIC_EXIT_r10 870 +#define _DYNAMIC_EXIT_r20 871 +#define _DYNAMIC_EXIT_r30 872 +#define _END_FOR_r10 873 +#define _END_SEND_r31 874 +#define _ERROR_POP_N_r00 875 +#define _EXIT_INIT_CHECK_r10 876 +#define _EXIT_TRACE_r00 877 +#define _EXIT_TRACE_r10 878 +#define _EXIT_TRACE_r20 879 +#define _EXIT_TRACE_r30 880 +#define _EXPAND_METHOD_r00 881 +#define _EXPAND_METHOD_KW_r11 882 +#define _FATAL_ERROR_r00 883 +#define _FATAL_ERROR_r11 884 +#define _FATAL_ERROR_r22 885 +#define _FATAL_ERROR_r33 886 +#define _FORMAT_SIMPLE_r11 887 +#define _FORMAT_WITH_SPEC_r21 888 +#define _FOR_ITER_r23 889 +#define _FOR_ITER_GEN_FRAME_r03 890 +#define _FOR_ITER_GEN_FRAME_r13 891 +#define _FOR_ITER_GEN_FRAME_r23 892 +#define _FOR_ITER_TIER_TWO_r23 893 +#define _FOR_ITER_VIRTUAL_r23 894 +#define _FOR_ITER_VIRTUAL_TIER_TWO_r23 895 +#define _GET_AITER_r11 896 +#define _GET_ANEXT_r12 897 +#define _GET_AWAITABLE_r11 898 +#define _GET_ITER_r12 899 +#define _GET_ITER_TRAD_r12 900 +#define _GET_LEN_r12 901 +#define _GUARD_BINARY_OP_EXTEND_r22 902 +#define _GUARD_BINARY_OP_EXTEND_LHS_r02 903 +#define _GUARD_BINARY_OP_EXTEND_LHS_r12 904 +#define _GUARD_BINARY_OP_EXTEND_LHS_r22 905 +#define _GUARD_BINARY_OP_EXTEND_LHS_r33 906 +#define _GUARD_BINARY_OP_EXTEND_RHS_r02 907 +#define _GUARD_BINARY_OP_EXTEND_RHS_r12 908 +#define _GUARD_BINARY_OP_EXTEND_RHS_r22 909 +#define _GUARD_BINARY_OP_EXTEND_RHS_r33 910 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 911 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 912 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 913 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 914 +#define _GUARD_BIT_IS_SET_POP_r00 915 +#define _GUARD_BIT_IS_SET_POP_r10 916 +#define _GUARD_BIT_IS_SET_POP_r21 917 +#define _GUARD_BIT_IS_SET_POP_r32 918 +#define _GUARD_BIT_IS_SET_POP_4_r00 919 +#define _GUARD_BIT_IS_SET_POP_4_r10 920 +#define _GUARD_BIT_IS_SET_POP_4_r21 921 +#define _GUARD_BIT_IS_SET_POP_4_r32 922 +#define _GUARD_BIT_IS_SET_POP_5_r00 923 +#define _GUARD_BIT_IS_SET_POP_5_r10 924 +#define _GUARD_BIT_IS_SET_POP_5_r21 925 +#define _GUARD_BIT_IS_SET_POP_5_r32 926 +#define _GUARD_BIT_IS_SET_POP_6_r00 927 +#define _GUARD_BIT_IS_SET_POP_6_r10 928 +#define _GUARD_BIT_IS_SET_POP_6_r21 929 +#define _GUARD_BIT_IS_SET_POP_6_r32 930 +#define _GUARD_BIT_IS_SET_POP_7_r00 931 +#define _GUARD_BIT_IS_SET_POP_7_r10 932 +#define _GUARD_BIT_IS_SET_POP_7_r21 933 +#define _GUARD_BIT_IS_SET_POP_7_r32 934 +#define _GUARD_BIT_IS_UNSET_POP_r00 935 +#define _GUARD_BIT_IS_UNSET_POP_r10 936 +#define _GUARD_BIT_IS_UNSET_POP_r21 937 +#define _GUARD_BIT_IS_UNSET_POP_r32 938 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 939 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 940 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 941 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 942 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 943 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 944 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 945 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 946 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 947 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 948 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 949 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 950 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 951 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 952 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 953 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 954 +#define _GUARD_CALLABLE_BUILTIN_CLASS_r00 955 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 956 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 957 +#define _GUARD_CALLABLE_BUILTIN_O_r00 958 +#define _GUARD_CALLABLE_ISINSTANCE_r03 959 +#define _GUARD_CALLABLE_ISINSTANCE_r13 960 +#define _GUARD_CALLABLE_ISINSTANCE_r23 961 +#define _GUARD_CALLABLE_ISINSTANCE_r33 962 +#define _GUARD_CALLABLE_LEN_r03 963 +#define _GUARD_CALLABLE_LEN_r13 964 +#define _GUARD_CALLABLE_LEN_r23 965 +#define _GUARD_CALLABLE_LEN_r33 966 +#define _GUARD_CALLABLE_LIST_APPEND_r03 967 +#define _GUARD_CALLABLE_LIST_APPEND_r13 968 +#define _GUARD_CALLABLE_LIST_APPEND_r23 969 +#define _GUARD_CALLABLE_LIST_APPEND_r33 970 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 971 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 972 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 973 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 974 +#define _GUARD_CALLABLE_STR_1_r03 975 +#define _GUARD_CALLABLE_STR_1_r13 976 +#define _GUARD_CALLABLE_STR_1_r23 977 +#define _GUARD_CALLABLE_STR_1_r33 978 +#define _GUARD_CALLABLE_TUPLE_1_r03 979 +#define _GUARD_CALLABLE_TUPLE_1_r13 980 +#define _GUARD_CALLABLE_TUPLE_1_r23 981 +#define _GUARD_CALLABLE_TUPLE_1_r33 982 +#define _GUARD_CALLABLE_TYPE_1_r03 983 +#define _GUARD_CALLABLE_TYPE_1_r13 984 +#define _GUARD_CALLABLE_TYPE_1_r23 985 +#define _GUARD_CALLABLE_TYPE_1_r33 986 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 987 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 988 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 989 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 990 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 991 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 992 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 993 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 994 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 995 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 996 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 997 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 998 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 999 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 1000 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 1001 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 1002 +#define _GUARD_DORV_NO_DICT_r01 1003 +#define _GUARD_DORV_NO_DICT_r11 1004 +#define _GUARD_DORV_NO_DICT_r22 1005 +#define _GUARD_DORV_NO_DICT_r33 1006 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 1007 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 1008 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 1009 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 1010 +#define _GUARD_GLOBALS_VERSION_r00 1011 +#define _GUARD_GLOBALS_VERSION_r11 1012 +#define _GUARD_GLOBALS_VERSION_r22 1013 +#define _GUARD_GLOBALS_VERSION_r33 1014 +#define _GUARD_IP_RETURN_GENERATOR_r00 1015 +#define _GUARD_IP_RETURN_GENERATOR_r11 1016 +#define _GUARD_IP_RETURN_GENERATOR_r22 1017 +#define _GUARD_IP_RETURN_GENERATOR_r33 1018 +#define _GUARD_IP_RETURN_VALUE_r00 1019 +#define _GUARD_IP_RETURN_VALUE_r11 1020 +#define _GUARD_IP_RETURN_VALUE_r22 1021 +#define _GUARD_IP_RETURN_VALUE_r33 1022 +#define _GUARD_IP_YIELD_VALUE_r00 1023 +#define _GUARD_IP_YIELD_VALUE_r11 1024 +#define _GUARD_IP_YIELD_VALUE_r22 1025 +#define _GUARD_IP_YIELD_VALUE_r33 1026 +#define _GUARD_IP__PUSH_FRAME_r00 1027 +#define _GUARD_IP__PUSH_FRAME_r11 1028 +#define _GUARD_IP__PUSH_FRAME_r22 1029 +#define _GUARD_IP__PUSH_FRAME_r33 1030 +#define _GUARD_IS_FALSE_POP_r00 1031 +#define _GUARD_IS_FALSE_POP_r10 1032 +#define _GUARD_IS_FALSE_POP_r21 1033 +#define _GUARD_IS_FALSE_POP_r32 1034 +#define _GUARD_IS_NONE_POP_r00 1035 +#define _GUARD_IS_NONE_POP_r10 1036 +#define _GUARD_IS_NONE_POP_r21 1037 +#define _GUARD_IS_NONE_POP_r32 1038 +#define _GUARD_IS_NOT_NONE_POP_r10 1039 +#define _GUARD_IS_TRUE_POP_r00 1040 +#define _GUARD_IS_TRUE_POP_r10 1041 +#define _GUARD_IS_TRUE_POP_r21 1042 +#define _GUARD_IS_TRUE_POP_r32 1043 +#define _GUARD_ITERATOR_r01 1044 +#define _GUARD_ITERATOR_r11 1045 +#define _GUARD_ITERATOR_r22 1046 +#define _GUARD_ITERATOR_r33 1047 +#define _GUARD_ITER_VIRTUAL_r01 1048 +#define _GUARD_ITER_VIRTUAL_r11 1049 +#define _GUARD_ITER_VIRTUAL_r22 1050 +#define _GUARD_ITER_VIRTUAL_r33 1051 +#define _GUARD_KEYS_VERSION_r01 1052 +#define _GUARD_KEYS_VERSION_r11 1053 +#define _GUARD_KEYS_VERSION_r22 1054 +#define _GUARD_KEYS_VERSION_r33 1055 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r03 1056 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r13 1057 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r23 1058 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r33 1059 +#define _GUARD_NOS_ANY_DICT_r02 1060 +#define _GUARD_NOS_ANY_DICT_r12 1061 +#define _GUARD_NOS_ANY_DICT_r22 1062 +#define _GUARD_NOS_ANY_DICT_r33 1063 +#define _GUARD_NOS_COMPACT_ASCII_r02 1064 +#define _GUARD_NOS_COMPACT_ASCII_r12 1065 +#define _GUARD_NOS_COMPACT_ASCII_r22 1066 +#define _GUARD_NOS_COMPACT_ASCII_r33 1067 +#define _GUARD_NOS_DICT_r02 1068 +#define _GUARD_NOS_DICT_r12 1069 +#define _GUARD_NOS_DICT_r22 1070 +#define _GUARD_NOS_DICT_r33 1071 +#define _GUARD_NOS_FLOAT_r02 1072 +#define _GUARD_NOS_FLOAT_r12 1073 +#define _GUARD_NOS_FLOAT_r22 1074 +#define _GUARD_NOS_FLOAT_r33 1075 +#define _GUARD_NOS_INT_r02 1076 +#define _GUARD_NOS_INT_r12 1077 +#define _GUARD_NOS_INT_r22 1078 +#define _GUARD_NOS_INT_r33 1079 +#define _GUARD_NOS_ITER_VIRTUAL_r02 1080 +#define _GUARD_NOS_ITER_VIRTUAL_r12 1081 +#define _GUARD_NOS_ITER_VIRTUAL_r22 1082 +#define _GUARD_NOS_ITER_VIRTUAL_r33 1083 +#define _GUARD_NOS_LIST_r02 1084 +#define _GUARD_NOS_LIST_r12 1085 +#define _GUARD_NOS_LIST_r22 1086 +#define _GUARD_NOS_LIST_r33 1087 +#define _GUARD_NOS_NOT_NULL_r02 1088 +#define _GUARD_NOS_NOT_NULL_r12 1089 +#define _GUARD_NOS_NOT_NULL_r22 1090 +#define _GUARD_NOS_NOT_NULL_r33 1091 +#define _GUARD_NOS_NULL_r02 1092 +#define _GUARD_NOS_NULL_r12 1093 +#define _GUARD_NOS_NULL_r22 1094 +#define _GUARD_NOS_NULL_r33 1095 +#define _GUARD_NOS_OVERFLOWED_r02 1096 +#define _GUARD_NOS_OVERFLOWED_r12 1097 +#define _GUARD_NOS_OVERFLOWED_r22 1098 +#define _GUARD_NOS_OVERFLOWED_r33 1099 +#define _GUARD_NOS_TUPLE_r02 1100 +#define _GUARD_NOS_TUPLE_r12 1101 +#define _GUARD_NOS_TUPLE_r22 1102 +#define _GUARD_NOS_TUPLE_r33 1103 +#define _GUARD_NOS_TYPE_VERSION_r02 1104 +#define _GUARD_NOS_TYPE_VERSION_r12 1105 +#define _GUARD_NOS_TYPE_VERSION_r22 1106 +#define _GUARD_NOS_TYPE_VERSION_r33 1107 +#define _GUARD_NOS_UNICODE_r02 1108 +#define _GUARD_NOS_UNICODE_r12 1109 +#define _GUARD_NOS_UNICODE_r22 1110 +#define _GUARD_NOS_UNICODE_r33 1111 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1112 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1113 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1114 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1115 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1116 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1117 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1118 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1119 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1120 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1121 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1122 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1123 +#define _GUARD_THIRD_NULL_r03 1124 +#define _GUARD_THIRD_NULL_r13 1125 +#define _GUARD_THIRD_NULL_r23 1126 +#define _GUARD_THIRD_NULL_r33 1127 +#define _GUARD_TOS_ANY_DICT_r01 1128 +#define _GUARD_TOS_ANY_DICT_r11 1129 +#define _GUARD_TOS_ANY_DICT_r22 1130 +#define _GUARD_TOS_ANY_DICT_r33 1131 +#define _GUARD_TOS_ANY_SET_r01 1132 +#define _GUARD_TOS_ANY_SET_r11 1133 +#define _GUARD_TOS_ANY_SET_r22 1134 +#define _GUARD_TOS_ANY_SET_r33 1135 +#define _GUARD_TOS_DICT_r01 1136 +#define _GUARD_TOS_DICT_r11 1137 +#define _GUARD_TOS_DICT_r22 1138 +#define _GUARD_TOS_DICT_r33 1139 +#define _GUARD_TOS_FLOAT_r01 1140 +#define _GUARD_TOS_FLOAT_r11 1141 +#define _GUARD_TOS_FLOAT_r22 1142 +#define _GUARD_TOS_FLOAT_r33 1143 +#define _GUARD_TOS_FROZENDICT_r01 1144 +#define _GUARD_TOS_FROZENDICT_r11 1145 +#define _GUARD_TOS_FROZENDICT_r22 1146 +#define _GUARD_TOS_FROZENDICT_r33 1147 +#define _GUARD_TOS_FROZENSET_r01 1148 +#define _GUARD_TOS_FROZENSET_r11 1149 +#define _GUARD_TOS_FROZENSET_r22 1150 +#define _GUARD_TOS_FROZENSET_r33 1151 +#define _GUARD_TOS_INT_r01 1152 +#define _GUARD_TOS_INT_r11 1153 +#define _GUARD_TOS_INT_r22 1154 +#define _GUARD_TOS_INT_r33 1155 +#define _GUARD_TOS_LIST_r01 1156 +#define _GUARD_TOS_LIST_r11 1157 +#define _GUARD_TOS_LIST_r22 1158 +#define _GUARD_TOS_LIST_r33 1159 +#define _GUARD_TOS_OVERFLOWED_r01 1160 +#define _GUARD_TOS_OVERFLOWED_r11 1161 +#define _GUARD_TOS_OVERFLOWED_r22 1162 +#define _GUARD_TOS_OVERFLOWED_r33 1163 +#define _GUARD_TOS_SET_r01 1164 +#define _GUARD_TOS_SET_r11 1165 +#define _GUARD_TOS_SET_r22 1166 +#define _GUARD_TOS_SET_r33 1167 +#define _GUARD_TOS_SLICE_r01 1168 +#define _GUARD_TOS_SLICE_r11 1169 +#define _GUARD_TOS_SLICE_r22 1170 +#define _GUARD_TOS_SLICE_r33 1171 +#define _GUARD_TOS_TUPLE_r01 1172 +#define _GUARD_TOS_TUPLE_r11 1173 +#define _GUARD_TOS_TUPLE_r22 1174 +#define _GUARD_TOS_TUPLE_r33 1175 +#define _GUARD_TOS_UNICODE_r01 1176 +#define _GUARD_TOS_UNICODE_r11 1177 +#define _GUARD_TOS_UNICODE_r22 1178 +#define _GUARD_TOS_UNICODE_r33 1179 +#define _GUARD_TYPE_r01 1180 +#define _GUARD_TYPE_r11 1181 +#define _GUARD_TYPE_r22 1182 +#define _GUARD_TYPE_r33 1183 +#define _GUARD_TYPE_VERSION_r01 1184 +#define _GUARD_TYPE_VERSION_r11 1185 +#define _GUARD_TYPE_VERSION_r22 1186 +#define _GUARD_TYPE_VERSION_r33 1187 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1188 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1189 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1190 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1191 +#define _HANDLE_PENDING_AND_DEOPT_r00 1192 +#define _HANDLE_PENDING_AND_DEOPT_r10 1193 +#define _HANDLE_PENDING_AND_DEOPT_r20 1194 +#define _HANDLE_PENDING_AND_DEOPT_r30 1195 +#define _IMPORT_FROM_r12 1196 +#define _IMPORT_NAME_r21 1197 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1198 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1199 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1200 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1201 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1202 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1203 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1204 +#define _INSERT_NULL_r10 1205 +#define _INSTRUMENTED_FOR_ITER_r23 1206 +#define _INSTRUMENTED_INSTRUCTION_r00 1207 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1208 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1209 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1210 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1211 +#define _INSTRUMENTED_LINE_r00 1212 +#define _INSTRUMENTED_NOT_TAKEN_r00 1213 +#define _INSTRUMENTED_NOT_TAKEN_r11 1214 +#define _INSTRUMENTED_NOT_TAKEN_r22 1215 +#define _INSTRUMENTED_NOT_TAKEN_r33 1216 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1217 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1218 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1219 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1220 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1221 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1222 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1223 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1224 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1225 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1226 +#define _IS_NONE_r11 1227 +#define _IS_OP_r03 1228 +#define _IS_OP_r13 1229 +#define _IS_OP_r23 1230 +#define _ITER_CHECK_LIST_r02 1231 +#define _ITER_CHECK_LIST_r12 1232 +#define _ITER_CHECK_LIST_r22 1233 +#define _ITER_CHECK_LIST_r33 1234 +#define _ITER_CHECK_RANGE_r02 1235 +#define _ITER_CHECK_RANGE_r12 1236 +#define _ITER_CHECK_RANGE_r22 1237 +#define _ITER_CHECK_RANGE_r33 1238 +#define _ITER_CHECK_TUPLE_r02 1239 +#define _ITER_CHECK_TUPLE_r12 1240 +#define _ITER_CHECK_TUPLE_r22 1241 +#define _ITER_CHECK_TUPLE_r33 1242 +#define _ITER_JUMP_LIST_r02 1243 +#define _ITER_JUMP_LIST_r12 1244 +#define _ITER_JUMP_LIST_r22 1245 +#define _ITER_JUMP_LIST_r33 1246 +#define _ITER_JUMP_RANGE_r02 1247 +#define _ITER_JUMP_RANGE_r12 1248 +#define _ITER_JUMP_RANGE_r22 1249 +#define _ITER_JUMP_RANGE_r33 1250 +#define _ITER_JUMP_TUPLE_r02 1251 +#define _ITER_JUMP_TUPLE_r12 1252 +#define _ITER_JUMP_TUPLE_r22 1253 +#define _ITER_JUMP_TUPLE_r33 1254 +#define _ITER_NEXT_LIST_r23 1255 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1256 +#define _ITER_NEXT_RANGE_r03 1257 +#define _ITER_NEXT_RANGE_r13 1258 +#define _ITER_NEXT_RANGE_r23 1259 +#define _ITER_NEXT_TUPLE_r03 1260 +#define _ITER_NEXT_TUPLE_r13 1261 +#define _ITER_NEXT_TUPLE_r23 1262 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1263 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1264 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1265 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1266 +#define _JUMP_TO_TOP_r00 1267 +#define _LIST_APPEND_r10 1268 +#define _LIST_EXTEND_r11 1269 +#define _LOAD_ATTR_r10 1270 +#define _LOAD_ATTR_CLASS_r11 1271 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 1272 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1273 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1274 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1275 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1276 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1277 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1278 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1279 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1280 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1281 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1282 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1283 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1284 +#define _LOAD_ATTR_MODULE_r12 1285 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1286 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1287 +#define _LOAD_ATTR_PROPERTY_FRAME_r01 1288 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1289 +#define _LOAD_ATTR_PROPERTY_FRAME_r22 1290 +#define _LOAD_ATTR_PROPERTY_FRAME_r33 1291 +#define _LOAD_ATTR_SLOT_r02 1292 +#define _LOAD_ATTR_SLOT_r12 1293 +#define _LOAD_ATTR_SLOT_r23 1294 +#define _LOAD_ATTR_WITH_HINT_r12 1295 +#define _LOAD_BUILD_CLASS_r01 1296 +#define _LOAD_BYTECODE_r00 1297 +#define _LOAD_COMMON_CONSTANT_r01 1298 +#define _LOAD_COMMON_CONSTANT_r12 1299 +#define _LOAD_COMMON_CONSTANT_r23 1300 +#define _LOAD_CONST_r01 1301 +#define _LOAD_CONST_r12 1302 +#define _LOAD_CONST_r23 1303 +#define _LOAD_CONST_INLINE_r01 1304 +#define _LOAD_CONST_INLINE_r12 1305 +#define _LOAD_CONST_INLINE_r23 1306 +#define _LOAD_CONST_INLINE_BORROW_r01 1307 +#define _LOAD_CONST_INLINE_BORROW_r12 1308 +#define _LOAD_CONST_INLINE_BORROW_r23 1309 +#define _LOAD_DEREF_r01 1310 +#define _LOAD_FAST_r01 1311 +#define _LOAD_FAST_r12 1312 +#define _LOAD_FAST_r23 1313 +#define _LOAD_FAST_0_r01 1314 +#define _LOAD_FAST_0_r12 1315 +#define _LOAD_FAST_0_r23 1316 +#define _LOAD_FAST_1_r01 1317 +#define _LOAD_FAST_1_r12 1318 +#define _LOAD_FAST_1_r23 1319 +#define _LOAD_FAST_2_r01 1320 +#define _LOAD_FAST_2_r12 1321 +#define _LOAD_FAST_2_r23 1322 +#define _LOAD_FAST_3_r01 1323 +#define _LOAD_FAST_3_r12 1324 +#define _LOAD_FAST_3_r23 1325 +#define _LOAD_FAST_4_r01 1326 +#define _LOAD_FAST_4_r12 1327 +#define _LOAD_FAST_4_r23 1328 +#define _LOAD_FAST_5_r01 1329 +#define _LOAD_FAST_5_r12 1330 +#define _LOAD_FAST_5_r23 1331 +#define _LOAD_FAST_6_r01 1332 +#define _LOAD_FAST_6_r12 1333 +#define _LOAD_FAST_6_r23 1334 +#define _LOAD_FAST_7_r01 1335 +#define _LOAD_FAST_7_r12 1336 +#define _LOAD_FAST_7_r23 1337 +#define _LOAD_FAST_AND_CLEAR_r01 1338 +#define _LOAD_FAST_AND_CLEAR_r12 1339 +#define _LOAD_FAST_AND_CLEAR_r23 1340 +#define _LOAD_FAST_BORROW_r01 1341 +#define _LOAD_FAST_BORROW_r12 1342 +#define _LOAD_FAST_BORROW_r23 1343 +#define _LOAD_FAST_BORROW_0_r01 1344 +#define _LOAD_FAST_BORROW_0_r12 1345 +#define _LOAD_FAST_BORROW_0_r23 1346 +#define _LOAD_FAST_BORROW_1_r01 1347 +#define _LOAD_FAST_BORROW_1_r12 1348 +#define _LOAD_FAST_BORROW_1_r23 1349 +#define _LOAD_FAST_BORROW_2_r01 1350 +#define _LOAD_FAST_BORROW_2_r12 1351 +#define _LOAD_FAST_BORROW_2_r23 1352 +#define _LOAD_FAST_BORROW_3_r01 1353 +#define _LOAD_FAST_BORROW_3_r12 1354 +#define _LOAD_FAST_BORROW_3_r23 1355 +#define _LOAD_FAST_BORROW_4_r01 1356 +#define _LOAD_FAST_BORROW_4_r12 1357 +#define _LOAD_FAST_BORROW_4_r23 1358 +#define _LOAD_FAST_BORROW_5_r01 1359 +#define _LOAD_FAST_BORROW_5_r12 1360 +#define _LOAD_FAST_BORROW_5_r23 1361 +#define _LOAD_FAST_BORROW_6_r01 1362 +#define _LOAD_FAST_BORROW_6_r12 1363 +#define _LOAD_FAST_BORROW_6_r23 1364 +#define _LOAD_FAST_BORROW_7_r01 1365 +#define _LOAD_FAST_BORROW_7_r12 1366 +#define _LOAD_FAST_BORROW_7_r23 1367 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1368 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1369 +#define _LOAD_FAST_CHECK_r01 1370 +#define _LOAD_FAST_CHECK_r12 1371 +#define _LOAD_FAST_CHECK_r23 1372 +#define _LOAD_FAST_LOAD_FAST_r02 1373 +#define _LOAD_FAST_LOAD_FAST_r13 1374 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1375 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1376 +#define _LOAD_GLOBAL_r00 1377 +#define _LOAD_GLOBAL_BUILTINS_r01 1378 +#define _LOAD_GLOBAL_MODULE_r01 1379 +#define _LOAD_LOCALS_r01 1380 +#define _LOAD_LOCALS_r12 1381 +#define _LOAD_LOCALS_r23 1382 +#define _LOAD_NAME_r01 1383 +#define _LOAD_SMALL_INT_r01 1384 +#define _LOAD_SMALL_INT_r12 1385 +#define _LOAD_SMALL_INT_r23 1386 +#define _LOAD_SMALL_INT_0_r01 1387 +#define _LOAD_SMALL_INT_0_r12 1388 +#define _LOAD_SMALL_INT_0_r23 1389 +#define _LOAD_SMALL_INT_1_r01 1390 +#define _LOAD_SMALL_INT_1_r12 1391 +#define _LOAD_SMALL_INT_1_r23 1392 +#define _LOAD_SMALL_INT_2_r01 1393 +#define _LOAD_SMALL_INT_2_r12 1394 +#define _LOAD_SMALL_INT_2_r23 1395 +#define _LOAD_SMALL_INT_3_r01 1396 +#define _LOAD_SMALL_INT_3_r12 1397 +#define _LOAD_SMALL_INT_3_r23 1398 +#define _LOAD_SPECIAL_r00 1399 +#define _LOAD_SUPER_ATTR_ATTR_r31 1400 +#define _LOAD_SUPER_ATTR_METHOD_r32 1401 +#define _LOCK_OBJECT_r01 1402 +#define _LOCK_OBJECT_r11 1403 +#define _LOCK_OBJECT_r22 1404 +#define _LOCK_OBJECT_r33 1405 +#define _MAKE_CALLARGS_A_TUPLE_r33 1406 +#define _MAKE_CELL_r00 1407 +#define _MAKE_FUNCTION_r12 1408 +#define _MAKE_HEAP_SAFE_r01 1409 +#define _MAKE_HEAP_SAFE_r11 1410 +#define _MAKE_HEAP_SAFE_r22 1411 +#define _MAKE_HEAP_SAFE_r33 1412 +#define _MAKE_WARM_r00 1413 +#define _MAKE_WARM_r11 1414 +#define _MAKE_WARM_r22 1415 +#define _MAKE_WARM_r33 1416 +#define _MAP_ADD_r20 1417 +#define _MATCH_CLASS_r33 1418 +#define _MATCH_KEYS_r23 1419 +#define _MATCH_MAPPING_r02 1420 +#define _MATCH_MAPPING_r12 1421 +#define _MATCH_MAPPING_r23 1422 +#define _MATCH_SEQUENCE_r02 1423 +#define _MATCH_SEQUENCE_r12 1424 +#define _MATCH_SEQUENCE_r23 1425 +#define _MAYBE_EXPAND_METHOD_r00 1426 +#define _MAYBE_EXPAND_METHOD_KW_r11 1427 +#define _MONITOR_CALL_r00 1428 +#define _MONITOR_CALL_KW_r11 1429 +#define _MONITOR_JUMP_BACKWARD_r00 1430 +#define _MONITOR_JUMP_BACKWARD_r11 1431 +#define _MONITOR_JUMP_BACKWARD_r22 1432 +#define _MONITOR_JUMP_BACKWARD_r33 1433 +#define _MONITOR_RESUME_r00 1434 +#define _NOP_r00 1435 +#define _NOP_r11 1436 +#define _NOP_r22 1437 +#define _NOP_r33 1438 +#define _POP_EXCEPT_r10 1439 +#define _POP_ITER_r20 1440 +#define _POP_JUMP_IF_FALSE_r00 1441 +#define _POP_JUMP_IF_FALSE_r10 1442 +#define _POP_JUMP_IF_FALSE_r21 1443 +#define _POP_JUMP_IF_FALSE_r32 1444 +#define _POP_JUMP_IF_TRUE_r00 1445 +#define _POP_JUMP_IF_TRUE_r10 1446 +#define _POP_JUMP_IF_TRUE_r21 1447 +#define _POP_JUMP_IF_TRUE_r32 1448 +#define _POP_TOP_r10 1449 +#define _POP_TOP_FLOAT_r00 1450 +#define _POP_TOP_FLOAT_r10 1451 +#define _POP_TOP_FLOAT_r21 1452 +#define _POP_TOP_FLOAT_r32 1453 +#define _POP_TOP_INT_r00 1454 +#define _POP_TOP_INT_r10 1455 +#define _POP_TOP_INT_r21 1456 +#define _POP_TOP_INT_r32 1457 +#define _POP_TOP_NOP_r00 1458 +#define _POP_TOP_NOP_r10 1459 +#define _POP_TOP_NOP_r21 1460 +#define _POP_TOP_NOP_r32 1461 +#define _POP_TOP_OPARG_r00 1462 +#define _POP_TOP_UNICODE_r00 1463 +#define _POP_TOP_UNICODE_r10 1464 +#define _POP_TOP_UNICODE_r21 1465 +#define _POP_TOP_UNICODE_r32 1466 +#define _PUSH_EXC_INFO_r02 1467 +#define _PUSH_EXC_INFO_r12 1468 +#define _PUSH_EXC_INFO_r23 1469 +#define _PUSH_FRAME_r10 1470 +#define _PUSH_NULL_r01 1471 +#define _PUSH_NULL_r12 1472 +#define _PUSH_NULL_r23 1473 +#define _PUSH_NULL_CONDITIONAL_r00 1474 +#define _PUSH_TAGGED_ZERO_r01 1475 +#define _PUSH_TAGGED_ZERO_r12 1476 +#define _PUSH_TAGGED_ZERO_r23 1477 +#define _PY_FRAME_EX_r31 1478 +#define _PY_FRAME_GENERAL_r01 1479 +#define _PY_FRAME_KW_r11 1480 +#define _REPLACE_WITH_TRUE_r02 1481 +#define _REPLACE_WITH_TRUE_r12 1482 +#define _REPLACE_WITH_TRUE_r23 1483 +#define _RESUME_CHECK_r00 1484 +#define _RESUME_CHECK_r11 1485 +#define _RESUME_CHECK_r22 1486 +#define _RESUME_CHECK_r33 1487 +#define _RETURN_GENERATOR_r01 1488 +#define _RETURN_VALUE_r11 1489 +#define _RROT_3_r03 1490 +#define _RROT_3_r13 1491 +#define _RROT_3_r23 1492 +#define _RROT_3_r33 1493 +#define _SAVE_RETURN_OFFSET_r00 1494 +#define _SAVE_RETURN_OFFSET_r11 1495 +#define _SAVE_RETURN_OFFSET_r22 1496 +#define _SAVE_RETURN_OFFSET_r33 1497 +#define _SEND_r33 1498 +#define _SEND_GEN_FRAME_r33 1499 +#define _SETUP_ANNOTATIONS_r00 1500 +#define _SET_ADD_r10 1501 +#define _SET_FUNCTION_ATTRIBUTE_r01 1502 +#define _SET_FUNCTION_ATTRIBUTE_r11 1503 +#define _SET_FUNCTION_ATTRIBUTE_r21 1504 +#define _SET_FUNCTION_ATTRIBUTE_r32 1505 +#define _SET_IP_r00 1506 +#define _SET_IP_r11 1507 +#define _SET_IP_r22 1508 +#define _SET_IP_r33 1509 +#define _SET_UPDATE_r11 1510 +#define _SPILL_OR_RELOAD_r01 1511 +#define _SPILL_OR_RELOAD_r02 1512 +#define _SPILL_OR_RELOAD_r03 1513 +#define _SPILL_OR_RELOAD_r10 1514 +#define _SPILL_OR_RELOAD_r12 1515 +#define _SPILL_OR_RELOAD_r13 1516 +#define _SPILL_OR_RELOAD_r20 1517 +#define _SPILL_OR_RELOAD_r21 1518 +#define _SPILL_OR_RELOAD_r23 1519 +#define _SPILL_OR_RELOAD_r30 1520 +#define _SPILL_OR_RELOAD_r31 1521 +#define _SPILL_OR_RELOAD_r32 1522 +#define _START_EXECUTOR_r00 1523 +#define _STORE_ATTR_r20 1524 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1525 +#define _STORE_ATTR_SLOT_r21 1526 +#define _STORE_ATTR_WITH_HINT_r21 1527 +#define _STORE_DEREF_r10 1528 +#define _STORE_FAST_LOAD_FAST_r11 1529 +#define _STORE_FAST_STORE_FAST_r20 1530 +#define _STORE_GLOBAL_r10 1531 +#define _STORE_NAME_r10 1532 +#define _STORE_SLICE_r30 1533 +#define _STORE_SUBSCR_r30 1534 +#define _STORE_SUBSCR_DICT_r31 1535 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1536 +#define _STORE_SUBSCR_LIST_INT_r32 1537 +#define _SWAP_r11 1538 +#define _SWAP_2_r02 1539 +#define _SWAP_2_r12 1540 +#define _SWAP_2_r22 1541 +#define _SWAP_2_r33 1542 +#define _SWAP_3_r03 1543 +#define _SWAP_3_r13 1544 +#define _SWAP_3_r23 1545 +#define _SWAP_3_r33 1546 +#define _SWAP_FAST_r01 1547 +#define _SWAP_FAST_r11 1548 +#define _SWAP_FAST_r22 1549 +#define _SWAP_FAST_r33 1550 +#define _SWAP_FAST_0_r01 1551 +#define _SWAP_FAST_0_r11 1552 +#define _SWAP_FAST_0_r22 1553 +#define _SWAP_FAST_0_r33 1554 +#define _SWAP_FAST_1_r01 1555 +#define _SWAP_FAST_1_r11 1556 +#define _SWAP_FAST_1_r22 1557 +#define _SWAP_FAST_1_r33 1558 +#define _SWAP_FAST_2_r01 1559 +#define _SWAP_FAST_2_r11 1560 +#define _SWAP_FAST_2_r22 1561 +#define _SWAP_FAST_2_r33 1562 +#define _SWAP_FAST_3_r01 1563 +#define _SWAP_FAST_3_r11 1564 +#define _SWAP_FAST_3_r22 1565 +#define _SWAP_FAST_3_r33 1566 +#define _SWAP_FAST_4_r01 1567 +#define _SWAP_FAST_4_r11 1568 +#define _SWAP_FAST_4_r22 1569 +#define _SWAP_FAST_4_r33 1570 +#define _SWAP_FAST_5_r01 1571 +#define _SWAP_FAST_5_r11 1572 +#define _SWAP_FAST_5_r22 1573 +#define _SWAP_FAST_5_r33 1574 +#define _SWAP_FAST_6_r01 1575 +#define _SWAP_FAST_6_r11 1576 +#define _SWAP_FAST_6_r22 1577 +#define _SWAP_FAST_6_r33 1578 +#define _SWAP_FAST_7_r01 1579 +#define _SWAP_FAST_7_r11 1580 +#define _SWAP_FAST_7_r22 1581 +#define _SWAP_FAST_7_r33 1582 +#define _TIER2_RESUME_CHECK_r00 1583 +#define _TIER2_RESUME_CHECK_r11 1584 +#define _TIER2_RESUME_CHECK_r22 1585 +#define _TIER2_RESUME_CHECK_r33 1586 +#define _TO_BOOL_r11 1587 +#define _TO_BOOL_BOOL_r01 1588 +#define _TO_BOOL_BOOL_r11 1589 +#define _TO_BOOL_BOOL_r22 1590 +#define _TO_BOOL_BOOL_r33 1591 +#define _TO_BOOL_INT_r02 1592 +#define _TO_BOOL_INT_r12 1593 +#define _TO_BOOL_INT_r23 1594 +#define _TO_BOOL_LIST_r02 1595 +#define _TO_BOOL_LIST_r12 1596 +#define _TO_BOOL_LIST_r23 1597 +#define _TO_BOOL_NONE_r01 1598 +#define _TO_BOOL_NONE_r11 1599 +#define _TO_BOOL_NONE_r22 1600 +#define _TO_BOOL_NONE_r33 1601 +#define _TO_BOOL_STR_r02 1602 +#define _TO_BOOL_STR_r12 1603 +#define _TO_BOOL_STR_r23 1604 +#define _TRACE_RECORD_r00 1605 +#define _UNARY_INVERT_r12 1606 +#define _UNARY_NEGATIVE_r12 1607 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1608 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1609 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1610 +#define _UNARY_NOT_r01 1611 +#define _UNARY_NOT_r11 1612 +#define _UNARY_NOT_r22 1613 +#define _UNARY_NOT_r33 1614 +#define _UNPACK_EX_r10 1615 +#define _UNPACK_SEQUENCE_r10 1616 +#define _UNPACK_SEQUENCE_LIST_r10 1617 +#define _UNPACK_SEQUENCE_TUPLE_r10 1618 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1619 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1620 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1621 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1622 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1623 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1624 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1625 +#define _WITH_EXCEPT_START_r33 1626 +#define _YIELD_VALUE_r11 1627 +#define MAX_UOP_REGS_ID 1627 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 17fd5d04838..8f543dbeeb8 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -397,6 +397,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_VALIDITY] = HAS_DEOPT_FLAG, [_LOAD_CONST_INLINE] = HAS_PURE_FLAG, [_LOAD_CONST_INLINE_BORROW] = HAS_PURE_FLAG, + [_RROT_3] = HAS_PURE_FLAG, [_START_EXECUTOR] = HAS_DEOPT_FLAG, [_MAKE_WARM] = 0, [_FATAL_ERROR] = 0, @@ -3699,6 +3700,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_RROT_3] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 3, 0, _RROT_3_r03 }, + { 3, 1, _RROT_3_r13 }, + { 3, 2, _RROT_3_r23 }, + { 3, 3, _RROT_3_r33 }, + }, + }, [_START_EXECUTOR] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -4695,6 +4705,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_LOAD_CONST_INLINE_BORROW_r01] = _LOAD_CONST_INLINE_BORROW, [_LOAD_CONST_INLINE_BORROW_r12] = _LOAD_CONST_INLINE_BORROW, [_LOAD_CONST_INLINE_BORROW_r23] = _LOAD_CONST_INLINE_BORROW, + [_RROT_3_r03] = _RROT_3, + [_RROT_3_r13] = _RROT_3, + [_RROT_3_r23] = _RROT_3, + [_RROT_3_r33] = _RROT_3, [_START_EXECUTOR_r00] = _START_EXECUTOR, [_MAKE_WARM_r00] = _MAKE_WARM, [_MAKE_WARM_r11] = _MAKE_WARM, @@ -5896,6 +5910,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_RETURN_GENERATOR_r01] = "_RETURN_GENERATOR_r01", [_RETURN_VALUE] = "_RETURN_VALUE", [_RETURN_VALUE_r11] = "_RETURN_VALUE_r11", + [_RROT_3] = "_RROT_3", + [_RROT_3_r03] = "_RROT_3_r03", + [_RROT_3_r13] = "_RROT_3_r13", + [_RROT_3_r23] = "_RROT_3_r23", + [_RROT_3_r33] = "_RROT_3_r33", [_SAVE_RETURN_OFFSET] = "_SAVE_RETURN_OFFSET", [_SAVE_RETURN_OFFSET_r00] = "_SAVE_RETURN_OFFSET_r00", [_SAVE_RETURN_OFFSET_r11] = "_SAVE_RETURN_OFFSET_r11", @@ -6808,6 +6827,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _LOAD_CONST_INLINE_BORROW: return 0; + case _RROT_3: + return 0; case _START_EXECUTOR: return 0; case _MAKE_WARM: diff --git a/Python/bytecodes.c b/Python/bytecodes.c index a73df99f3f5..d485172c82f 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -6107,6 +6107,13 @@ dummy_func( value = PyStackRef_FromPyObjectBorrow(ptr); } + tier2 pure op(_RROT_3, (bottom, middle, top -- bottom, middle, top)) { + _PyStackRef temp = top; + top = middle; + middle = bottom; + bottom = temp; + } + tier2 op(_START_EXECUTOR, (executor/4 --)) { #ifndef _Py_JIT assert(current_executor == (_PyExecutorObject*)executor); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 5a7129c1ffd..f8fc35de9d7 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -22337,6 +22337,102 @@ break; } + case _RROT_3_r03: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef top; + _PyStackRef middle; + _PyStackRef bottom; + top = stack_pointer[-1]; + middle = stack_pointer[-2]; + bottom = stack_pointer[-3]; + _PyStackRef temp = top; + top = middle; + middle = bottom; + bottom = temp; + _tos_cache2 = top; + _tos_cache1 = middle; + _tos_cache0 = bottom; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _RROT_3_r13: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef top; + _PyStackRef middle; + _PyStackRef bottom; + _PyStackRef _stack_item_0 = _tos_cache0; + top = _stack_item_0; + middle = stack_pointer[-1]; + bottom = stack_pointer[-2]; + _PyStackRef temp = top; + top = middle; + middle = bottom; + bottom = temp; + _tos_cache2 = top; + _tos_cache1 = middle; + _tos_cache0 = bottom; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _RROT_3_r23: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef top; + _PyStackRef middle; + _PyStackRef bottom; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + top = _stack_item_1; + middle = _stack_item_0; + bottom = stack_pointer[-1]; + _PyStackRef temp = top; + top = middle; + middle = bottom; + bottom = temp; + _tos_cache2 = top; + _tos_cache1 = middle; + _tos_cache0 = bottom; + SET_CURRENT_CACHED_VALUES(3); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _RROT_3_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef top; + _PyStackRef middle; + _PyStackRef bottom; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + top = _stack_item_2; + middle = _stack_item_1; + bottom = _stack_item_0; + _PyStackRef temp = top; + top = middle; + middle = bottom; + bottom = temp; + _tos_cache2 = top; + _tos_cache1 = middle; + _tos_cache0 = bottom; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _START_EXECUTOR_r00: { CHECK_CURRENT_CACHED_VALUES(0); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 15d4d0bc181..33b5257fd58 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -936,6 +936,13 @@ dummy_func(void) { assert(oparg >= 2); } + op(_RROT_3, (bottom, middle, top -- bottom, middle, top)) { + JitOptRef temp = top; + top = middle; + middle = bottom; + bottom = temp; + } + op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, o)) { attr = sym_new_not_null(ctx); (void)offset; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index b09aca910fc..8f208beb864 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -638,10 +638,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -710,10 +709,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -782,10 +780,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -1605,10 +1602,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -2935,10 +2931,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -3010,10 +3005,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -3074,10 +3068,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -3156,10 +3149,9 @@ if (sym_is_const(ctx, b)) { PyObject *result = sym_get_const(ctx, b); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -3265,10 +3257,9 @@ if (sym_is_const(ctx, b)) { PyObject *result = sym_get_const(ctx, b); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -3332,10 +3323,9 @@ if (sym_is_const(ctx, b)) { PyObject *result = sym_get_const(ctx, b); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -5220,10 +5210,9 @@ if (sym_is_const(ctx, res)) { PyObject *result = sym_get_const(ctx, res); if (_Py_IsImmortal(result)) { - // Replace with _LOAD_CONST_INLINE_BORROW + _SWAP + _SWAP since we have two inputs and an immortal result + // Replace with _LOAD_CONST_INLINE_BORROW + _RROT_3 since we have two inputs and an immortal result ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result); - ADD_OP(_SWAP, 3, 0); - ADD_OP(_SWAP, 2, 0); + ADD_OP(_RROT_3, 0, 0); } } CHECK_STACK_BOUNDS(1); @@ -5504,6 +5493,23 @@ break; } + case _RROT_3: { + JitOptRef top; + JitOptRef middle; + JitOptRef bottom; + top = stack_pointer[-1]; + middle = stack_pointer[-2]; + bottom = stack_pointer[-3]; + JitOptRef temp = top; + top = middle; + middle = bottom; + bottom = temp; + stack_pointer[-3] = bottom; + stack_pointer[-2] = middle; + stack_pointer[-1] = top; + break; + } + case _START_EXECUTOR: { break; } diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index 784e1a8a2d1..aa914783f7c 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -258,8 +258,7 @@ def replace_opcode_if_evaluates_pure( # usually for binary ops with passthrough references 2: [("_LOAD_CONST_INLINE_BORROW", "0, (uintptr_t)result"), - ("_SWAP", "3, 0"), - ("_SWAP", "2, 0")], + ("_RROT_3", "0, 0")], }, } From f2c7c0d2b799c927d9a78e87e4a640d3f9b0356c Mon Sep 17 00:00:00 2001 From: sunmy2019 <59365878+sunmy2019@users.noreply.github.com> Date: Fri, 1 May 2026 20:12:08 +0800 Subject: [PATCH 727/775] gh-148967: Fix FFI type pointer handling for C complex support in set_stginfo_ffi_type_pointer (GH-148969) --- Modules/_ctypes/_ctypes.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 0bdc30a0cb3..5325321efe7 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -2225,6 +2225,7 @@ c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value) static int set_stginfo_ffi_type_pointer(StgInfo *stginfo, struct fielddesc *fmt) { +#if defined(_Py_FFI_SUPPORT_C_COMPLEX) if (!fmt->pffi_type->elements) { stginfo->ffi_type_pointer = *fmt->pffi_type; } @@ -2244,6 +2245,10 @@ set_stginfo_ffi_type_pointer(StgInfo *stginfo, struct fielddesc *fmt) memcpy(stginfo->ffi_type_pointer.elements, fmt->pffi_type->elements, els_size); } +#else + assert(!fmt->pffi_type->elements); + stginfo->ffi_type_pointer = *fmt->pffi_type; +#endif return 0; } From 9668d260a197207b440c8e65f09f4cc24b9cd566 Mon Sep 17 00:00:00 2001 From: petervanvugt <65050545+petervanvugt@users.noreply.github.com> Date: Fri, 1 May 2026 08:37:36 -0700 Subject: [PATCH 728/775] gh-148850: Fix memory sanitizer false positive in os.getrandom (GH-148851) Co-authored-by: Petr Viktorin --- Include/pyport.h | 4 ++++ .../2026-04-21-19-29-29.gh-issue-148850.MSH0J_.rst | 1 + Modules/posixmodule.c | 2 ++ 3 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-19-29-29.gh-issue-148850.MSH0J_.rst diff --git a/Include/pyport.h b/Include/pyport.h index c975921beaf..73a3e6cdaf0 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -553,6 +553,7 @@ extern "C" { # if !defined(_Py_MEMORY_SANITIZER) # define _Py_MEMORY_SANITIZER # define _Py_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +# define _Py_MSAN_UNPOISON(PTR, SIZE) (__msan_unpoison(PTR, SIZE)) # endif # endif # if __has_feature(address_sanitizer) @@ -591,6 +592,9 @@ extern "C" { #ifndef _Py_NO_SANITIZE_MEMORY # define _Py_NO_SANITIZE_MEMORY #endif +#ifndef _Py_MSAN_UNPOISON +# define _Py_MSAN_UNPOISON(PTR, SIZE) +#endif /* AIX has __bool__ redefined in it's system header file. */ #if defined(_AIX) && defined(__bool__) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-19-29-29.gh-issue-148850.MSH0J_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-19-29-29.gh-issue-148850.MSH0J_.rst new file mode 100644 index 00000000000..324d1610310 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-21-19-29-29.gh-issue-148850.MSH0J_.rst @@ -0,0 +1 @@ +Fix the memory sanitizer false positive in :func:`os.getrandom`. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e5ce487723b..3bdbf2ef816 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -17195,6 +17195,8 @@ os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) goto error; } + _Py_MSAN_UNPOISON(data, size); + return PyBytesWriter_FinishWithSize(writer, n); error: From d96ffc18320a58d164c1809871bb3aea7f549ac6 Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Fri, 1 May 2026 10:52:06 -0700 Subject: [PATCH 729/775] gh-83938, gh-122476: Stop incorrectly RFC 2047 encoding non-ASCII email addresses (#122540) The email generators had been incorrectly flattening non-ASCII email addresses to RFC 2047 encoded-word format, leaving them undeliverable. (RFC 2047 prohibits use of encoded-word in an addr-spec.) This change raises a HeaderWriteError when attempting to flatten an EmailMessage with a non-ASCII addr-spec and a policy with utf8=False. (Exception: If the non-ASCII address originated from parsing a message, it will be flattened as originally parsed, without error.) This also applies to other contexts in which RFC2047 words are not allowed by the RFCs. Non-ASCII email addresses are supported when using a policy with utf8=True (such as email.policy.SMTPUTF8) under RFCs 6531 and 6532. Non-ASCII email address domains (but not localparts) can also be used with non-SMTPUTF8 policies by encoding the domain as an IDNA A-label. (The email package does not perform this encoding, because it cannot know whether the caller wants IDNA 2003, IDNA 2008, or some other variant such as UTS #46.) Co-authored-by: R. David Murray --- Doc/library/email.policy.rst | 19 +++- Doc/whatsnew/3.15.rst | 10 ++ Lib/email/_header_value_parser.py | 91 +++++++++++++---- .../test_email/test__header_value_parser.py | 8 +- Lib/test/test_email/test_generator.py | 99 ++++++++++++++++++- ...4-07-31-17-22-10.gh-issue-83938.TtUa-c.rst | 8 ++ ...-07-31-17-23-06.gh-issue-122476.TtUa-c.rst | 7 ++ 7 files changed, 216 insertions(+), 26 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-07-31-17-22-10.gh-issue-83938.TtUa-c.rst create mode 100644 Misc/NEWS.d/next/Library/2024-07-31-17-23-06.gh-issue-122476.TtUa-c.rst diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst index 8f6e4218c97..816d02d86f4 100644 --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -403,11 +403,26 @@ added matters. To illustrate:: .. attribute:: utf8 If ``False``, follow :rfc:`5322`, supporting non-ASCII characters in - headers by encoding them as "encoded words". If ``True``, follow - :rfc:`6532` and use ``utf-8`` encoding for headers. Messages + headers by encoding them as :rfc:`2047` "encoded words". If ``True``, + follow :rfc:`6532` and use ``utf-8`` encoding for headers. Messages formatted in this way may be passed to SMTP servers that support the ``SMTPUTF8`` extension (:rfc:`6531`). + When ``False``, the generator will raise + :exc:`~email.errors.HeaderWriteError` if any header includes non-ASCII + characters in a context where :rfc:`2047` does not permit encoded words. + This particularly applies to mailboxes ("addr-spec") with non-ASCII + characters, which can be created via + :class:`~email.headerregistry.Address`. To use a mailbox with a non-ASCII + domain name with ``utf8=False``, first encode the domain using the + third-party :pypi:`idna` or :pypi:`uts46` module or with + :mod:`encodings.idna`. It is not possible to use a non-ASCII username + ("local-part") in a mailbox when ``utf8=False``. + + .. versionchanged:: 3.15 + Can trigger the raising of :exc:`~email.errors.HeaderWriteError`. + (Earlier versions incorrectly applied :rfc:`2047` in certain contexts, + mostly notably in addr-specs.) .. attribute:: refold_source diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index a687ee5115b..782b2fe0024 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -914,6 +914,16 @@ faulthandler (Contributed by Eric Froemling in :gh:`149085`.) +email +----- + +* Email generators now raise an error when an :class:`.EmailMessage` cannot be + accurately flattened due to a non-ASCII email address (mailbox) in an address + header. Options for supporting Email Address Internationalization (EAI) are + discussed in :attr:`.EmailPolicy.utf8`. + (Contributed by R David Murray and Mike Edmunds in :gh:`122540`.) + + functools --------- diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index a53903a197f..26b6e26ae65 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -157,10 +157,7 @@ def all_defects(self): def startswith_fws(self): return self[0].startswith_fws() - @property - def as_ew_allowed(self): - """True if all top level tokens of this part may be RFC2047 encoded.""" - return all(part.as_ew_allowed for part in self) + as_ew_allowed = True @property def comments(self): @@ -429,6 +426,7 @@ def addr_spec(self): class AngleAddr(TokenList): token_type = 'angle-addr' + as_ew_allowed = False @property def local_part(self): @@ -847,26 +845,22 @@ def params(self): class ContentType(ParameterizedHeaderValue): token_type = 'content-type' - as_ew_allowed = False maintype = 'text' subtype = 'plain' class ContentDisposition(ParameterizedHeaderValue): token_type = 'content-disposition' - as_ew_allowed = False content_disposition = None class ContentTransferEncoding(TokenList): token_type = 'content-transfer-encoding' - as_ew_allowed = False cte = '7bit' class HeaderLabel(TokenList): token_type = 'header-label' - as_ew_allowed = False class MsgID(TokenList): @@ -2835,13 +2829,68 @@ def _steal_trailing_WSP_if_exists(lines): def _refold_parse_tree(parse_tree, *, policy): - """Return string of contents of parse_tree folded according to RFC rules. - - """ # max_line_length 0/None means no limit, ie: infinitely long. maxlen = policy.max_line_length or sys.maxsize encoding = 'utf-8' if policy.utf8 else 'us-ascii' lines = [''] # Folded lines to be output + if parse_tree.as_ew_allowed: + _refold_with_ew(parse_tree, lines, maxlen, encoding, policy=policy) + else: + _refold_without_ew(parse_tree, lines, maxlen, encoding, policy=policy) + return policy.linesep.join(lines) + policy.linesep + +def _refold_without_ew(parse_tree, lines, maxlen, encoding, *, policy): + parts = list(parse_tree) + while parts: + part = parts.pop(0) + tstr = str(part) + try: + tstr.encode(encoding) + except UnicodeEncodeError: + if any(isinstance(x, errors.UndecodableBytesDefect) + for x in part.all_defects): + # There is garbage data from parsing a message in binary mode, + # just pass it through. Not good, but the best we can do. + pass + elif policy.utf8: + # If this happens, it's a programmer error. + raise + else: + raise errors.HeaderWriteError( + f"Non-ASCII {part.token_type} '{part}' is invalid" + " under current policy setting (utf8=False)" + ) + if len(tstr) <= maxlen - len(lines[-1]): + lines[-1] += tstr + continue + # This part is too long to fit. The RFC wants us to break at + # "major syntactic breaks", so unless we don't consider this + # to be one, check if it will fit on the next line by itself. + if (part.syntactic_break and + len(tstr) + 1 <= maxlen): + newline = _steal_trailing_WSP_if_exists(lines) + if newline or part.startswith_fws(): + lines.append(newline + tstr) + continue + if not hasattr(part, 'encode'): + # It's not a terminal, try folding the subparts. + newparts = list(part) + parts = newparts + parts + continue + # We can't figure out how to wrap, it, so give up. + newline = _steal_trailing_WSP_if_exists(lines) + if newline or part.startswith_fws(): + lines.append(newline + tstr) + else: + # We can't fold it onto the next line either... + lines[-1] += tstr + return + + +def _refold_with_ew(parse_tree, lines, maxlen, encoding, *, policy): + """Return string of contents of parse_tree folded according to RFC rules. + + """ last_word_is_ew = False last_ew = None # if there is an encoded word in the last line of lines, # points to the encoded word's first character @@ -2855,6 +2904,11 @@ def _refold_parse_tree(parse_tree, *, policy): if part is end_ew_not_allowed: wrap_as_ew_blocked -= 1 continue + if part.token_type == 'mime-parameters': + # Mime parameter folding (using RFC2231) is extra special. + _fold_mime_parameters(part, lines, maxlen, encoding) + last_word_is_ew = False + continue tstr = str(part) if not want_encoding: if part.token_type in ('ptext', 'vtext'): @@ -2876,14 +2930,11 @@ def _refold_parse_tree(parse_tree, *, policy): charset = 'utf-8' want_encoding = True - if part.token_type == 'mime-parameters': - # Mime parameter folding (using RFC2231) is extra special. - _fold_mime_parameters(part, lines, maxlen, encoding) - last_word_is_ew = False - continue - if want_encoding and not wrap_as_ew_blocked: - if not part.as_ew_allowed: + if any( + not x.as_ew_allowed for x in part + if hasattr(x, 'as_ew_allowed') + ): want_encoding = False last_ew = None if part.syntactic_break: @@ -2964,6 +3015,8 @@ def _refold_parse_tree(parse_tree, *, policy): [ValueTerminal(make_quoted_pairs(p), 'ptext') for p in newparts] + [ValueTerminal('"', 'ptext')]) + _refold_without_ew(newparts, lines, maxlen, encoding, policy=policy) + continue if part.token_type == 'comment': newparts = ( [ValueTerminal('(', 'ptext')] + @@ -2991,7 +3044,7 @@ def _refold_parse_tree(parse_tree, *, policy): lines[-1] += tstr last_word_is_ew = last_word_is_ew and not bool(tstr.strip(_WSP)) - return policy.linesep.join(lines) + policy.linesep + return def _fold_as_ew(to_encode, lines, maxlen, last_ew, ew_combine_allowed, charset, last_word_is_ew): """Fold string to_encode into lines as encoded word, combining if allowed. diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index f3c03062572..bc698759614 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -3374,10 +3374,12 @@ def test_fold_unfoldable_element_stealing_whitespace(self): self._test(token, expected, policy=policy) def test_encoded_word_with_undecodable_bytes(self): - self._test(parser.get_address_list( - ' =?utf-8?Q?=E5=AE=A2=E6=88=B6=E6=AD=A3=E8=A6=8F=E4=BA=A4=E7?=' + self._test( + parser.get_address_list( + ' =?utf-8?Q?=E5=AE=A2=E6=88=B6=E6=AD=A3=E8=A6=8F=E4=BA=A4=E7?=' + ' ' )[0], - ' =?unknown-8bit?b?5a6i5oi25q2j6KaP5Lqk5w==?=\n', + ' =?unknown-8bit?b?5a6i5oi25q2j6KaP5Lqk5w==?= \n', ) diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py index 3c9a86f3e8c..8d912738029 100644 --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -1,4 +1,5 @@ import io +import re import textwrap import unittest import random @@ -295,6 +296,69 @@ def test_keep_long_encoded_newlines(self): g.flatten(msg) self.assertEqual(s.getvalue(), self.typ(expected)) + def test_non_ascii_addr_spec_raises(self): + # non-ascii is not permitted in any part of an addr-spec. If the + # programmer generated it, it's an error. (See also + # test_non_ascii_addr_spec_preserved below.) + p = self.policy.clone(utf8=False, max_line_length=20) + g = self.genclass(self.ioclass(), policy=p) + # XXX The particular part detected here isn't part of a behavioral + # spec and may change in the future. + cases = [ + ('wők@example.com', 'wők', 'local-part'), + ('wok@exàmple.com', 'exàmple.com', 'domain'), + ('wők@exàmple.com', 'wők', 'local-part'), + ( + '"Name, for display" ', + 'wők@example.com', + 'addr-spec', + ), + ( + 'Näyttönimi ', + 'wők@example.com', + 'addr-spec', + ), + ( + '"a lőng quoted string as the local part"@example.com', + 'a lőng quoted string as the local part', + 'local-part', + ), + + ] + for address, badtoken, partname in cases: + with self.subTest(address=address): + msg = EmailMessage() + msg['To'] = address + expected_error = ( + fr"(?i)(?=.*non-ascii)" + fr"(?=.*{re.escape(badtoken)})" + fr"(?=.*{partname})" + fr"(?=.*policy.*utf8)" + ) + with self.assertRaisesRegex( + email.errors.HeaderWriteError, expected_error + ): + g.flatten(msg) + + def test_local_part_quoted_string_wrapped_correctly(self): + msg = self.msgmaker(self.typ(textwrap.dedent("""\ + To: <"a long local part in a quoted string"@example.com> + Subject: test + + None + """)), policy=self.policy.clone(max_line_length=20)) + expected = textwrap.dedent("""\ + To: <"a long local part in a + quoted string"@example.com> + Subject: test + + None + """) + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(max_line_length=30)) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + def _test_boundary_detection(self, linesep): # Generate a boundary token in the same way as _make_boundary token = random.randrange(sys.maxsize) @@ -515,12 +579,12 @@ def test_cte_type_7bit_transforms_8bit_cte(self): def test_smtputf8_policy(self): msg = EmailMessage() - msg['From'] = "Páolo " + msg['From'] = "Páolo " msg['To'] = 'Dinsdale' msg['Subject'] = 'Nudge nudge, wink, wink \u1F609' msg.set_content("oh là là, know what I mean, know what I mean?") expected = textwrap.dedent("""\ - From: Páolo + From: Páolo To: Dinsdale Subject: Nudge nudge, wink, wink \u1F609 Content-Type: text/plain; charset="utf-8" @@ -555,6 +619,37 @@ def test_smtp_policy(self): g.flatten(msg) self.assertEqual(s.getvalue(), expected) + def test_non_ascii_addr_spec_preserved(self): + # A defective non-ASCII addr-spec parsed from the original + # message is left unchanged when flattening. + # (See also test_non_ascii_addr_spec_raises above.) + source = ( + 'To: jörg@example.com, "But a long name still works with refold_source" ' + ).encode() + expected = ( + b'To: j\xc3\xb6rg@example.com,\n' + b' "But a long name still works with refold_source" \n' + b'\n' + ) + msg = message_from_bytes(source, policy=policy.default) + s = io.BytesIO() + g = BytesGenerator(s, policy=policy.default) + g.flatten(msg) + self.assertEqual(s.getvalue(), expected) + + def test_idna_encoding_preserved(self): + # Nothing tries to decode a pre-encoded IDNA domain. + msg = EmailMessage() + msg["To"] = Address( + username='jörg', + domain='☕.example'.encode('idna').decode() # IDNA 2003 + ) + expected = 'To: jörg@xn--53h.example\n\n'.encode() + s = io.BytesIO() + g = BytesGenerator(s, policy=policy.default.clone(utf8=True)) + g.flatten(msg) + self.assertEqual(s.getvalue(), expected) + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2024-07-31-17-22-10.gh-issue-83938.TtUa-c.rst b/Misc/NEWS.d/next/Library/2024-07-31-17-22-10.gh-issue-83938.TtUa-c.rst new file mode 100644 index 00000000000..7082c72f685 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-31-17-22-10.gh-issue-83938.TtUa-c.rst @@ -0,0 +1,8 @@ +The :mod:`email` module no longer incorrectly uses :rfc:`2047` encoding for +a mailbox with non-ASCII characters in its domain. Under a policy with +:attr:`~email.policy.EmailPolicy.utf8` set ``False``, attempting to serialize +such a message will now raise an :exc:`~email.errors.HeaderWriteError`. +Either apply an appropriate IDNA encoding to convert the domain to ASCII before +serialization, or use :data:`email.policy.SMTPUTF8` (or another policy with +``utf8=True``) to correctly pass through the internationalized domain name +as Unicode characters. diff --git a/Misc/NEWS.d/next/Library/2024-07-31-17-23-06.gh-issue-122476.TtUa-c.rst b/Misc/NEWS.d/next/Library/2024-07-31-17-23-06.gh-issue-122476.TtUa-c.rst new file mode 100644 index 00000000000..29c076d3a74 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-31-17-23-06.gh-issue-122476.TtUa-c.rst @@ -0,0 +1,7 @@ +The :mod:`email` module no longer incorrectly uses :rfc:`2047` encoding for +a mailbox with non-ASCII characters in its local-part. Under a policy with +:attr:`~email.policy.EmailPolicy.utf8` set ``False``, attempting to serialize +such a message will now raise an :exc:`~email.errors.HeaderWriteError`. +There is no valid 7-bit encoding for an internationalized local-part. Use +:data:`email.policy.SMTPUTF8` (or another policy with ``utf8=True``) to +correctly pass through the local-part as Unicode characters. From b60557382828a094f9da525cbd71c154bb97378b Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Fri, 1 May 2026 11:00:46 -0700 Subject: [PATCH 730/775] gh-81074: Allow non-ASCII addr_spec in email.headerregistry.Address (#122477) The email.headerregistry.Address constructor raised an error if addr_spec contained a non-ASCII character. (But it fully supports non-ASCII in the separate username and domain args.) This change removes the error for a non-ASCII addr_spec, as well as the Defect that triggered it. In the unicode era non-ascii is not a defect, though it is an error when an attempt is made to serialize it to ascii. The serialization issue was handled in #122540. --- Lib/email/_header_value_parser.py | 5 ----- Lib/email/errors.py | 6 ++--- .../test_email/test__header_value_parser.py | 11 ---------- Lib/test/test_email/test_headerregistry.py | 22 +++++++++---------- ...4-07-30-19-19-33.gh-issue-81074.YAeWNf.rst | 8 +++++++ 5 files changed, 21 insertions(+), 31 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-07-30-19-19-33.gh-issue-81074.YAeWNf.rst diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 26b6e26ae65..9873958f5c2 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1503,11 +1503,6 @@ def get_local_part(value): local_part.defects.append(errors.ObsoleteHeaderDefect( "local-part is not a dot-atom (contains CFWS)")) local_part[0] = obs_local_part - try: - local_part.value.encode('ascii') - except UnicodeEncodeError: - local_part.defects.append(errors.NonASCIILocalPartDefect( - "local-part contains non-ASCII characters)")) return local_part, value def get_obs_local_part(value): diff --git a/Lib/email/errors.py b/Lib/email/errors.py index 6bc744bd59c..859307dd85b 100644 --- a/Lib/email/errors.py +++ b/Lib/email/errors.py @@ -109,9 +109,9 @@ class ObsoleteHeaderDefect(HeaderDefect): """Header uses syntax declared obsolete by RFC 5322""" class NonASCIILocalPartDefect(HeaderDefect): - """local_part contains non-ASCII characters""" - # This defect only occurs during unicode parsing, not when - # parsing messages decoded from binary. + """Unused. Note: this error is deprecated and may be removed in the future.""" + # RFC 6532 permits a non-ASCII local-part. _header_value_parser previously + # treated this as a parse-time defect (when parsing Unicode, but not bytes). class InvalidDateDefect(HeaderDefect): """Header has unparsable or invalid date""" diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index bc698759614..aded44e85ee 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1235,17 +1235,6 @@ def test_get_local_part_valid_and_invalid_qp_in_atom_list(self): '@example.com') self.assertEqual(local_part.local_part, r'\example\\ example') - def test_get_local_part_unicode_defect(self): - # Currently this only happens when parsing unicode, not when parsing - # stuff that was originally binary. - local_part = self._test_get_x(parser.get_local_part, - 'exámple@example.com', - 'exámple', - 'exámple', - [errors.NonASCIILocalPartDefect], - '@example.com') - self.assertEqual(local_part.local_part, 'exámple') - # get_dtext def test_get_dtext_only(self): diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 2aaa7d68ca3..aa918255d15 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1543,17 +1543,19 @@ def test_quoting(self): self.assertEqual(str(a), '"Sara J." <"bad name"@example.com>') def test_il8n(self): - a = Address('Éric', 'wok', 'exàmple.com') + a = Address('Éric', 'wők', 'exàmple.com') self.assertEqual(a.display_name, 'Éric') - self.assertEqual(a.username, 'wok') + self.assertEqual(a.username, 'wők') self.assertEqual(a.domain, 'exàmple.com') - self.assertEqual(a.addr_spec, 'wok@exàmple.com') - self.assertEqual(str(a), 'Éric ') + self.assertEqual(a.addr_spec, 'wők@exàmple.com') + self.assertEqual(str(a), 'Éric ') - # XXX: there is an API design issue that needs to be solved here. - #def test_non_ascii_username_raises(self): - # with self.assertRaises(ValueError): - # Address('foo', 'wők', 'example.com') + def test_i18n_in_addr_spec(self): + a = Address(addr_spec='wők@exàmple.com') + self.assertEqual(a.username, 'wők') + self.assertEqual(a.domain, 'exàmple.com') + self.assertEqual(a.addr_spec, 'wők@exàmple.com') + self.assertEqual(str(a), 'wők@exàmple.com') def test_crlf_in_constructor_args_raises(self): cases = ( @@ -1574,10 +1576,6 @@ def test_crlf_in_constructor_args_raises(self): with self.subTest(kwargs=kwargs), self.assertRaisesRegex(ValueError, "invalid arguments"): Address(**kwargs) - def test_non_ascii_username_in_addr_spec_raises(self): - with self.assertRaises(ValueError): - Address('foo', addr_spec='wők@example.com') - def test_address_addr_spec_and_username_raises(self): with self.assertRaises(TypeError): Address('foo', username='bing', addr_spec='bar@baz') diff --git a/Misc/NEWS.d/next/Library/2024-07-30-19-19-33.gh-issue-81074.YAeWNf.rst b/Misc/NEWS.d/next/Library/2024-07-30-19-19-33.gh-issue-81074.YAeWNf.rst new file mode 100644 index 00000000000..87de4fade14 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-30-19-19-33.gh-issue-81074.YAeWNf.rst @@ -0,0 +1,8 @@ +The :mod:`email` module no longer treats email addresses with non-ASCII +characters as defects when parsing a Unicode string or in the ``addr_spec`` +parameter to :class:`email.headerregistry.Address`. :rfc:`5322` permits such +addresses, and they were already supported when parsing bytes and in the Address +``username`` parameter. + +The (undocumented) :exc:`!email.errors.NonASCIILocalPartDefect` is no longer +used and should be considered deprecated. From 60b751c0181ec4f646666fb02bf4b44e3969e44c Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 1 May 2026 21:39:36 +0300 Subject: [PATCH 731/775] Build mpdecimal from source to workaround unreliable launchpad.net (#149248) --- .github/workflows/posix-deps-apt.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/posix-deps-apt.sh b/.github/workflows/posix-deps-apt.sh index 7994a01ee46..6201e719ca8 100755 --- a/.github/workflows/posix-deps-apt.sh +++ b/.github/workflows/posix-deps-apt.sh @@ -26,9 +26,16 @@ apt-get -yq --no-install-recommends install \ xvfb \ zlib1g-dev -# Workaround missing libmpdec-dev on ubuntu 24.04: -# https://launchpad.net/~ondrej/+archive/ubuntu/php -# https://deb.sury.org/ -sudo add-apt-repository ppa:ondrej/php -apt-get update -apt-get -yq --no-install-recommends install libmpdec-dev +# Workaround missing libmpdec-dev on ubuntu 24.04 by building mpdecimal +# from source. ppa:ondrej/php (launchpad.net) are unreliable +# (https://status.canonical.com) so fetch the tarball directly +# from the upstream host. +# https://www.bytereef.org/mpdecimal/ +MPDECIMAL_VERSION=4.0.1 +curl -fsSL "https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-${MPDECIMAL_VERSION}.tar.gz" \ + | tar -xz -C /tmp +(cd "/tmp/mpdecimal-${MPDECIMAL_VERSION}" \ + && ./configure --prefix=/usr/local \ + && make -j"$(nproc)" \ + && make install) +ldconfig From fa542449bb01e536e7db702d26918b36e3aebe69 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Fri, 1 May 2026 19:55:38 +0100 Subject: [PATCH 732/775] gh-139038: Update final JIT figures for 3.15rc1 (#149210) Co-authored-by: Stan Ulbrych --- Doc/whatsnew/3.15.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 782b2fe0024..83d3cb82195 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1589,11 +1589,11 @@ Upgraded JIT compiler Results from the `pyperformance `__ benchmark suite report -`6-7% `__ +`8-9% `__ geometric mean performance improvement for the JIT over the standard CPython interpreter built with all optimizations enabled on x86-64 Linux. On AArch64 macOS, the JIT has a -`12-13% `__ +`12-13% `__ speedup over the :ref:`tail calling interpreter ` with all optimizations enabled. The speedups for JIT builds versus no JIT builds range from roughly 15% slowdown to over From 4e3811f05300eb436be3d670c9c62631e85844ea Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 1 May 2026 21:57:09 +0300 Subject: [PATCH 733/775] gh-148726: Document the GC change in What's New in Python 3.14 (#149209) --- Doc/whatsnew/3.14.rst | 45 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index dfdfe66be7e..0bb8858aea1 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -953,10 +953,24 @@ when a module is imported) will still emit the syntax warning. (Contributed by Irit Katriel in :gh:`130080`.) +.. _incremental-garbage-collection: .. _whatsnew314-incremental-gc: -Incremental garbage collection ------------------------------- +Garbage collection +------------------ + +**From Python 3.14.5 onwards:** + +The garbage collector (GC) has changed in Python 3.14.5. + +Python 3.14.0-3.14.4 shipped with a new incremental GC. +However, due to a number of `reports +`__ +of significant memory pressure in production environments, +it has been reverted back to the generational GC from 3.13. +This is the GC now used in Python 3.14.5 and later. + +**Previously in Python 3.14.0-3.14.4:** The cycle garbage collector is now incremental. This means that maximum pause times are reduced @@ -2203,7 +2217,18 @@ difflib gc -- -* The new :ref:`incremental garbage collector ` +* **From Python 3.14.5 onwards:** + + Python 3.14.0-3.14.4 shipped with a new incremental garbage collector. + However, due to a number of `reports + `__ + of significant memory pressure in production environments, + it has been reverted back to the generational GC from 3.13. + This is the GC now used in Python 3.14.5 and later. + +* **Previously in Python 3.14.0-3.14.4:** + + The new :ref:`incremental garbage collector ` means that maximum pause times are reduced by an order of magnitude or more for larger heaps. @@ -3447,3 +3472,17 @@ Changes in the C API functions on Python 3.13 and older. .. _pythoncapi-compat project: https://github.com/python/pythoncapi-compat/ + + +Notable changes in 3.14.5 +========================= + +gc +-- + +* The incremental garbage collector shipped in Python 3.14.0-3.14.4 has been + reverted back to the generational garbage collector from 3.13, + due to a number of `reports + `__ + of significant memory pressure in production environments. + See :ref:`whatsnew314-incremental-gc` for details. From 6040d65843198ded82c479eff790d66910cd8435 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Fri, 1 May 2026 20:32:50 +0100 Subject: [PATCH 734/775] Clarify `max_length` in zstd & zlib decompressor documentation (#143805) Also provide examples of how to decompress data using max_length for zstd and zlib. Co-authored-by: Emma Smith --- Doc/library/compression.zstd.rst | 10 +++++++--- Doc/library/zlib.rst | 5 +++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Doc/library/compression.zstd.rst b/Doc/library/compression.zstd.rst index 7ca843f27f5..6d99e36e1e5 100644 --- a/Doc/library/compression.zstd.rst +++ b/Doc/library/compression.zstd.rst @@ -331,10 +331,14 @@ Compressing and decompressing data in memory If *max_length* is non-negative, the method returns at most *max_length* bytes of decompressed data. If this limit is reached and further - output can be produced, the :attr:`~.needs_input` attribute will - be set to ``False``. In this case, the next call to + output can be produced (or EOF is reached), the :attr:`~.needs_input` + attribute will be set to ``False``. In this case, the next call to :meth:`~.decompress` may provide *data* as ``b''`` to obtain - more of the output. + more of the output. The full content can thus be read like:: + + process_output(d.decompress(data, max_length)) + while not d.eof and not d.needs_input: + process_output(d.decompress(b"", max_length)) If all of the input data was decompressed and returned (either because this was less than *max_length* bytes, or because diff --git a/Doc/library/zlib.rst b/Doc/library/zlib.rst index ce0a22b9456..f043915c0f4 100644 --- a/Doc/library/zlib.rst +++ b/Doc/library/zlib.rst @@ -308,6 +308,11 @@ Decompression objects support the following methods and attributes: :attr:`unconsumed_tail`. This bytestring must be passed to a subsequent call to :meth:`decompress` if decompression is to continue. If *max_length* is zero then the whole input is decompressed, and :attr:`unconsumed_tail` is empty. + For example, the full content could be read like:: + + process_output(d.decompress(data, max_length)) + while chunk := d.decompress(d.unconsumed_tail, max_length): + process_output(chunk) .. versionchanged:: 3.6 *max_length* can be used as a keyword argument. From 8c611e12bc735f863d58cf416f293ddd9811021d Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 1 May 2026 22:37:14 +0300 Subject: [PATCH 735/775] Fix source link in `Doc/howto/descriptor.rst` (#149215) --- Doc/howto/descriptor.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 9d5a9ac8b71..07a405837d9 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -1640,7 +1640,7 @@ by member descriptors: class Member: def __init__(self, name, clsname, offset): - 'Emulate PyMemberDef in Include/structmember.h' + 'Emulate PyMemberDef in Include/descrobject.h' # Also see descr_new() in Objects/descrobject.c self.name = name self.clsname = clsname From 690e0de70671a07eba705156508a49c609f44bb1 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 1 May 2026 22:53:28 +0300 Subject: [PATCH 736/775] gh-149083: Change several other docs examples to use `sentinel()` (#149213) --- Doc/faq/programming.rst | 2 +- Doc/howto/descriptor.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index ff34bb5d71c..591565cbc01 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -1924,7 +1924,7 @@ correctly using identity tests: .. code-block:: python - _sentinel = object() + _sentinel = sentinel('_sentinel') def pop(self, key, default=_sentinel): if key in self: diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 07a405837d9..a7a68281860 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -594,7 +594,7 @@ a pure Python equivalent: def object_getattribute(obj, name): "Emulate PyObject_GenericGetAttr() in Objects/object.c" - null = object() + null = sentinel('null') objtype = type(obj) cls_var = find_name_in_mro(objtype, name, null) descr_get = getattr(type(cls_var), '__get__', null) @@ -1635,7 +1635,7 @@ by member descriptors: .. testcode:: - null = object() + null = sentinel('null') class Member: From 323677325735373a06506e5156b7d8e0e96c9660 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Fri, 1 May 2026 21:16:11 +0100 Subject: [PATCH 737/775] =?UTF-8?q?gh-149202:=20Implement=20PEP=20831=20?= =?UTF-8?q?=E2=80=93=20Frame=20Pointers=20Everywhere:=20Enabling=20System-?= =?UTF-8?q?Level=20Observability=20for=20Python=20(#149201)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Savannah Ostrowski Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Emma Smith --- Doc/howto/perf_profiling.rst | 5 +- Doc/using/configure.rst | 18 +++ Doc/whatsnew/3.15.rst | 11 ++ Lib/test/test_frame_pointer_unwind.py | 5 +- ...-04-05-16-10-00.gh-issue-149202.W8sQeR.rst | 4 + configure | 116 ++++++++++++++++-- configure.ac | 28 ++++- 7 files changed, 170 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-16-10-00.gh-issue-149202.W8sQeR.rst diff --git a/Doc/howto/perf_profiling.rst b/Doc/howto/perf_profiling.rst index fc4772bbcca..653f28ddbab 100644 --- a/Doc/howto/perf_profiling.rst +++ b/Doc/howto/perf_profiling.rst @@ -217,8 +217,9 @@ Example, using the :mod:`sys` APIs in file :file:`example.py`: How to obtain the best results ------------------------------ -For best results, Python should be compiled with -``CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"`` as this allows +For best results, keep frame pointers enabled. On supported GCC-compatible +toolchains, CPython builds itself with ``-fno-omit-frame-pointer`` and, when +available, ``-mno-omit-leaf-frame-pointer`` by default. These flags allow profilers to unwind using only the frame pointer and not on DWARF debug information. This is because as the code that is interposed to allow ``perf`` support is dynamically generated it doesn't have any DWARF debugging information diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index d5c17560b66..086f6bfa22a 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -780,6 +780,24 @@ also be used to improve performance. .. versionadded:: 3.14 +.. option:: --without-frame-pointers + + Disable frame pointers, which are enabled by default (see :pep:`831`). + + By default, the build appends ``-fno-omit-frame-pointer`` (and + ``-mno-omit-leaf-frame-pointer`` when the compiler supports it) to + ``BASECFLAGS`` so profilers, debuggers, and system tracing tools + (``perf``, ``eBPF``, ``dtrace``, ``gdb``) can walk the C call stack + without DWARF metadata. The flags propagate to third-party C + extensions through :mod:`sysconfig`. On compilers that do not + understand them, the build silently skips them. + + Downstream packagers and authors of native libraries built with + custom build systems should set the same flags so the unwind chain + stays unbroken across all native frames. + + .. versionadded:: 3.15 + .. option:: --without-mimalloc Disable the fast :ref:`mimalloc ` allocator diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 83d3cb82195..b075441fdea 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -86,6 +86,7 @@ Summary -- Release highlights * :pep:`782`: :ref:`A new PyBytesWriter C API to create a Python bytes object ` * :pep:`803`: :ref:`Stable ABI for Free-Threaded Builds ` +* :pep:`831`: :ref:`Frame pointers everywhere ` * :ref:`The JIT compiler has been significantly upgraded ` * :ref:`Improved error messages ` * :ref:`The official Windows 64-bit binaries now use the tail-calling interpreter @@ -2262,6 +2263,16 @@ Build changes and :option:`-X dev <-X>` is passed to the Python or Python is built in :ref:`debug mode `. (Contributed by Donghee Na in :gh:`141770`.) +.. _whatsnew315-frame-pointers: + +* CPython is now built with frame pointers enabled by default + (:pep:`831`). Pass :option:`--without-frame-pointers` to opt out. + Authors of C extensions and native libraries built with custom build + systems should add ``-fno-omit-frame-pointer`` and + ``-mno-omit-leaf-frame-pointer`` to their own ``CFLAGS`` to keep the + unwind chain intact. + (Contributed by Pablo Galindo Salgado and Savannah Ostrowski in :gh:`149201`.) + .. _whatsnew315-windows-tail-calling-interpreter: * 64-bit builds using Visual Studio 2026 (MSVC 18) may now use the new diff --git a/Lib/test/test_frame_pointer_unwind.py b/Lib/test/test_frame_pointer_unwind.py index c70ec281686..2f9ce2bf049 100644 --- a/Lib/test/test_frame_pointer_unwind.py +++ b/Lib/test/test_frame_pointer_unwind.py @@ -27,9 +27,8 @@ def _frame_pointers_expected(machine): ) if "no-omit-frame-pointer" in cflags: - # For example, configure adds -fno-omit-frame-pointer if Python - # has perf trampoline (PY_HAVE_PERF_TRAMPOLINE) and Python is built - # in debug mode. + # For example, configure adds -fno-omit-frame-pointer by default on + # supported GCC-compatible builds. return True if "omit-frame-pointer" in cflags: return False diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-16-10-00.gh-issue-149202.W8sQeR.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-16-10-00.gh-issue-149202.W8sQeR.rst new file mode 100644 index 00000000000..f82ca91f5ba --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-04-05-16-10-00.gh-issue-149202.W8sQeR.rst @@ -0,0 +1,4 @@ +Enable frame pointers by default for GCC-compatible CPython builds, including +``-mno-omit-leaf-frame-pointer`` when the compiler supports it, so profilers +and debuggers can unwind native interpreter frames more reliably. Users can pass +``--without-frame-pointers`` to opt out. diff --git a/configure b/configure index 6cd7a190046..734aa3a6a72 100755 --- a/configure +++ b/configure @@ -1115,6 +1115,7 @@ enable_bolt with_strict_overflow enable_safety enable_slower_safety +with_frame_pointers enable_experimental_jit with_dsymutil with_address_sanitizer @@ -1912,6 +1913,8 @@ Optional Packages: is no) --with-strict-overflow if 'yes', add -fstrict-overflow to CFLAGS, else add -fno-strict-overflow (default is no) + --without-frame-pointers + build without frame pointers (default is no) --with-dsymutil link debug information into final executable with dsymutil in macOS (default is no) --with-address-sanitizer @@ -10241,9 +10244,115 @@ fi fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build with frame pointers" >&5 +printf %s "checking whether to build with frame pointers... " >&6; } + +# Check whether --with-frame-pointers was given. +if test ${with_frame_pointers+y} +then : + withval=$with_frame_pointers; +else case e in #( + e) with_frame_pointers=yes ;; +esac +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_frame_pointers" >&5 +printf "%s\n" "$with_frame_pointers" >&6; } + if test "x$ac_cv_gcc_compat" = xyes then : + frame_pointer_cflags= + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-omit-frame-pointer" >&5 +printf %s "checking whether C compiler accepts -fno-omit-frame-pointer... " >&6; } +if test ${ax_cv_check_cflags__Werror__fno_omit_frame_pointer+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Werror -fno-omit-frame-pointer" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ax_cv_check_cflags__Werror__fno_omit_frame_pointer=yes +else case e in #( + e) ax_cv_check_cflags__Werror__fno_omit_frame_pointer=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS=$ax_check_save_flags ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror__fno_omit_frame_pointer" >&5 +printf "%s\n" "$ax_cv_check_cflags__Werror__fno_omit_frame_pointer" >&6; } +if test "x$ax_cv_check_cflags__Werror__fno_omit_frame_pointer" = xyes +then : + + frame_pointer_cflags="-fno-omit-frame-pointer" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -mno-omit-leaf-frame-pointer" >&5 +printf %s "checking whether C compiler accepts -mno-omit-leaf-frame-pointer... " >&6; } +if test ${ax_cv_check_cflags__Werror__mno_omit_leaf_frame_pointer+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Werror -mno-omit-leaf-frame-pointer" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ax_cv_check_cflags__Werror__mno_omit_leaf_frame_pointer=yes +else case e in #( + e) ax_cv_check_cflags__Werror__mno_omit_leaf_frame_pointer=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS=$ax_check_save_flags ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror__mno_omit_leaf_frame_pointer" >&5 +printf "%s\n" "$ax_cv_check_cflags__Werror__mno_omit_leaf_frame_pointer" >&6; } +if test "x$ax_cv_check_cflags__Werror__mno_omit_leaf_frame_pointer" = xyes +then : + + frame_pointer_cflags="$frame_pointer_cflags -mno-omit-leaf-frame-pointer" + +else case e in #( + e) : ;; +esac +fi + + +else case e in #( + e) : ;; +esac +fi + + if test -n "$frame_pointer_cflags" && test "x$with_frame_pointers" != xno; then + BASECFLAGS="$frame_pointer_cflags $BASECFLAGS" + fi + CFLAGS_NODIST="$CFLAGS_NODIST -std=c11" @@ -14124,13 +14233,6 @@ printf "%s\n" "#define PY_HAVE_PERF_TRAMPOLINE 1" >>confdefs.h PERF_TRAMPOLINE_OBJ=Python/asm_trampoline.o - if test "x$Py_DEBUG" = xtrue -then : - - as_fn_append BASECFLAGS " -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer" - -fi - fi diff --git a/configure.ac b/configure.ac index 60511db39fa..c8cb1686d55 100644 --- a/configure.ac +++ b/configure.ac @@ -2529,7 +2529,30 @@ then AX_CHECK_COMPILE_FLAG([-D_FORTIFY_SOURCE=3], [CFLAGS_NODIST="$CFLAGS_NODIST -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3"], [AC_MSG_WARN([-D_FORTIFY_SOURCE=3 not supported])], [-Werror]) fi +AC_MSG_CHECKING([whether to build with frame pointers]) +AC_ARG_WITH([frame-pointers], + [AS_HELP_STRING([--without-frame-pointers], + [build without frame pointers (default is no)])], + [], + [with_frame_pointers=yes]) +AC_MSG_RESULT([$with_frame_pointers]) + AS_VAR_IF([ac_cv_gcc_compat], [yes], [ + dnl Keep frame pointers in CPython, stdlib objects, and third-party + dnl extensions built against this Python (BASECFLAGS propagates via + dnl sysconfig) so native profilers can unwind interpreter frames and + dnl generated trampolines without DWARF. + frame_pointer_cflags= + AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [ + frame_pointer_cflags="-fno-omit-frame-pointer" + AX_CHECK_COMPILE_FLAG([-mno-omit-leaf-frame-pointer], [ + frame_pointer_cflags="$frame_pointer_cflags -mno-omit-leaf-frame-pointer" + ], [], [-Werror]) + ], [], [-Werror]) + if test -n "$frame_pointer_cflags" && test "x$with_frame_pointers" != xno; then + BASECFLAGS="$frame_pointer_cflags $BASECFLAGS" + fi + CFLAGS_NODIST="$CFLAGS_NODIST -std=c11" PY_CHECK_CC_WARNING([enable], [extra], [if we can add -Wextra]) @@ -3788,11 +3811,6 @@ AC_MSG_RESULT([$perf_trampoline]) AS_VAR_IF([perf_trampoline], [yes], [ AC_DEFINE([PY_HAVE_PERF_TRAMPOLINE], [1], [Define to 1 if you have the perf trampoline.]) PERF_TRAMPOLINE_OBJ=Python/asm_trampoline.o - - dnl perf needs frame pointers for unwinding, include compiler option in debug builds - AS_VAR_IF([Py_DEBUG], [true], [ - AS_VAR_APPEND([BASECFLAGS], [" -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"]) - ]) ]) AC_SUBST([PERF_TRAMPOLINE_OBJ]) From 91e871a3077ca44cd65e966a4fead5410074506b Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 1 May 2026 16:31:00 -0500 Subject: [PATCH 738/775] gh-124397: Add free-threading support for iterators. (gh-148894) --- Doc/library/threading.rst | 156 ++++++++++++ Doc/whatsnew/3.15.rst | 10 + Lib/test/test_threading.py | 225 ++++++++++++++++++ Lib/threading.py | 143 +++++++++++ ...-04-22-20-49-49.gh-issue-124397.plMglV.rst | 3 + 5 files changed, 537 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-04-22-20-49-49.gh-issue-124397.plMglV.rst diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index 19cc4f191df..fbe3951e034 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -1436,3 +1436,159 @@ is equivalent to:: Currently, :class:`Lock`, :class:`RLock`, :class:`Condition`, :class:`Semaphore`, and :class:`BoundedSemaphore` objects may be used as :keyword:`with` statement context managers. + + +Iterator synchronization +------------------------ + +By default, Python iterators do not support concurrent access. Most iterators make +no guarantees when accessed simultaneously from multiple threads. Generator +iterators, for example, raise :exc:`ValueError` if one of their iterator methods +is called while the generator is already executing. The tools in this section +allow reliable concurrency support to be added to ordinary iterators and +iterator-producing callables. + +The :class:`serialize_iterator` wrapper lets multiple threads share a single iterator and +take turns consuming from it. While one thread is running ``__next__()``, the +others block until the iterator becomes available. Each value produced by the +underlying iterator is delivered to exactly one caller. + +The :func:`concurrent_tee` function lets multiple threads each receive the full +stream of values from one underlying iterator. It creates independent iterators +that all draw from the same source. Values are buffered until consumed by all +of the derived iterators. + +.. class:: serialize_iterator(iterable) + + Return an iterator wrapper that serializes concurrent calls to + :meth:`~iterator.__next__` using a lock. + + If the wrapped iterator also defines :meth:`~generator.send`, + :meth:`~generator.throw`, or :meth:`~generator.close`, those calls + are serialized as well. + + This makes it possible to share a single iterator, including a generator + iterator, between multiple threads. A lock ensures that calls are handled + one at a time. No values are duplicated or skipped by the wrapper itself. + Each item from the underlying iterator is given to exactly one caller. + + This wrapper does not copy or buffer values. Threads that call + :func:`next` while another thread is already advancing the iterator will + block until the active call completes. + + Example: + + .. code-block:: python + + import threading + + def squares(n): + for x in range(n): + yield x * x + + def consume(name, iterable): + for item in iterable: + print(name, item) + + source = threading.serialize_iterator(squares(5)) + + t1 = threading.Thread(target=consume, args=("left", source)) + t2 = threading.Thread(target=consume, args=("right", source)) + t1.start() + t2.start() + t1.join() + t2.join() + + In this example, each number is printed exactly once, but the work is shared + between the two threads. + + .. versionadded:: next + + +.. function:: synchronized_iterator(func) + + Wrap an iterator-producing callable so that each iterator it returns is + automatically passed through :class:`serialize_iterator`. + + This is especially useful as a :term:`decorator` for generator functions, + allowing their generator-iterators to be consumed from multiple threads. + + Example: + + .. code-block:: python + + import threading + + @threading.synchronized_iterator + def squares(n): + for x in range(n): + yield x * x + + def consume(name, iterable): + for item in iterable: + print(name, item) + + source = squares(5) + + t1 = threading.Thread(target=consume, args=("left", source)) + t2 = threading.Thread(target=consume, args=("right", source)) + t1.start() + t2.start() + t1.join() + t2.join() + + The returned wrapper preserves the metadata of *func*, such as its name and + wrapped function reference. + + .. versionadded:: next + + +.. function:: concurrent_tee(iterable, n=2) + + Return *n* independent iterators from a single input *iterable*, with + guaranteed behavior when the derived iterators are consumed concurrently. + + This function is similar to :func:`itertools.tee`, but is intended for cases + where the source iterator may feed consumers running in different threads. + Each returned iterator yields every value from the underlying iterable, in + the same order. + + Internally, values are buffered until every derived iterator has consumed + them. + + The returned iterators share the same underlying synchronization lock. Each + individual derived iterator is intended to be consumed by one thread at a + time. If a single derived iterator must itself be shared by multiple + threads, wrap it with :class:`serialize_iterator`. + + If *n* is ``0``, return an empty tuple. If *n* is negative, raise + :exc:`ValueError`. + + Example: + + .. code-block:: python + + import threading + + def squares(n): + for x in range(n): + yield x * x + + def consume(name, iterable): + for item in iterable: + print(name, item) + + source = squares(5) + left, right = threading.concurrent_tee(source) + + t1 = threading.Thread(target=consume, args=("left", left)) + t2 = threading.Thread(target=consume, args=("right", right)) + t1.start() + t2.start() + t1.join() + t2.join() + + In this example, both consumer threads see the full sequence of squares + from a single generator expression. + + .. versionadded:: next diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index b075441fdea..b63e7a4790e 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1279,6 +1279,16 @@ tarfile (Contributed by Christoph Walcher in :gh:`57911`.) +threading +--------- + +* Added :class:`~threading.serialize_iterator`, + :func:`~threading.synchronized_iterator`, + and :func:`~threading.concurrent_tee` to support concurrent access to + generators and iterators. + (Contributed by Raymond Hettinger in :gh:`124397`.) + + timeit ------ diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 0ca91ce0d78..3d01804513b 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -2368,6 +2368,231 @@ class BarrierTests(lock_tests.BarrierTests): barriertype = staticmethod(threading.Barrier) +## Test Synchronization tools for iterators ################ + +class ThreadingIteratorToolsTests(BaseTestCase): + def test_serialize_serializes_concurrent_iteration(self): + limit = 10_000 + workers_count = 10 + result = 0 + result_lock = threading.Lock() + start = threading.Event() + + def producer(limit): + for x in range(limit): + yield x + + def consumer(iterator): + nonlocal result + start.wait() + total = 0 + for x in iterator: + total += x + with result_lock: + result += total + + iterator = threading.serialize_iterator(producer(limit)) + workers = [ + threading.Thread(target=consumer, args=(iterator,)) + for _ in range(workers_count) + ] + with threading_helper.wait_threads_exit(): + for worker in workers: + worker.start() + for worker in workers: + # Wait for the worker thread to actually start. + while worker.ident is None: + time.sleep(0.1) + start.set() + for worker in workers: + worker.join() + + self.assertEqual(result, limit * (limit - 1) // 2) + + def test_serialize_generator_methods(self): + # A generator that yields and receives + def echo(): + try: + while True: + val = yield "ready" + yield f"received {val}" + except ValueError: + yield "caught" + + it = threading.serialize_iterator(echo()) + + # Test __next__ + self.assertEqual(next(it), "ready") + + # Test send() + self.assertEqual(it.send("hello"), "received hello") + self.assertEqual(next(it), "ready") + + # Test throw() + self.assertEqual(it.throw(ValueError), "caught") + + # Test close() + it.close() + with self.assertRaises(StopIteration): + next(it) + + def test_serialize_methods_attribute_error(self): + # A standard iterator that does not have send/throw/close + # should raise AttributeError when called. + standard_it = threading.serialize_iterator([1, 2, 3]) + + with self.assertRaises(AttributeError): + standard_it.send("foo") + + with self.assertRaises(AttributeError): + standard_it.throw(ValueError) + + with self.assertRaises(AttributeError): + standard_it.close() + + def test_serialize_generator_methods_locking(self): + # Verifies that generator methods also acquire the lock. + # We can test this by checking if the lock is held during the call. + + class LockCheckingGenerator: + def __init__(self, lock): + self.lock = lock + def __iter__(self): + return self + def send(self, value): + if not self.lock.locked(): + raise RuntimeError("Lock not held during send()") + return value + def throw(self, *args): + if not self.lock.locked(): + raise RuntimeError("Lock not held during throw()") + def close(self): + if not self.lock.locked(): + raise RuntimeError("Lock not held during close()") + + # Manually create the serialize object to inspect the lock + it = threading.serialize_iterator([]) + mock_gen = LockCheckingGenerator(it._lock) + it._iterator = mock_gen + + # These should not raise RuntimeError + it.send(1) + it.throw(ValueError) + it.close() + + def test_serialize_next_exception(self): + # Verify exception pass through for calls to next() + + def f(): + raise RuntimeError + yield None + + g = threading.serialize_iterator(f()) + with self.assertRaises(RuntimeError): + next(g) + + def test_synchronized_serializes_generator_instances(self): + unique = 10 + repetitions = 5 + limit = 100 + start = threading.Event() + + @threading.synchronized_iterator + def atomic_counter(): + # The sleep widens the race window that would exist without + # synchronization between yielding a value and advancing state. + i = 0 + while True: + yield i + time.sleep(0.0005) + i += 1 + + def consumer(counter): + start.wait() + for _ in range(limit): + next(counter) + + unique_counters = [atomic_counter() for _ in range(unique)] + counters = unique_counters * repetitions + workers = [ + threading.Thread(target=consumer, args=(counter,)) + for counter in counters + ] + with threading_helper.wait_threads_exit(): + for worker in workers: + worker.start() + start.set() + for worker in workers: + worker.join() + + self.assertEqual( + {next(counter) for counter in unique_counters}, + {limit * repetitions}, + ) + + def test_synchronized_preserves_wrapped_metadata(self): + def gen(): + yield 1 + + wrapped = threading.synchronized_iterator(gen) + + self.assertEqual(wrapped.__name__, gen.__name__) + self.assertIs(wrapped.__wrapped__, gen) + self.assertEqual(list(wrapped()), [1]) + + def test_concurrent_tee_supports_concurrent_consumers(self): + limit = 5_000 + num_threads = 25 + successes = 0 + failures = [] + result_lock = threading.Lock() + start = threading.Event() + expected = list(range(limit)) + + def producer(limit): + for x in range(limit): + yield x + + def consumer(iterator): + nonlocal successes + start.wait() + items = list(iterator) + with result_lock: + if items == expected: + successes += 1 + else: + failures.append(items[:20]) + + tees = threading.concurrent_tee(producer(limit), n=num_threads) + workers = [ + threading.Thread(target=consumer, args=(iterator,)) + for iterator in tees + ] + with threading_helper.wait_threads_exit(): + for worker in workers: + worker.start() + start.set() + for worker in workers: + worker.join() + + self.assertEqual(failures, []) + self.assertEqual(successes, len(tees)) + + # Verify that locks are shared + self.assertEqual(len({id(t_obj.lock) for t_obj in tees}), 1) + + def test_concurrent_tee_zero_iterators(self): + self.assertEqual(threading.concurrent_tee(range(10), n=0), ()) + + def test_concurrent_tee_negative_n(self): + with self.assertRaises(ValueError): + threading.concurrent_tee(range(10), n=-1) + + +################# + + + class MiscTestCase(unittest.TestCase): def test__all__(self): restore_default_excepthook(self) diff --git a/Lib/threading.py b/Lib/threading.py index 4ebceae7029..abac31e2588 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -29,6 +29,7 @@ 'Barrier', 'BrokenBarrierError', 'Timer', 'ThreadError', 'setprofile', 'settrace', 'local', 'stack_size', 'excepthook', 'ExceptHookArgs', 'gettrace', 'getprofile', + 'serialize_iterator', 'synchronized_iterator', 'concurrent_tee', 'setprofile_all_threads','settrace_all_threads'] # Rename some stuff so "from threading import *" is safe @@ -842,6 +843,148 @@ class BrokenBarrierError(RuntimeError): pass +## Synchronization tools for iterators ##################### + +class serialize_iterator: + """Wrap a non-concurrent iterator with a lock to enforce sequential access. + + Applies a non-reentrant lock around calls to __next__. If the + wrapped iterator also defines send(), throw(), or close(), those + calls are serialized as well. + + Allows iterator and generator instances to be shared by multiple consumer + threads. + + For example, itertools.count does not make thread-safe instances, + but that is easily fixed with: + + atomic_counter = serialize_iterator(itertools.count()) + + """ + + __slots__ = ('_iterator', '_lock') + + def __init__(self, iterable): + self._iterator = iter(iterable) + self._lock = Lock() + + def __iter__(self): + return self + + def __next__(self): + with self._lock: + return next(self._iterator) + + def send(self, value, /): + """Send a value to a generator. + + Raises AttributeError if not a generator. + """ + with self._lock: + return self._iterator.send(value) + + def throw(self, *args): + """Call throw() on a generator. + + Raises AttributeError if not a generator. + """ + with self._lock: + return self._iterator.throw(*args) + + def close(self): + """Call close() on a generator. + + Raises AttributeError if not a generator. + """ + with self._lock: + return self._iterator.close() + + +def synchronized_iterator(func): + """Wrap an iterator-returning callable to make its iterators thread-safe. + + Existing itertools and more-itertools can be wrapped so that their + iterator instances are serialized. + + For example, itertools.count does not make thread-safe instances, + but that is easily fixed with: + + atomic_counter = synchronized_iterator(itertools.count) + + Can also be used as a decorator for generator function definitions + so that the generator instances are serialized:: + + import time + + @synchronized_iterator + def enumerate_and_timestamp(iterable): + for count, value in enumerate(iterable): + yield count, time.time_ns(), value + + """ + + from functools import wraps + + @wraps(func) + def inner(*args, **kwargs): + iterator = func(*args, **kwargs) + return serialize_iterator(iterator) + + return inner + + +def concurrent_tee(iterable, n=2): + """Variant of itertools.tee() but with guaranteed threading semantics. + + Takes a non-threadsafe iterator as an input and creates concurrent + tee objects for other threads to have reliable independent copies of + the data stream. + + The new iterators are only thread-safe if consumed within a single thread. + To share just one of the new iterators across multiple threads, wrap it + with threading.serialize_iterator(). + """ + + if n < 0: + raise ValueError("n must be a non-negative integer") + if n == 0: + return () + iterator = _concurrent_tee(iterable) + result = [iterator] + for _ in range(n - 1): + result.append(_concurrent_tee(iterator)) + return tuple(result) + + +class _concurrent_tee: + __slots__ = ('iterator', 'link', 'lock') + + def __init__(self, iterable): + if isinstance(iterable, _concurrent_tee): + self.iterator = iterable.iterator + self.link = iterable.link + self.lock = iterable.lock + else: + self.iterator = iter(iterable) + self.link = [None, None] + self.lock = Lock() + + def __iter__(self): + return self + + def __next__(self): + link = self.link + if link[1] is None: + with self.lock: + if link[1] is None: + link[0] = next(self.iterator) + link[1] = [None, None] + value, self.link = link + return value + +############################################################ + + # Helper to generate new thread names _counter = _count(1).__next__ def _newname(name_template): diff --git a/Misc/NEWS.d/next/Library/2026-04-22-20-49-49.gh-issue-124397.plMglV.rst b/Misc/NEWS.d/next/Library/2026-04-22-20-49-49.gh-issue-124397.plMglV.rst new file mode 100644 index 00000000000..431448a484b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-22-20-49-49.gh-issue-124397.plMglV.rst @@ -0,0 +1,3 @@ +The threading module added tooling to support concurrent iterator access: +:class:`threading.serialize_iterator`, :func:`threading.synchronized_iterator`, +and :func:`threading.concurrent_tee`. From bb911a2319365a4155e7398b4b7978589d8bed49 Mon Sep 17 00:00:00 2001 From: Amp Tell Date: Sat, 2 May 2026 00:39:58 +0200 Subject: [PATCH 739/775] gh-75707: tarfile: Add optional open() argument "mtime" (GH-138117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it possible to set the gzip header mtime field without overriding time.time(), making it useful when creating reproducible archives. * 📜🤖 Added by blurb_it. --------- Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Ethan Furman --- Doc/library/tarfile.rst | 4 +++ Lib/tarfile.py | 18 ++++++++----- Lib/test/test_tarfile.py | 27 +++++++++++++++++++ ...5-08-24-15-09-30.gh-issue-75707.GOWZrC.rst | 1 + 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-08-24-15-09-30.gh-issue-75707.GOWZrC.rst diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index a86469bb9ad..6f1e01cf5aa 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -142,6 +142,10 @@ Some facts and figures: a Zstandard dictionary used to improve compression of smaller amounts of data. + For modes ``'w:gz'`` and ``'w|gz'``, :func:`tarfile.open` accepts the + keyword argument *mtime* to create a gzip archive header with that mtime. By + default, the mtime is set to the time of creation of the archive. + For special purposes, there is a second format for *mode*: ``'filemode|[compression]'``. :func:`tarfile.open` will return a :class:`TarFile` object that processes its data as a stream of blocks. No random seeking will diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 7f0b0b3c632..4f47aaab902 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -337,7 +337,7 @@ class _Stream: """ def __init__(self, name, mode, comptype, fileobj, bufsize, - compresslevel, preset): + compresslevel, preset, mtime): """Construct a _Stream object. """ self._extfileobj = True @@ -372,7 +372,7 @@ def __init__(self, name, mode, comptype, fileobj, bufsize, self.exception = zlib.error self._init_read_gz() else: - self._init_write_gz(compresslevel) + self._init_write_gz(compresslevel, mtime) elif comptype == "bz2": try: @@ -421,7 +421,7 @@ def __del__(self): if hasattr(self, "closed") and not self.closed: self.close() - def _init_write_gz(self, compresslevel): + def _init_write_gz(self, compresslevel, mtime): """Initialize for writing with gzip compression. """ self.cmp = self.zlib.compressobj(compresslevel, @@ -429,7 +429,9 @@ def _init_write_gz(self, compresslevel): -self.zlib.MAX_WBITS, self.zlib.DEF_MEM_LEVEL, 0) - timestamp = struct.pack(" Date: Fri, 1 May 2026 16:51:06 -0700 Subject: [PATCH 740/775] GH-149252: Update WASI SDK version from 32 to 33 (#149253) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- .../next/Build/2026-05-01-20-01-32.gh-issue-149252.4W_0-w.rst | 1 + Platforms/WASI/config.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Build/2026-05-01-20-01-32.gh-issue-149252.4W_0-w.rst diff --git a/Misc/NEWS.d/next/Build/2026-05-01-20-01-32.gh-issue-149252.4W_0-w.rst b/Misc/NEWS.d/next/Build/2026-05-01-20-01-32.gh-issue-149252.4W_0-w.rst new file mode 100644 index 00000000000..646a8e33732 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-05-01-20-01-32.gh-issue-149252.4W_0-w.rst @@ -0,0 +1 @@ +Update to WASI SDK 33. diff --git a/Platforms/WASI/config.toml b/Platforms/WASI/config.toml index 31ec2b8023d..6a6d5713ee9 100644 --- a/Platforms/WASI/config.toml +++ b/Platforms/WASI/config.toml @@ -2,5 +2,5 @@ # This allows for blanket copying of the WASI build code between supported # Python versions. [targets] -wasi-sdk = 32 +wasi-sdk = 33 host-triple = "wasm32-wasip1" From ff35fe4633cc6d3a30f6af8281dfa641783c1d07 Mon Sep 17 00:00:00 2001 From: "W. H. Wang" Date: Sat, 2 May 2026 10:27:23 +0800 Subject: [PATCH 741/775] gh-149117: Set `ImportError.name` on errors from `runpy.run_module`/`run_path` (gh-149159) Set ImportError.name on errors from runpy.run_module/run_path `runpy.run_module()` and `runpy.run_path()` now set the `name` attribute of the `ImportError` they raise to the requested module name, matching the behaviour of a regular import statement (previously `name` was always `None`, which broke introspection). The `name=` kwarg is gated on `issubclass(error, ImportError)` because `_get_module_details()` is also used by `_run_module_as_main()` with a private `_Error` sentinel class. `_Error` does not subclass ImportError, and `BaseException.__init__` rejects unknown kwargs at the C level, so passing `name=` unconditionally would break the `python -m foo` codepath. --- Lib/runpy.py | 25 ++++++++++------ Lib/test/test_runpy.py | 30 +++++++++++++++++++ ...-04-29-16-11-27.gh-issue-149117.yEeTYd.rst | 3 ++ 3 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-29-16-11-27.gh-issue-149117.yEeTYd.rst diff --git a/Lib/runpy.py b/Lib/runpy.py index 9f62d20e9a2..a535b4f651a 100644 --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -102,8 +102,10 @@ def _run_module_code(code, init_globals=None, # Helper to get the full name, spec and code for a module def _get_module_details(mod_name, error=ImportError): + # name= is only accepted by ImportError and its subclasses. + kwargs = {"name": mod_name} if issubclass(error, ImportError) else {} if mod_name.startswith("."): - raise error("Relative module names not supported") + raise error("Relative module names not supported", **kwargs) pkg_name, _, _ = mod_name.rpartition(".") if pkg_name: # Try importing the parent to avoid catching initialization errors @@ -136,12 +138,13 @@ def _get_module_details(mod_name, error=ImportError): if mod_name.endswith(".py"): msg += (f". Try using '{mod_name[:-3]}' instead of " f"'{mod_name}' as the module name.") - raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex + raise error(msg.format(mod_name, type(ex).__name__, ex), + **kwargs) from ex if spec is None: - raise error("No module named %s" % mod_name) + raise error("No module named %s" % mod_name, **kwargs) if spec.submodule_search_locations is not None: if mod_name == "__main__" or mod_name.endswith(".__main__"): - raise error("Cannot use package as __main__ module") + raise error("Cannot use package as __main__ module", **kwargs) try: pkg_main_name = mod_name + ".__main__" return _get_module_details(pkg_main_name, error) @@ -149,17 +152,19 @@ def _get_module_details(mod_name, error=ImportError): if mod_name not in sys.modules: raise # No module loaded; being a package is irrelevant raise error(("%s; %r is a package and cannot " + - "be directly executed") %(e, mod_name)) + "be directly executed") %(e, mod_name), + **kwargs) loader = spec.loader if loader is None: raise error("%r is a namespace package and cannot be executed" - % mod_name) + % mod_name, + **kwargs) try: code = loader.get_code(mod_name) except ImportError as e: - raise error(format(e)) from e + raise error(format(e), **kwargs) from e if code is None: - raise error("No code object available for %s" % mod_name) + raise error("No code object available for %s" % mod_name, **kwargs) return mod_name, spec, code class _Error(Exception): @@ -232,6 +237,7 @@ def _get_main_module_details(error=ImportError): # Also moves the standard __main__ out of the way so that the # preexisting __loader__ entry doesn't cause issues main_name = "__main__" + kwargs = {"name": main_name} if issubclass(error, ImportError) else {} saved_main = sys.modules[main_name] del sys.modules[main_name] try: @@ -239,7 +245,8 @@ def _get_main_module_details(error=ImportError): except ImportError as exc: if main_name in str(exc): raise error("can't find %r module in %r" % - (main_name, sys.path[0])) from exc + (main_name, sys.path[0]), + **kwargs) from exc raise finally: sys.modules[main_name] = saved_main diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index 9f3bc8973eb..55b9673ef6c 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -217,6 +217,25 @@ def test_invalid_names(self): # Package without __main__.py self.expect_import_error("multiprocessing") + def test_invalid_names_set_name_attribute(self): + cases = [ + # (mod_name, expected_name) -- comment indicates raise site + ("nonexistent_runpy_test_module", + "nonexistent_runpy_test_module"), # spec is None + ("sys.imp.eric", "sys.imp.eric"), # find_spec error + (".relative_name", ".relative_name"), # relative name rejected + ("sys", "sys"), # builtin: no code object + ("multiprocessing", "multiprocessing"), # package without __main__ + ] + for mod_name, expected_name in cases: + with self.subTest(mod_name=mod_name): + try: + run_module(mod_name) + except ImportError as exc: + self.assertEqual(exc.name, expected_name) + else: + self.fail("Expected ImportError for %r" % mod_name) + def test_library_module(self): self.assertEqual(run_module("runpy")["__name__"], "runpy") @@ -714,6 +733,17 @@ def test_directory_error(self): msg = "can't find '__main__' module in %r" % script_dir self._check_import_error(script_dir, msg) + def test_directory_error_sets_name_attribute(self): + with temp_dir() as script_dir: + self._make_test_script(script_dir, 'not_main') + try: + run_path(script_dir) + except ImportError as exc: + self.assertEqual(exc.name, '__main__') + else: + self.fail("Expected ImportError for directory without " + "__main__.py") + def test_zipfile(self): with temp_dir() as script_dir: mod_name = '__main__' diff --git a/Misc/NEWS.d/next/Library/2026-04-29-16-11-27.gh-issue-149117.yEeTYd.rst b/Misc/NEWS.d/next/Library/2026-04-29-16-11-27.gh-issue-149117.yEeTYd.rst new file mode 100644 index 00000000000..41223e90ed0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-29-16-11-27.gh-issue-149117.yEeTYd.rst @@ -0,0 +1,3 @@ +Fix :func:`runpy.run_module` and :func:`runpy.run_path` to set the +:attr:`~ImportError.name` attribute on the :exc:`ImportError` they +raise. From 0e2c055892629c36e77e20d396376676890da7f6 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Fri, 1 May 2026 23:52:43 -0400 Subject: [PATCH 742/775] gh-149254: Update macOS installer to use OpenSSL 3.5.6. (#149262) --- Mac/BuildScript/build-installer.py | 6 +++--- .../macOS/2026-05-01-20-12-33.gh-issue-149254.kXdWpS.rst | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/macOS/2026-05-01-20-12-33.gh-issue-149254.kXdWpS.rst diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index cd5f4c71b00..c5f92a99a1e 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -246,9 +246,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 3.5.5", - url="https://github.com/openssl/openssl/releases/download/openssl-3.5.5/openssl-3.5.5.tar.gz", - checksum="b28c91532a8b65a1f983b4c28b7488174e4a01008e29ce8e69bd789f28bc2a89", + name="OpenSSL 3.5.6", + url="https://github.com/openssl/openssl/releases/download/openssl-3.5.6/openssl-3.5.6.tar.gz", + checksum="deae7c80cba99c4b4f940ecadb3c3338b13cb77418409238e57d7f31f2a3b736", buildrecipe=build_universal_openssl, configure=None, install=None, diff --git a/Misc/NEWS.d/next/macOS/2026-05-01-20-12-33.gh-issue-149254.kXdWpS.rst b/Misc/NEWS.d/next/macOS/2026-05-01-20-12-33.gh-issue-149254.kXdWpS.rst new file mode 100644 index 00000000000..278327c91f1 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2026-05-01-20-12-33.gh-issue-149254.kXdWpS.rst @@ -0,0 +1 @@ +Update macOS installer to use OpenSSL 3.5.6. From 0f5cd57f80a704e67b8566f8cf5686d300db28c3 Mon Sep 17 00:00:00 2001 From: htjworld <116538001+htjworld@users.noreply.github.com> Date: Sat, 2 May 2026 12:54:24 +0900 Subject: [PATCH 743/775] statistics: Fix geometric_mean() error message for negative inputs (#149246) --- Lib/statistics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/statistics.py b/Lib/statistics.py index 32fcf2313a8..01ca6c51daf 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -248,7 +248,7 @@ def count_positive(iterable): elif x == 0.0: found_zero = True else: - raise StatisticsError('No negative inputs allowed', x) + raise StatisticsError(f'No negative inputs allowed: {x!r}') total = fsum(map(log, count_positive(data))) From bb5e41efdbe227c7ad9b32a259f79404bab42d5c Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 1 May 2026 22:58:23 -0500 Subject: [PATCH 744/775] gh-149244 Document statistics functions that require sequence inputs. (gh-149264) --- Doc/library/statistics.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index cbb131855dc..dba0e26787d 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -713,7 +713,7 @@ However, for reading convenience, most of the examples show sorted sequences. .. function:: covariance(x, y, /) - Return the sample covariance of two inputs *x* and *y*. Covariance + Return the sample covariance of two sequence inputs *x* and *y*. Covariance is a measure of the joint variability of two inputs. Both inputs must be of the same length (no less than two), otherwise @@ -739,7 +739,7 @@ However, for reading convenience, most of the examples show sorted sequences. Return the `Pearson's correlation coefficient `_ - for two inputs. Pearson's correlation coefficient *r* takes values + for two sequence inputs. Pearson's correlation coefficient *r* takes values between -1 and +1. It measures the strength and direction of a linear relationship. @@ -802,7 +802,7 @@ However, for reading convenience, most of the examples show sorted sequences. (it is equal to the difference between predicted and actual values of the dependent variable). - Both inputs must be of the same length (no less than two), and + Both inputs must be sequences of the same length (no less than two), and the independent variable *x* cannot be constant; otherwise a :exc:`StatisticsError` is raised. From e635ad2c68399b5da7918392dc913a9e10aa2726 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 2 May 2026 16:50:32 +0800 Subject: [PATCH 745/775] gh-149254: Bump OpenSSL versions for iOS and Android. (#149270) Bump OpenSSL versions for iOS and Android. --- .../2026-05-02-15-38-03.gh-issue-149254.0HOL0j.rst | 1 + Platforms/Android/__main__.py | 10 ++++++++-- Platforms/Apple/__main__.py | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2026-05-02-15-38-03.gh-issue-149254.0HOL0j.rst diff --git a/Misc/NEWS.d/next/Security/2026-05-02-15-38-03.gh-issue-149254.0HOL0j.rst b/Misc/NEWS.d/next/Security/2026-05-02-15-38-03.gh-issue-149254.0HOL0j.rst new file mode 100644 index 00000000000..f3cf924db25 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-05-02-15-38-03.gh-issue-149254.0HOL0j.rst @@ -0,0 +1 @@ +Update Android and iOS installer to use OpenSSL 3.5.6. diff --git a/Platforms/Android/__main__.py b/Platforms/Android/__main__.py index 315632ea12c..d2546cf76c2 100755 --- a/Platforms/Android/__main__.py +++ b/Platforms/Android/__main__.py @@ -216,8 +216,14 @@ def make_build_python(context): def unpack_deps(host, prefix_dir, cache_dir): os.chdir(prefix_dir) deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download" - for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.5.5-0", - "sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-2"]: + for name_ver in [ + "bzip2-1.0.8-3", + "libffi-3.4.4-3", + "openssl-3.5.6-0", + "sqlite-3.50.4-0", + "xz-5.4.6-1", + "zstd-1.5.7-2" + ]: filename = f"{name_ver}-{host}.tar.gz" out_path = download(f"{deps_url}/{name_ver}/{filename}", cache_dir) shutil.unpack_archive(out_path) diff --git a/Platforms/Apple/__main__.py b/Platforms/Apple/__main__.py index 44a991c6c20..d94198a309f 100644 --- a/Platforms/Apple/__main__.py +++ b/Platforms/Apple/__main__.py @@ -319,7 +319,7 @@ def unpack_deps( for name_ver in [ "BZip2-1.0.8-2", "libFFI-3.4.7-2", - "OpenSSL-3.5.5-1", + "OpenSSL-3.5.6-1", "XZ-5.6.4-2", "mpdecimal-4.0.0-2", "zstd-1.5.7-1", From b89735625dff07005c31bdc86cbe7113ef1b59d0 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 2 May 2026 12:04:05 +0300 Subject: [PATCH 746/775] gh-148914: Fix memoization of in-band PickleBuffer in the Python implementation (GH-149052) Previously, identical PickleBuffers did not preserve identity. Also, empty writable PickleBuffer memoized an empty bytearray object in place of b'' which is a singleton in CPython, so the following references to b'' were unpickled as an empty bytearray object. --- Lib/pickle.py | 12 ++--- Lib/test/pickletester.py | 45 +++++++++++++++++++ ...-04-27-17-12-11.gh-issue-148914.i5C3kW.rst | 6 +++ 3 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-27-17-12-11.gh-issue-148914.i5C3kW.rst diff --git a/Lib/pickle.py b/Lib/pickle.py index 3e7cf25cb05..95836afdc2b 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -920,17 +920,11 @@ def save_picklebuffer(self, obj): # Write data in-band # XXX The C implementation avoids a copy here buf = m.tobytes() - in_memo = id(buf) in self.memo if m.readonly: - if in_memo: - self._save_bytes_no_memo(buf) - else: - self.save_bytes(buf) + self._save_bytes_no_memo(buf) else: - if in_memo: - self._save_bytearray_no_memo(buf) - else: - self.save_bytearray(buf) + self._save_bytearray_no_memo(buf) + self.memoize(obj) else: # Write data out-of-band self.write(NEXT_BUFFER) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index c2018c9785b..9ba498ce8f5 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -3100,6 +3100,51 @@ def test_bytearray_memoization(self): self.assertIsNot(b2a, b2b) self.assert_is_copy(b2a, b2b) + def test_picklebuffer_memoization(self): + if self.py_version < (3, 8): + self.skipTest('not supported in Python < 3.8') + array_types = [bytes, bytearray] + for proto in range(5, pickle.HIGHEST_PROTOCOL + 1): + for array_type in array_types: + for s in b'', b'xyz', b'xyz'*100: + with self.subTest(proto=proto, array_type=array_type, s=s, independent=False): + b = pickle.PickleBuffer(array_type(s)) + p = self.dumps((b, b), proto) + b1, b2 = self.loads(p) + self.assertIs(b1, b2) + + with self.subTest(proto=proto, array_type=array_type, s=s, independent=True): + b = array_type(s) + b1a = pickle.PickleBuffer(b) + b2a = pickle.PickleBuffer(b) + p = self.dumps((b1a, b2a), proto) + b1b, b2b = self.loads(p) + if array_type is not bytes: + self.assertIsNot(b1b, b2b) + self.assert_is_copy(b1b, b) + self.assert_is_copy(b2b, b) + + def test_empty_picklebuffer_memoization(self): + # gh-148914: Empty writable PickleBuffer memoized an empty bytearray + # with the id of b'' (a singleton in CPython). + if self.py_version < (3, 8): + self.skipTest('not supported in Python < 3.8') + for proto in range(5, pickle.HIGHEST_PROTOCOL + 1): + for readonly in False, True: + with self.subTest(proto=proto, readonly=readonly): + b = b'' + ba = bytearray() + buf = pickle.PickleBuffer(b if readonly else ba) + p = self.dumps((buf, b, ba), proto) + buf, b, ba = self.loads(p) + array_type = bytes if readonly else bytearray + self.assertIsInstance(buf, array_type) + self.assertIsInstance(b, bytes) + self.assertIsInstance(ba, bytearray) + self.assertEqual(buf, b'') + self.assertEqual(b, b'') + self.assertEqual(ba, b'') + def test_ints(self): for proto in protocols: n = sys.maxsize diff --git a/Misc/NEWS.d/next/Library/2026-04-27-17-12-11.gh-issue-148914.i5C3kW.rst b/Misc/NEWS.d/next/Library/2026-04-27-17-12-11.gh-issue-148914.i5C3kW.rst new file mode 100644 index 00000000000..8348aad0d89 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-27-17-12-11.gh-issue-148914.i5C3kW.rst @@ -0,0 +1,6 @@ +Fix memoization of in-band :class:`~pickle.PickleBuffer` in the Python +implementation of :mod:`pickle`. Previously, identical +:class:`!PickleBuffer`\ s did not preserve identity, and empty writable +:class:`!PickleBuffer` memoized an empty bytearray object in place of +``b''``, so the following references to ``b''`` were unpickled as an empty +bytearray object. From fea2a57282d243edd95c2166aa685c2568c47eaf Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Sat, 2 May 2026 14:23:16 +0500 Subject: [PATCH 747/775] GH-148932: Improve error message if profiling.sampling run from venv on Windows platform (#149247) --- Lib/profiling/sampling/sample.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/profiling/sampling/sample.py b/Lib/profiling/sampling/sample.py index 6a76bbeeb24..9195f5ee6dd 100644 --- a/Lib/profiling/sampling/sample.py +++ b/Lib/profiling/sampling/sample.py @@ -58,6 +58,10 @@ def __init__(self, pid, sample_interval_usec, all_threads, *, mode=PROFILING_MOD try: self.unwinder = self._new_unwinder(native, gc, opcodes, skip_non_matching_threads) except RuntimeError as err: + if os.name == "nt" and sys.executable.endswith("python.exe"): + raise SystemExit( + "Running profiling.sampling from virtualenv on Windows platform is not supported" + ) from err raise SystemExit(err) from err # Track sample intervals and total sample count self.sample_intervals = deque(maxlen=100) From 4f0cfe53cbb56c32b097f9c38d66444960b5f17f Mon Sep 17 00:00:00 2001 From: lighting9999 Date: Sat, 2 May 2026 20:55:43 +0800 Subject: [PATCH 748/775] gh-149221:Fix binomialvariate Function for random module (gh-149222) --- Lib/random.py | 7 ++++++- Lib/test/test_random.py | 6 ++++++ .../Library/2026-05-02-01-09-29.gh-issue-149221.__KOks.rst | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-05-02-01-09-29.gh-issue-149221.__KOks.rst diff --git a/Lib/random.py b/Lib/random.py index c89cbb755ab..dc037629bab 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -836,7 +836,12 @@ def binomialvariate(self, n=1, p=0.5): if not c: return x while True: - y += _floor(_log2(random()) / c) + 1 + try: + y += _floor(_log2(random()) / c) + 1 + # The random() function can return 0.0, which causes log2(0.0) to raise a ValueError. + # See https://github.com/python/cpython/issue/149221 + except ValueError: + continue if y > n: return x x += 1 diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 1e57b9244b4..dbd3b855f53 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -1075,6 +1075,12 @@ def test_avg_std(self): msg='%s%r' % (variate.__name__, args)) self.assertAlmostEqual(s2/(N-1), sigmasqrd, places=2, msg='%s%r' % (variate.__name__, args)) + def test_binomialvariate_log_zero(self): + # gh-149222: Variety random() return 0.0 no input Error + with unittest.mock.patch.object(random.Random, 'random', side_effect= [0.0] + [0.5] * 20): + result = random.binomialvariate(10, 0.5) + self.assertIsInstance(result, int) + self.assertIn(result, range(11)) def test_constant(self): g = random.Random() diff --git a/Misc/NEWS.d/next/Library/2026-05-02-01-09-29.gh-issue-149221.__KOks.rst b/Misc/NEWS.d/next/Library/2026-05-02-01-09-29.gh-issue-149221.__KOks.rst new file mode 100644 index 00000000000..fab2b0f6a23 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-02-01-09-29.gh-issue-149221.__KOks.rst @@ -0,0 +1 @@ +Catch rare math domain error for :func:`random.binomialvariate`. From da09ef807b162cdfbc58460b2eddf5b1a94881bb Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 2 May 2026 08:29:06 -0500 Subject: [PATCH 749/775] gh-149221: Minor comment edit (gh-149278) Minor comment edit --- Lib/random.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/random.py b/Lib/random.py index dc037629bab..726a71e7828 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -838,9 +838,8 @@ def binomialvariate(self, n=1, p=0.5): while True: try: y += _floor(_log2(random()) / c) + 1 - # The random() function can return 0.0, which causes log2(0.0) to raise a ValueError. - # See https://github.com/python/cpython/issue/149221 except ValueError: + # Reject case where random() returned 0.0 continue if y > n: return x From c7b7ca2cd5e01b607b7ed610d13b1ac28b977d1d Mon Sep 17 00:00:00 2001 From: Diego Russo Date: Sat, 2 May 2026 14:42:03 +0100 Subject: [PATCH 750/775] GH-126910: Add gdb support for unwinding JIT frames (#146071) Co-authored-by: Pablo Galindo Salgado --- Doc/c-api/perfmaps.rst | 2 +- Include/cpython/ceval.h | 2 +- Include/internal/pycore_ceval.h | 6 +- Include/internal/pycore_interp_structs.h | 2 +- Include/internal/pycore_jit.h | 2 +- Include/internal/pycore_jit_unwind.h | 68 ++ Include/internal/pycore_optimizer.h | 1 + Lib/test/test_gdb/gdb_jit_sample.py | 27 + Lib/test/test_gdb/test_jit.py | 201 ++++ Lib/test/test_gdb/util.py | 57 +- Lib/test/test_perfmaps.py | 17 +- Makefile.pre.in | 9 +- ...-03-17-20-30-17.gh-issue-126910.NaUwmD.rst | 1 + Modules/_testinternalcapi.c | 10 +- Modules/posixmodule.c | 8 + Python/ceval.c | 2 +- Python/ceval_macros.h | 1 - Python/jit.c | 45 + Python/jit_unwind.c | 986 ++++++++++++++++++ Python/optimizer.c | 1 + Python/perf_jit_trampoline.c | 897 +++------------- Python/perf_trampoline.c | 2 +- Python/sysmodule.c | 4 +- Tools/build/smelly.py | 2 + Tools/c-analyzer/cpython/_parser.py | 2 + Tools/c-analyzer/cpython/ignored.tsv | 2 + Tools/jit/README.md | 4 +- Tools/jit/_dwarf.py | 236 +++++ Tools/jit/_targets.py | 123 ++- Tools/jit/_writer.py | 26 +- Tools/jit/build.py | 55 +- Tools/jit/shim.c | 2 +- 32 files changed, 1993 insertions(+), 810 deletions(-) create mode 100644 Include/internal/pycore_jit_unwind.h create mode 100644 Lib/test/test_gdb/gdb_jit_sample.py create mode 100644 Lib/test/test_gdb/test_jit.py create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-20-30-17.gh-issue-126910.NaUwmD.rst create mode 100644 Python/jit_unwind.c create mode 100644 Tools/jit/_dwarf.py diff --git a/Doc/c-api/perfmaps.rst b/Doc/c-api/perfmaps.rst index 76a1e9f528d..bd05e628faa 100644 --- a/Doc/c-api/perfmaps.rst +++ b/Doc/c-api/perfmaps.rst @@ -31,7 +31,7 @@ Note that holding an :term:`attached thread state` is not required for these API or ``-2`` on failure to create a lock. Check ``errno`` for more information about the cause of a failure. -.. c:function:: int PyUnstable_WritePerfMapEntry(const void *code_addr, unsigned int code_size, const char *entry_name) +.. c:function:: int PyUnstable_WritePerfMapEntry(const void *code_addr, size_t code_size, const char *entry_name) Write one single entry to the ``/tmp/perf-$pid.map`` file. This function is thread safe. Here is what an example entry looks like:: diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h index bbab8d35b75..5b66fa1040d 100644 --- a/Include/cpython/ceval.h +++ b/Include/cpython/ceval.h @@ -38,7 +38,7 @@ typedef struct { PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void); PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry( const void *code_addr, - unsigned int code_size, + size_t code_size, const char *entry_name); PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void); PyAPI_FUNC(int) PyUnstable_CopyPerfMapFile(const char* parent_filename); diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index f9507fda160..fd4221f0816 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -94,7 +94,7 @@ typedef struct { void* (*init_state)(void); // Callback to register every trampoline being created void (*write_state)(void* state, const void *code_addr, - unsigned int code_size, PyCodeObject* code); + size_t code_size, PyCodeObject* code); // Callback to free the trampoline state int (*free_state)(void* state); } _PyPerf_Callbacks; @@ -108,6 +108,10 @@ extern PyStatus _PyPerfTrampoline_AfterFork_Child(void); #ifdef PY_HAVE_PERF_TRAMPOLINE extern _PyPerf_Callbacks _Py_perfmap_callbacks; extern _PyPerf_Callbacks _Py_perfmap_jit_callbacks; +extern void _PyPerfJit_WriteNamedCode(const void *code_addr, + size_t code_size, + const char *entry, + const char *filename); #endif static inline PyObject* diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index cccfe3565db..86f018e3286 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -69,7 +69,7 @@ struct code_arena_st; struct trampoline_api_st { void* (*init_state)(void); void (*write_state)(void* state, const void *code_addr, - unsigned int code_size, PyCodeObject* code); + size_t code_size, PyCodeObject* code); int (*free_state)(void* state); void *state; Py_ssize_t code_padding; diff --git a/Include/internal/pycore_jit.h b/Include/internal/pycore_jit.h index b3cadcce824..2f97cc26eaf 100644 --- a/Include/internal/pycore_jit.h +++ b/Include/internal/pycore_jit.h @@ -23,7 +23,7 @@ typedef _Py_CODEUNIT *(*jit_func)( _PyStackRef _tos_cache0, _PyStackRef _tos_cache1, _PyStackRef _tos_cache2 ); -_Py_CODEUNIT *_PyJIT( +_Py_CODEUNIT *_PyJIT_Entry( _PyExecutorObject *executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate ); diff --git a/Include/internal/pycore_jit_unwind.h b/Include/internal/pycore_jit_unwind.h new file mode 100644 index 00000000000..2d325ad9562 --- /dev/null +++ b/Include/internal/pycore_jit_unwind.h @@ -0,0 +1,68 @@ +#ifndef Py_INTERNAL_JIT_UNWIND_H +#define Py_INTERNAL_JIT_UNWIND_H + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include +#include + +#if defined(_Py_JIT) && defined(__linux__) && defined(__ELF__) +# define PY_HAVE_JIT_GDB_UNWIND +#endif + +#if defined(PY_HAVE_PERF_TRAMPOLINE) || defined(PY_HAVE_JIT_GDB_UNWIND) + +#if defined(PY_HAVE_JIT_GDB_UNWIND) +extern PyMutex _Py_jit_debug_mutex; +#endif + +/* DWARF exception-handling pointer encodings shared by JIT unwind users. */ +enum { + DWRF_EH_PE_absptr = 0x00, + DWRF_EH_PE_omit = 0xff, + + /* Data type encodings */ + DWRF_EH_PE_uleb128 = 0x01, + DWRF_EH_PE_udata2 = 0x02, + DWRF_EH_PE_udata4 = 0x03, + DWRF_EH_PE_udata8 = 0x04, + DWRF_EH_PE_sleb128 = 0x09, + DWRF_EH_PE_sdata2 = 0x0a, + DWRF_EH_PE_sdata4 = 0x0b, + DWRF_EH_PE_sdata8 = 0x0c, + DWRF_EH_PE_signed = 0x08, + + /* Reference type encodings */ + DWRF_EH_PE_pcrel = 0x10, + DWRF_EH_PE_textrel = 0x20, + DWRF_EH_PE_datarel = 0x30, + DWRF_EH_PE_funcrel = 0x40, + DWRF_EH_PE_aligned = 0x50, + DWRF_EH_PE_indirect = 0x80 +}; + +/* Return the size of the generated .eh_frame data for the given encoding. */ +size_t _PyJitUnwind_EhFrameSize(int absolute_addr); + +/* + * Build DWARF .eh_frame data for JIT code; returns size written or 0 on error. + * absolute_addr selects the FDE address encoding: + * - 0: PC-relative offsets (perf jitdump synthesized DSO). + * - nonzero: absolute addresses (GDB JIT in-memory ELF). + */ +size_t _PyJitUnwind_BuildEhFrame(uint8_t *buffer, size_t buffer_size, + const void *code_addr, size_t code_size, + int absolute_addr); + +void *_PyJitUnwind_GdbRegisterCode(const void *code_addr, + size_t code_size, + const char *entry, + const char *filename); + +void _PyJitUnwind_GdbUnregisterCode(void *handle); + +#endif // defined(PY_HAVE_PERF_TRAMPOLINE) || defined(PY_HAVE_JIT_GDB_UNWIND) + +#endif // Py_INTERNAL_JIT_UNWIND_H diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index f356d60ae5c..a0727c045e5 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -198,6 +198,7 @@ typedef struct _PyExecutorObject { uint32_t code_size; size_t jit_size; void *jit_code; + void *jit_gdb_handle; _PyExitData exits[1]; } _PyExecutorObject; diff --git a/Lib/test/test_gdb/gdb_jit_sample.py b/Lib/test/test_gdb/gdb_jit_sample.py new file mode 100644 index 00000000000..b439e82e8b3 --- /dev/null +++ b/Lib/test/test_gdb/gdb_jit_sample.py @@ -0,0 +1,27 @@ +# Sample script for use by test_gdb.test_jit + +import _testinternalcapi +import operator + + +WARMUP_ITERATIONS = _testinternalcapi.TIER2_THRESHOLD + 10 + + +def jit_bt_hot(depth, warming_up_caller=False): + if depth == 0: + if not warming_up_caller: + id(42) + return + + for iteration in range(WARMUP_ITERATIONS): + operator.call( + jit_bt_hot, + depth - 1, + warming_up_caller or iteration + 1 != WARMUP_ITERATIONS, + ) + + +# Warm the shared shim once without hitting builtin_id so the real run uses +# the steady-state shim path when GDB breaks inside id(42). +jit_bt_hot(1, warming_up_caller=True) +jit_bt_hot(1) diff --git a/Lib/test/test_gdb/test_jit.py b/Lib/test/test_gdb/test_jit.py new file mode 100644 index 00000000000..ea88d7b0a1f --- /dev/null +++ b/Lib/test/test_gdb/test_jit.py @@ -0,0 +1,201 @@ +import os +import platform +import re +import sys +import unittest + +from .util import setup_module, DebuggerTests + + +JIT_SAMPLE_SCRIPT = os.path.join(os.path.dirname(__file__), "gdb_jit_sample.py") +# In batch GDB, break in builtin_id() while it is running under JIT, +# then repeatedly "finish" until the selected frame is the JIT executor. +# That gives a deterministic backtrace starting with py::jit:executor. +# +# builtin_id() sits only a few helper frames above the JIT entry on this path. +# This bound is just a generous upper limit so the test fails clearly if the +# expected stack shape changes. +MAX_FINISH_STEPS = 20 +# After landing on the JIT entry frame, single-step a bounded number of +# instructions further into the blob so the backtrace is taken from JIT code +# itself rather than the immediate helper-return site. The exact number of +# steps is not significant: each step is cross-checked against the selected +# frame's symbol so the test fails loudly if stepping escapes the registered +# JIT region, instead of asserting against a misleading backtrace. +MAX_JIT_ENTRY_STEPS = 4 +EVAL_FRAME_RE = r"(_PyEval_EvalFrameDefault|_PyEval_Vector)" +JIT_EXECUTOR_FRAME = "py::jit:executor" +JIT_ENTRY_SYMBOL = "_PyJIT_Entry" +BACKTRACE_FRAME_RE = re.compile(r"^#\d+\s+.*$", re.MULTILINE) + +FINISH_TO_JIT_EXECUTOR = ( + "python exec(\"import gdb\\n" + f"target = {JIT_EXECUTOR_FRAME!r}\\n" + f"for _ in range({MAX_FINISH_STEPS}):\\n" + " frame = gdb.selected_frame()\\n" + " if frame is not None and frame.name() == target:\\n" + " break\\n" + " gdb.execute('finish')\\n" + "else:\\n" + " raise RuntimeError('did not reach %s' % target)\\n\")" +) +STEP_INSIDE_JIT_EXECUTOR = ( + "python exec(\"import gdb\\n" + f"target = {JIT_EXECUTOR_FRAME!r}\\n" + f"for _ in range({MAX_JIT_ENTRY_STEPS}):\\n" + " frame = gdb.selected_frame()\\n" + " if frame is None or frame.name() != target:\\n" + " raise RuntimeError('left JIT region during stepping: '\\n" + " + repr(frame and frame.name()))\\n" + " gdb.execute('si')\\n" + "frame = gdb.selected_frame()\\n" + "if frame is None or frame.name() != target:\\n" + " raise RuntimeError('stepped out of JIT region after si')\\n\")" +) + + +def setUpModule(): + setup_module() + + +# The GDB JIT interface registration is gated on __linux__ && __ELF__ in +# Python/jit_unwind.c, and the synthetic EH-frame is only implemented for +# x86_64 and AArch64 (a #error fires otherwise). Skip cleanly on other +# platforms or architectures instead of producing timeouts / empty backtraces. +# is_enabled() implies is_available() and also implies that the runtime has +# JIT execution active; interpreter-only tier 2 builds don't hit this path. +@unittest.skipUnless(sys.platform == "linux", + "GDB JIT interface is only implemented for Linux + ELF") +@unittest.skipUnless(platform.machine() in ("x86_64", "aarch64"), + "GDB JIT CFI emitter only supports x86_64 and AArch64") +@unittest.skipUnless(hasattr(sys, "_jit") and sys._jit.is_enabled(), + "requires a JIT-enabled build with JIT execution active") +class JitBacktraceTests(DebuggerTests): + def get_stack_trace(self, **kwargs): + # These tests validate the JIT-relevant part of the backtrace via + # _assert_jit_backtrace_shape, so an unrelated "?? ()" frame below + # the JIT/eval segment (e.g. libc without debug info) is tolerable. + kwargs.setdefault("skip_on_truncation", False) + return super().get_stack_trace(**kwargs) + + def _extract_backtrace_frames(self, gdb_output): + frames = BACKTRACE_FRAME_RE.findall(gdb_output) + self.assertGreater( + len(frames), 0, + f"expected at least one GDB backtrace frame in output:\n{gdb_output}", + ) + return frames + + def _assert_jit_backtrace_shape(self, gdb_output, *, anchor_at_top): + # Shape assertions applied to every JIT backtrace we produce: + # 1. The synthetic JIT symbol appears exactly once. A second + # py::jit:executor frame would mean the unwinder is + # materializing two native frames for a single logical JIT + # region, or failing to unwind out of the region entirely. + # 2. The unwinder must climb directly back out of the JIT region + # into the eval loop. _PyJIT_Entry only exists to establish the + # physical frame; the synthetic executor FDE collapses it away. + # 3. For tests that assert a specific entry PC, the JIT frame + # is also at #0. + frames = self._extract_backtrace_frames(gdb_output) + backtrace = "\n".join(frames) + + jit_frames = [frame for frame in frames if JIT_EXECUTOR_FRAME in frame] + jit_count = len(jit_frames) + self.assertEqual( + jit_count, 1, + f"expected exactly 1 {JIT_EXECUTOR_FRAME} frame, got {jit_count}\n" + f"backtrace:\n{backtrace}", + ) + eval_frames = [frame for frame in frames if re.search(EVAL_FRAME_RE, frame)] + eval_count = len(eval_frames) + self.assertGreaterEqual( + eval_count, 1, + f"expected at least one _PyEval_* frame, got {eval_count}\n" + f"backtrace:\n{backtrace}", + ) + jit_frame_index = next( + i for i, frame in enumerate(frames) if JIT_EXECUTOR_FRAME in frame + ) + frames_after_jit = frames[jit_frame_index + 1:] + first_eval_offset = next( + ( + i for i, frame in enumerate(frames_after_jit) + if re.search(EVAL_FRAME_RE, frame) + ), + None, + ) + self.assertIsNotNone( + first_eval_offset, + f"expected an eval frame after the JIT frame\n" + f"backtrace:\n{backtrace}", + ) + unexpected_between = frames_after_jit[:first_eval_offset] + self.assertFalse( + unexpected_between, + "expected the executor frame to unwind directly into eval\n" + f"backtrace:\n{backtrace}", + ) + relevant_end = max( + i + for i, frame in enumerate(frames) + if ( + JIT_EXECUTOR_FRAME in frame + or re.search(EVAL_FRAME_RE, frame) + ) + ) + truncated_frames = [ + frame for frame in frames[: relevant_end + 1] + if " ?? ()" in frame + ] + self.assertFalse( + truncated_frames, + "unexpected truncated frame before the validated JIT/eval segment\n" + f"backtrace:\n{backtrace}", + ) + if anchor_at_top: + self.assertRegex( + frames[0], + re.compile(rf"^#0\s+{re.escape(JIT_EXECUTOR_FRAME)}"), + ) + + def test_bt_unwinds_through_jit_frames(self): + gdb_output = self.get_stack_trace( + script=JIT_SAMPLE_SCRIPT, + cmds_after_breakpoint=["bt"], + PYTHON_JIT="1", + ) + # The executor should appear as a named JIT frame and unwind back into + # the eval loop. + self._assert_jit_backtrace_shape(gdb_output, anchor_at_top=False) + + def test_bt_handoff_from_jit_entry_to_executor(self): + gdb_output = self.get_stack_trace( + script=JIT_SAMPLE_SCRIPT, + breakpoint=JIT_ENTRY_SYMBOL, + cmds_after_breakpoint=[ + "delete 1", + "tbreak builtin_id", + "continue", + "bt", + ], + PYTHON_JIT="1", + ) + # If we stop first in the shim and then continue into the real JIT + # workload, the final backtrace should match the architecture's + # executor unwind contract. + self._assert_jit_backtrace_shape(gdb_output, anchor_at_top=False) + + def test_bt_unwinds_from_inside_jit_executor(self): + gdb_output = self.get_stack_trace( + script=JIT_SAMPLE_SCRIPT, + cmds_after_breakpoint=[ + FINISH_TO_JIT_EXECUTOR, + STEP_INSIDE_JIT_EXECUTOR, + "bt", + ], + PYTHON_JIT="1", + ) + # Once the selected PC is inside the JIT executor, we require that GDB + # identifies the JIT frame at #0 and keeps unwinding into _PyEval_*. + self._assert_jit_backtrace_shape(gdb_output, anchor_at_top=True) diff --git a/Lib/test/test_gdb/util.py b/Lib/test/test_gdb/util.py index 8097fd52aba..d903adcf290 100644 --- a/Lib/test/test_gdb/util.py +++ b/Lib/test/test_gdb/util.py @@ -20,6 +20,27 @@ PYTHONHASHSEED = '123' +# gh-91960, bpo-40019: gdb reports these when the optimizer has dropped +# python-frame debug info; the test can't read what's not there. +_OPTIMIZED_OUT_PATTERNS = ( + '(frame information optimized out)', + 'Unable to read information on python frame', + '(unable to read python frame information)', +) +# gdb prints this when the unwinder genuinely failed to walk a frame — +# i.e. the CFI (ours or a library's) is wrong. Treat as a hard failure, +# not a skip, so regressions in our own unwind info don't hide. +_UNWIND_FAILURE_PATTERNS = ( + 'Backtrace stopped: frame did not save the PC', +) +# gh-104736: " ?? ()" in the bt usually means the unwinder bailed early, +# but can also be unrelated frames without debug info (e.g. libc). Tests +# that validate the JIT-relevant part of the backtrace themselves can +# opt out via skip_on_truncation=False. +_TRUNCATED_BACKTRACE_PATTERNS = ( + ' ?? ()', +) + def clean_environment(): # Remove PYTHON* environment variables such as PYTHONHOME @@ -160,7 +181,9 @@ def get_stack_trace(self, source=None, script=None, breakpoint=BREAKPOINT_FN, cmds_after_breakpoint=None, import_site=False, - ignore_stderr=False): + ignore_stderr=False, + skip_on_truncation=True, + **env_vars): ''' Run 'python -c SOURCE' under gdb with a breakpoint. @@ -239,7 +262,7 @@ def get_stack_trace(self, source=None, script=None, args += [script] # Use "args" to invoke gdb, capturing stdout, stderr: - out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED) + out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED, **env_vars) if not ignore_stderr: for line in err.splitlines(): @@ -255,26 +278,20 @@ def get_stack_trace(self, source=None, script=None, " because the Program Counter is" " not present") + for pattern in _UNWIND_FAILURE_PATTERNS: + if pattern in out: + raise AssertionError( + f"gdb unwinder failed ({pattern!r}) — CFI bug in our " + f"generated code or in a linked library.\n" + f"Full gdb output:\n{out}" + ) + # bpo-40019: Skip the test if gdb failed to read debug information # because the Python binary is optimized. - for pattern in ( - '(frame information optimized out)', - 'Unable to read information on python frame', - - # gh-91960: On Python built with "clang -Og", gdb gets - # "frame=" for _PyEval_EvalFrameDefault() parameter - '(unable to read python frame information)', - - # gh-104736: On Python built with "clang -Og" on ppc64le, - # "py-bt" displays a truncated or not traceback, but "where" - # logs this error message: - 'Backtrace stopped: frame did not save the PC', - - # gh-104736: When "bt" command displays something like: - # "#1 0x0000000000000000 in ?? ()", the traceback is likely - # truncated or wrong. - ' ?? ()', - ): + patterns = _OPTIMIZED_OUT_PATTERNS + if skip_on_truncation: + patterns = patterns + _TRUNCATED_BACKTRACE_PATTERNS + for pattern in patterns: if pattern in out: raise unittest.SkipTest(f"{pattern!r} found in gdb output") diff --git a/Lib/test/test_perfmaps.py b/Lib/test/test_perfmaps.py index 647c32656ab..ee4eb50033c 100644 --- a/Lib/test/test_perfmaps.py +++ b/Lib/test/test_perfmaps.py @@ -1,4 +1,5 @@ import os +import sys import sysconfig import unittest @@ -17,6 +18,9 @@ def supports_trampoline_profiling(): raise unittest.SkipTest("perf trampoline profiling not supported") class TestPerfMapWriting(unittest.TestCase): + def tearDown(self): + perf_map_state_teardown() + def test_write_perf_map_entry(self): self.assertEqual(write_perf_map_entry(0x1234, 5678, "entry1"), 0) self.assertEqual(write_perf_map_entry(0x2345, 6789, "entry2"), 0) @@ -24,4 +28,15 @@ def test_write_perf_map_entry(self): perf_file_contents = f.read() self.assertIn("1234 162e entry1", perf_file_contents) self.assertIn("2345 1a85 entry2", perf_file_contents) - perf_map_state_teardown() + + @unittest.skipIf(sys.maxsize <= 2**32, "requires size_t wider than unsigned int") + def test_write_perf_map_entry_large_size(self): + code_addr = 0x3456 + code_size = 1 << 33 + entry_name = "entry_big" + + self.assertEqual(write_perf_map_entry(code_addr, code_size, entry_name), 0) + with open(f"/tmp/perf-{os.getpid()}.map") as f: + perf_file_contents = f.read() + self.assertIn(f"{code_addr:x} {code_size:x} {entry_name}", + perf_file_contents) diff --git a/Makefile.pre.in b/Makefile.pre.in index 0edf55d991a..fc44399434f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -514,6 +514,7 @@ PYTHON_OBJS= \ Python/suggestions.o \ Python/perf_trampoline.o \ Python/perf_jit_trampoline.o \ + Python/jit_unwind.o \ Python/remote_debugging.o \ Python/$(DYNLOADFILE) \ $(LIBOBJS) \ @@ -3209,7 +3210,8 @@ Python/emscripten_trampoline_wasm.c: Python/emscripten_trampoline_inner.wasm $(PYTHON_FOR_REGEN) $(srcdir)/Platforms/emscripten/prepare_external_wasm.py $< $@ getWasmTrampolineModule JIT_SHIM_BUILD_OBJS= @JIT_SHIM_BUILD_O@ -JIT_BUILD_TARGETS= jit_stencils.h @JIT_STENCILS_H@ $(JIT_SHIM_BUILD_OBJS) +JIT_UNWIND_INFO_H= $(if $(JIT_OBJS),jit_unwind_info.h $(patsubst jit_stencils-%.h,jit_unwind_info-%.h,@JIT_STENCILS_H@)) +JIT_BUILD_TARGETS= jit_stencils.h @JIT_STENCILS_H@ $(JIT_UNWIND_INFO_H) $(JIT_SHIM_BUILD_OBJS) JIT_TARGETS= $(JIT_BUILD_TARGETS) $(filter-out $(JIT_SHIM_BUILD_OBJS),$(JIT_OBJS)) JIT_GENERATED_STAMP= .jit-stamp @@ -3237,6 +3239,9 @@ jit_shim-universal2-apple-darwin.o: jit_shim-aarch64-apple-darwin.o jit_shim-x86 Python/jit.o: $(srcdir)/Python/jit.c @JIT_STENCILS_H@ $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< +Python/jit_unwind.o: $(srcdir)/Python/jit_unwind.c $(JIT_UNWIND_INFO_H) + $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + .PHONY: regen-jit regen-jit: $(JIT_TARGETS) @@ -3362,7 +3367,7 @@ clean-profile: clean-retain-profile clean-bolt # gh-141808: The JIT stencils are deliberately kept in clean-profile .PHONY: clean-jit-stencils clean-jit-stencils: - -rm -f $(JIT_TARGETS) $(JIT_GENERATED_STAMP) jit_stencils*.h jit_shim*.o + -rm -f $(JIT_TARGETS) $(JIT_GENERATED_STAMP) jit_stencils*.h jit_unwind_info*.h jit_shim*.o .PHONY: clean clean: clean-profile clean-jit-stencils diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-20-30-17.gh-issue-126910.NaUwmD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-20-30-17.gh-issue-126910.NaUwmD.rst new file mode 100644 index 00000000000..4d2634d0dd1 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-17-20-30-17.gh-issue-126910.NaUwmD.rst @@ -0,0 +1 @@ +Add support for unwinding JIT frames using GDB. Patch by Diego Russo and Pablo Galindo. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 5319d9c7a48..a07675bb66d 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1256,16 +1256,22 @@ write_perf_map_entry(PyObject *self, PyObject *args) { PyObject *code_addr_v; const void *code_addr; - unsigned int code_size; + PyObject *code_size_s; + size_t code_size; const char *entry_name; - if (!PyArg_ParseTuple(args, "OIs", &code_addr_v, &code_size, &entry_name)) + if (!PyArg_ParseTuple(args, "OOs", &code_addr_v, &code_size_s, &entry_name)) return NULL; code_addr = PyLong_AsVoidPtr(code_addr_v); if (code_addr == NULL) { return NULL; } + code_size = PyLong_AsSize_t(code_size_s); + if (code_size == (size_t)-1 && PyErr_Occurred()) { + return NULL; + } + int ret = PyUnstable_WritePerfMapEntry(code_addr, code_size, entry_name); if (ret < 0) { PyErr_SetFromErrno(PyExc_OSError); diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 3bdbf2ef816..5bd53c2146a 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -20,6 +20,7 @@ #include "pycore_fileutils.h" // _Py_closerange() #include "pycore_import.h" // _PyImport_AcquireLock() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() +#include "pycore_jit_unwind.h" // _Py_jit_debug_mutex #include "pycore_long.h" // _PyLong_IsNegative() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyObject_LookupSpecial() @@ -758,6 +759,13 @@ PyOS_AfterFork_Child(void) goto fatal_error; } +#if defined(PY_HAVE_JIT_GDB_UNWIND) + // The child can inherit this mutex locked if another thread held it at + // fork(), but the child itself cannot be inside gdb_jit_register_code(). + // Reinitialize it before any executor cleanup can unregister JIT code. + _Py_jit_debug_mutex = (PyMutex){0}; +#endif + reset_remotedebug_data(tstate); reset_asyncio_state((_PyThreadStateImpl *)tstate); diff --git a/Python/ceval.c b/Python/ceval.c index 0d7f8a62e24..28087ba58d4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1305,7 +1305,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } #ifdef _Py_TIER2 #ifdef _Py_JIT -_PyJitEntryFuncPtr _Py_jit_entry = _PyJIT; +_PyJitEntryFuncPtr _Py_jit_entry = _PyJIT_Entry; #else _PyJitEntryFuncPtr _Py_jit_entry = _PyTier2Interpreter; #endif diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index a7d63fd3b82..a4e9980589e 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -168,7 +168,6 @@ #define STOP_TRACING() ((void)(0)); #endif - /* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */ #ifdef Py_DEBUG #define PRE_DISPATCH_GOTO() if (frame->lltrace >= 5) { \ diff --git a/Python/jit.c b/Python/jit.c index 26e01b25d48..8b555105129 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -15,6 +15,7 @@ #include "pycore_interpframe.h" #include "pycore_interpolation.h" #include "pycore_intrinsics.h" +#include "pycore_jit_unwind.h" #include "pycore_lazyimportobject.h" #include "pycore_list.h" #include "pycore_long.h" @@ -60,6 +61,40 @@ jit_error(const char *message) PyErr_Format(PyExc_RuntimeWarning, "JIT %s (%d)", message, hint); } +/* + * Publish JIT code to optional tooling backends. + * + * The return value is a backend-specific deregistration handle, not a + * success/failure indicator. NULL means there is nothing to unregister later: + * perf does not need a handle, and GDB registration failures are intentionally + * non-fatal because tooling support must not make JIT compilation fail. + */ +static void * +jit_record_code(const void *code_addr, size_t code_size, + const char *entry, const char *filename) +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + _PyPerf_Callbacks callbacks; + _PyPerfTrampoline_GetCallbacks(&callbacks); + if (callbacks.write_state == _Py_perfmap_jit_callbacks.write_state) { + _PyPerfJit_WriteNamedCode( + code_addr, code_size, entry, filename); + return NULL; + } +#endif + +#if defined(PY_HAVE_JIT_GDB_UNWIND) + return _PyJitUnwind_GdbRegisterCode( + code_addr, code_size, entry, filename); +#else + (void)code_addr; + (void)code_size; + (void)entry; + (void)filename; + return NULL; +#endif +} + static int address_in_executor_array(_PyExecutorObject **ptrs, size_t count, uintptr_t addr) { @@ -715,6 +750,10 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], siz } executor->jit_code = memory; executor->jit_size = total_size; + executor->jit_gdb_handle = jit_record_code(memory, + code_size + state.trampolines.size, + "jit", + "executor"); return 0; } @@ -727,6 +766,12 @@ _PyJIT_Free(_PyExecutorObject *executor) if (memory) { executor->jit_code = NULL; executor->jit_size = 0; +#if defined(PY_HAVE_JIT_GDB_UNWIND) + if (executor->jit_gdb_handle != NULL) { + _PyJitUnwind_GdbUnregisterCode(executor->jit_gdb_handle); + executor->jit_gdb_handle = NULL; + } +#endif if (jit_free(memory, size)) { PyErr_FormatUnraisable("Exception ignored while " "freeing JIT memory"); diff --git a/Python/jit_unwind.c b/Python/jit_unwind.c new file mode 100644 index 00000000000..09002feafec --- /dev/null +++ b/Python/jit_unwind.c @@ -0,0 +1,986 @@ +/* + * Python JIT - DWARF .eh_frame builder + * + * This file contains the DWARF CFI generator used to build .eh_frame + * data for JIT code (perf jitdump and other unwinders). + */ + +#include "Python.h" +#include "pycore_jit_unwind.h" +#include "pycore_lock.h" + +#if defined(PY_HAVE_JIT_GDB_UNWIND) +# include "jit_unwind_info.h" +# if !JIT_UNWIND_INFO_SUPPORTED +# error "JIT unwind info was not generated for this target" +# endif +#endif + +#if defined(PY_HAVE_PERF_TRAMPOLINE) || defined(PY_HAVE_JIT_GDB_UNWIND) + +#if defined(PY_HAVE_JIT_GDB_UNWIND) +# include +#endif +#include +#include + +// ============================================================================= +// DWARF CONSTANTS +// ============================================================================= + +/* + * DWARF (Debug With Arbitrary Record Formats) constants + * + * DWARF is a debugging data format used to provide stack unwinding information. + * These constants define the various encoding types and opcodes used in + * DWARF Call Frame Information (CFI) records. + */ + +/* DWARF Call Frame Information version */ +#define DWRF_CIE_VERSION 1 + +/* DWARF CFA (Call Frame Address) opcodes */ +enum { + DWRF_CFA_nop = 0x0, // No operation + DWRF_CFA_offset_extended = 0x5, // Extended offset instruction + DWRF_CFA_def_cfa = 0xc, // Define CFA rule + DWRF_CFA_def_cfa_register = 0xd, // Define CFA register + DWRF_CFA_def_cfa_offset = 0xe, // Define CFA offset + DWRF_CFA_offset_extended_sf = 0x11, // Extended signed offset + DWRF_CFA_advance_loc = 0x40, // Advance location counter + DWRF_CFA_offset = 0x80, // Simple offset instruction + DWRF_CFA_restore = 0xc0 // Restore register +}; + +/* + * Architecture-specific DWARF register numbers + * + * These constants define the register numbering scheme used by DWARF + * for each supported architecture. The numbers must match the ABI + * specification for proper stack unwinding. + */ +enum { +#ifdef __x86_64__ + /* x86_64 register numbering (note: order is defined by x86_64 ABI) */ + DWRF_REG_AX, // RAX + DWRF_REG_DX, // RDX + DWRF_REG_CX, // RCX + DWRF_REG_BX, // RBX + DWRF_REG_SI, // RSI + DWRF_REG_DI, // RDI + DWRF_REG_BP, // RBP + DWRF_REG_SP, // RSP + DWRF_REG_8, // R8 + DWRF_REG_9, // R9 + DWRF_REG_10, // R10 + DWRF_REG_11, // R11 + DWRF_REG_12, // R12 + DWRF_REG_13, // R13 + DWRF_REG_14, // R14 + DWRF_REG_15, // R15 + DWRF_REG_RA, // Return address (RIP) +#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) + /* AArch64 register numbering */ + DWRF_REG_FP = 29, // Frame Pointer + DWRF_REG_RA = 30, // Link register (return address) + DWRF_REG_SP = 31, // Stack pointer +#else +# error "Unsupported target architecture" +#endif +}; + +// ============================================================================= +// ELF OBJECT CONTEXT +// ============================================================================= + +/* + * Context for building ELF/DWARF structures + * + * This structure maintains state while constructing DWARF unwind information. + * It acts as a simple buffer manager with pointers to track current position + * and important landmarks within the buffer. + */ +typedef struct ELFObjectContext { + uint8_t* p; // Current write position in buffer + uint8_t* startp; // Start of buffer (for offset calculations) + uint8_t* fde_p; // Start of FDE data (for PC-relative calculations) + uintptr_t code_addr; // Address of the code section + size_t code_size; // Size of the code section +} ELFObjectContext; + +// ============================================================================= +// DWARF GENERATION UTILITIES +// ============================================================================= + +/* + * Append a null-terminated string to the ELF context buffer. + * + * Args: + * ctx: ELF object context + * str: String to append (must be null-terminated) + * + * Returns: Offset from start of buffer where string was written + */ +static uint32_t elfctx_append_string(ELFObjectContext* ctx, const char* str) { + uint8_t* p = ctx->p; + uint32_t ofs = (uint32_t)(p - ctx->startp); + + /* Copy string including null terminator */ + do { + *p++ = (uint8_t)*str; + } while (*str++); + + ctx->p = p; + return ofs; +} + +/* + * Append a SLEB128 (Signed Little Endian Base 128) value + * + * SLEB128 is a variable-length encoding used extensively in DWARF. + * It efficiently encodes small numbers in fewer bytes. + * + * Args: + * ctx: ELF object context + * v: Signed value to encode + */ +static void elfctx_append_sleb128(ELFObjectContext* ctx, int32_t v) { + uint8_t* p = ctx->p; + + /* Encode 7 bits at a time, with continuation bit in MSB */ + for (; (uint32_t)(v + 0x40) >= 0x80; v >>= 7) { + *p++ = (uint8_t)((v & 0x7f) | 0x80); // Set continuation bit + } + *p++ = (uint8_t)(v & 0x7f); // Final byte without continuation bit + + ctx->p = p; +} + +/* + * Append a ULEB128 (Unsigned Little Endian Base 128) value + * + * Similar to SLEB128 but for unsigned values. + * + * Args: + * ctx: ELF object context + * v: Unsigned value to encode + */ +static void elfctx_append_uleb128(ELFObjectContext* ctx, uint32_t v) { + uint8_t* p = ctx->p; + + /* Encode 7 bits at a time, with continuation bit in MSB */ + for (; v >= 0x80; v >>= 7) { + *p++ = (char)((v & 0x7f) | 0x80); // Set continuation bit + } + *p++ = (char)v; // Final byte without continuation bit + + ctx->p = p; +} + +/* + * Macros for generating DWARF structures + * + * These macros provide a convenient way to write various data types + * to the DWARF buffer while automatically advancing the pointer. + */ +#define DWRF_U8(x) (*p++ = (x)) // Write unsigned 8-bit +#define DWRF_I8(x) (*(int8_t*)p = (x), p++) // Write signed 8-bit +#define DWRF_U16(x) (*(uint16_t*)p = (x), p += 2) // Write unsigned 16-bit +#define DWRF_U32(x) (*(uint32_t*)p = (x), p += 4) // Write unsigned 32-bit +#define DWRF_ADDR(x) (*(uintptr_t*)p = (x), p += sizeof(uintptr_t)) // Write address +#define DWRF_UV(x) (ctx->p = p, elfctx_append_uleb128(ctx, (x)), p = ctx->p) // Write ULEB128 +#define DWRF_SV(x) (ctx->p = p, elfctx_append_sleb128(ctx, (x)), p = ctx->p) // Write SLEB128 +#define DWRF_STR(str) (ctx->p = p, elfctx_append_string(ctx, (str)), p = ctx->p) // Write string + +/* Align to specified boundary with NOP instructions */ +#define DWRF_ALIGNNOP(s) \ + while ((uintptr_t)p & ((s)-1)) { \ + *p++ = DWRF_CFA_nop; \ + } + +/* Write a DWARF section with automatic size calculation */ +#define DWRF_SECTION(name, stmt) \ + { \ + uint32_t* szp_##name = (uint32_t*)p; \ + p += 4; \ + stmt; \ + *szp_##name = (uint32_t)((p - (uint8_t*)szp_##name) - 4); \ + } + +// ============================================================================= +// DWARF EH FRAME GENERATION +// ============================================================================= + +static void elf_init_ehframe_perf(ELFObjectContext* ctx); +#if defined(PY_HAVE_JIT_GDB_UNWIND) +static void elf_init_ehframe_gdb(ELFObjectContext* ctx); +#endif + +static inline void elf_init_ehframe(ELFObjectContext* ctx, int absolute_addr) { + if (absolute_addr) { +#if defined(PY_HAVE_JIT_GDB_UNWIND) + elf_init_ehframe_gdb(ctx); +#else + Py_UNREACHABLE(); +#endif + } + else { + elf_init_ehframe_perf(ctx); + } +} + +size_t +_PyJitUnwind_EhFrameSize(int absolute_addr) +{ + /* The .eh_frame we emit is small and bounded; keep a generous buffer. */ + uint8_t scratch[512]; + _Static_assert(sizeof(scratch) >= 256, + "scratch buffer may be too small for elf_init_ehframe"); + ELFObjectContext ctx; + ctx.code_size = 1; + ctx.code_addr = 0; + ctx.startp = ctx.p = scratch; + ctx.fde_p = NULL; + /* Generate once into scratch to learn the required size. */ + elf_init_ehframe(&ctx, absolute_addr); + ptrdiff_t size = ctx.p - ctx.startp; + assert(size <= (ptrdiff_t)sizeof(scratch)); + return (size_t)size; +} + +size_t +_PyJitUnwind_BuildEhFrame(uint8_t *buffer, size_t buffer_size, + const void *code_addr, size_t code_size, + int absolute_addr) +{ + if (buffer == NULL || code_addr == NULL || code_size == 0) { + return 0; + } + /* Generate the frame twice: once to size-check, once to write. */ + size_t required = _PyJitUnwind_EhFrameSize(absolute_addr); + if (required == 0 || required > buffer_size) { + return 0; + } + ELFObjectContext ctx; + ctx.code_size = code_size; + ctx.code_addr = (uintptr_t)code_addr; + ctx.startp = ctx.p = buffer; + ctx.fde_p = NULL; + elf_init_ehframe(&ctx, absolute_addr); + size_t written = (size_t)(ctx.p - ctx.startp); + /* The frame size is independent of code_addr/code_size (fixed-width fields). */ + assert(written == required); + return written; +} + +/* + * Generate a minimal .eh_frame for a single JIT code region. + * + * The .eh_frame section contains Call Frame Information (CFI) that describes + * how to unwind the stack at any point in the code. This is essential for + * unwinding through JIT-generated code. + * + * The generated data contains: + * 1. A CIE (Common Information Entry) describing the calling convention. + * 2. An FDE (Frame Description Entry) describing how to unwind the JIT frame. + * + * Two flavors are emitted, dispatched on the absolute_addr flag: + * + * - absolute_addr == 0 (elf_init_ehframe_perf): PC-relative FDE address + * encoding for perf's synthesized DSO layout. The CIE describes the + * trampoline's entry state and the FDE walks through the prologue and + * epilogue with advance_loc instructions. This matches the pre-existing + * perf_jit_trampoline behavior byte-for-byte. + * + * - absolute_addr == 1 (elf_init_ehframe_gdb): absolute FDE address + * encoding for the GDB JIT in-memory ELF. The CIE describes the + * steady-state frame layout (CFA = %rbp+16 / x29+16, with saved fp and + * return-address column at fixed offsets) and the FDE emits no further + * CFI. The same rule applies at every PC in the registered region, + * which is correct for executor stencils (they pin the frame pointer + * across the region). This is the GDB-side fix; see elf_init_ehframe_gdb + * for details. + */ +static void elf_init_ehframe_perf(ELFObjectContext* ctx) { + int fde_ptr_enc = DWRF_EH_PE_pcrel | DWRF_EH_PE_sdata4; + uint8_t* p = ctx->p; + uint8_t* framep = p; // Remember start of frame data + + /* + * DWARF Unwind Table for Trampoline Function + * + * This section defines DWARF Call Frame Information (CFI) using encoded macros + * like `DWRF_U8`, `DWRF_UV`, and `DWRF_SECTION` to describe how the trampoline function + * preserves and restores registers. This is used by profiling tools (e.g., `perf`) + * and debuggers for stack unwinding in JIT-compiled code. + * + * ------------------------------------------------- + * TO REGENERATE THIS TABLE FROM GCC OBJECTS: + * ------------------------------------------------- + * + * 1. Create a trampoline source file (e.g., `trampoline.c`): + * + * #include + * typedef PyObject* (*py_evaluator)(void*, void*, int); + * PyObject* trampoline(void *ts, void *f, int throwflag, py_evaluator evaluator) { + * return evaluator(ts, f, throwflag); + * } + * + * 2. Compile to an object file with frame pointer preservation: + * + * gcc trampoline.c -I. -I./Include -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -c + * + * 3. Extract DWARF unwind info from the object file: + * + * readelf -w trampoline.o + * + * Example output from `.eh_frame`: + * + * 00000000 CIE + * Version: 1 + * Augmentation: "zR" + * Code alignment factor: 4 + * Data alignment factor: -8 + * Return address column: 30 + * DW_CFA_def_cfa: r31 (sp) ofs 0 + * + * 00000014 FDE cie=00000000 pc=0..14 + * DW_CFA_advance_loc: 4 + * DW_CFA_def_cfa_offset: 16 + * DW_CFA_offset: r29 at cfa-16 + * DW_CFA_offset: r30 at cfa-8 + * DW_CFA_advance_loc: 12 + * DW_CFA_restore: r30 + * DW_CFA_restore: r29 + * DW_CFA_def_cfa_offset: 0 + * + * -- These values can be verified by comparing with `readelf -w` or `llvm-dwarfdump --eh-frame`. + * + * ---------------------------------- + * HOW TO TRANSLATE TO DWRF_* MACROS: + * ---------------------------------- + * + * After compiling your trampoline with: + * + * gcc trampoline.c -I. -I./Include -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -c + * + * run: + * + * readelf -w trampoline.o + * + * to inspect the generated `.eh_frame` data. You will see two main components: + * + * 1. A CIE (Common Information Entry): shared configuration used by all FDEs. + * 2. An FDE (Frame Description Entry): function-specific unwind instructions. + * + * --------------------- + * Translating the CIE: + * --------------------- + * From `readelf -w`, you might see: + * + * 00000000 0000000000000010 00000000 CIE + * Version: 1 + * Augmentation: "zR" + * Code alignment factor: 4 + * Data alignment factor: -8 + * Return address column: 30 + * Augmentation data: 1b + * DW_CFA_def_cfa: r31 (sp) ofs 0 + * + * Map this to: + * + * DWRF_SECTION(CIE, + * DWRF_U32(0); // CIE ID (always 0 for CIEs) + * DWRF_U8(DWRF_CIE_VERSION); // Version: 1 + * DWRF_STR("zR"); // Augmentation string "zR" + * DWRF_UV(4); // Code alignment factor = 4 + * DWRF_SV(-8); // Data alignment factor = -8 + * DWRF_U8(DWRF_REG_RA); // Return address register (e.g., x30 = 30) + * DWRF_UV(1); // Augmentation data length = 1 + * DWRF_U8(DWRF_EH_PE_pcrel | DWRF_EH_PE_sdata4); // Encoding for FDE pointers + * + * DWRF_U8(DWRF_CFA_def_cfa); // DW_CFA_def_cfa + * DWRF_UV(DWRF_REG_SP); // Register: SP (r31) + * DWRF_UV(0); // Offset = 0 + * + * DWRF_ALIGNNOP(sizeof(uintptr_t)); // Align to pointer size boundary + * ) + * + * Notes: + * - Use `DWRF_UV` for unsigned LEB128, `DWRF_SV` for signed LEB128. + * - `DWRF_REG_RA` and `DWRF_REG_SP` are architecture-defined constants. + * + * --------------------- + * Translating the FDE: + * --------------------- + * From `readelf -w`: + * + * 00000014 0000000000000020 00000018 FDE cie=00000000 pc=0000000000000000..0000000000000014 + * DW_CFA_advance_loc: 4 + * DW_CFA_def_cfa_offset: 16 + * DW_CFA_offset: r29 at cfa-16 + * DW_CFA_offset: r30 at cfa-8 + * DW_CFA_advance_loc: 12 + * DW_CFA_restore: r30 + * DW_CFA_restore: r29 + * DW_CFA_def_cfa_offset: 0 + * + * Map the FDE header and instructions to: + * + * DWRF_SECTION(FDE, + * DWRF_U32((uint32_t)(p - framep)); // Offset to CIE (relative from here) + * DWRF_U32(pc_relative_offset); // PC-relative location of the code (calculated dynamically) + * DWRF_U32(ctx->code_size); // Code range covered by this FDE + * DWRF_U8(0); // Augmentation data length (none) + * + * DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance location by 1 unit (1 * 4 = 4 bytes) + * DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 16 + * DWRF_UV(16); + * + * DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // Save x29 (frame pointer) + * DWRF_UV(2); // At offset 2 * 8 = 16 bytes + * + * DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // Save x30 (return address) + * DWRF_UV(1); // At offset 1 * 8 = 8 bytes + * + * DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance location by 3 units (3 * 4 = 12 bytes) + * + * DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // Restore x30 + * DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // Restore x29 + * + * DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + * DWRF_UV(0); + * ) + * + * To regenerate: + * 1. Get the `code alignment factor`, `data alignment factor`, and `RA column` from the CIE. + * 2. Note the range of the function from the FDE's `pc=...` line and map it to the JIT code as + * the code is in a different address space every time. + * 3. For each `DW_CFA_*` entry, use the corresponding `DWRF_*` macro: + * - `DW_CFA_def_cfa_offset` → DWRF_U8(DWRF_CFA_def_cfa_offset), DWRF_UV(value) + * - `DW_CFA_offset: rX` → DWRF_U8(DWRF_CFA_offset | reg), DWRF_UV(offset) + * - `DW_CFA_restore: rX` → DWRF_U8(DWRF_CFA_offset | reg) // restore is same as reusing offset + * - `DW_CFA_advance_loc: N` → DWRF_U8(DWRF_CFA_advance_loc | (N / code_alignment_factor)) + * 4. Use `DWRF_REG_FP`, `DWRF_REG_RA`, etc., for register numbers. + * 5. Use `sizeof(uintptr_t)` (typically 8) for pointer size calculations and alignment. + */ + + /* + * Emit DWARF EH CIE (Common Information Entry) + * + * The CIE describes the calling conventions and basic unwinding rules + * that apply to all functions in this compilation unit. + */ + DWRF_SECTION(CIE, + DWRF_U32(0); // CIE ID (0 indicates this is a CIE) + DWRF_U8(DWRF_CIE_VERSION); // CIE version (1) + DWRF_STR("zR"); // Augmentation string ("zR" = has LSDA) +#ifdef __x86_64__ + DWRF_UV(1); // Code alignment factor (x86_64: 1 byte) +#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) + DWRF_UV(4); // Code alignment factor (AArch64: 4 bytes per instruction) +#endif + DWRF_SV(-(int64_t)sizeof(uintptr_t)); // Data alignment factor (negative) + DWRF_U8(DWRF_REG_RA); // Return address register number + DWRF_UV(1); // Augmentation data length + DWRF_U8(fde_ptr_enc); // FDE pointer encoding + + /* Initial CFI instructions - describe default calling convention */ +#ifdef __x86_64__ + /* x86_64 initial CFI state */ + DWRF_U8(DWRF_CFA_def_cfa); // Define CFA (Call Frame Address) + DWRF_UV(DWRF_REG_SP); // CFA = SP register + DWRF_UV(sizeof(uintptr_t)); // CFA = SP + pointer_size + DWRF_U8(DWRF_CFA_offset|DWRF_REG_RA); // Return address is saved + DWRF_UV(1); // At offset 1 from CFA +#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) + /* AArch64 initial CFI state */ + DWRF_U8(DWRF_CFA_def_cfa); // Define CFA (Call Frame Address) + DWRF_UV(DWRF_REG_SP); // CFA = SP register + DWRF_UV(0); // CFA = SP + 0 (AArch64 starts with offset 0) + // No initial register saves in AArch64 CIE +#endif + DWRF_ALIGNNOP(sizeof(uintptr_t)); // Align to pointer boundary + ) + + /* + * Emit DWARF EH FDE (Frame Description Entry) + * + * The FDE describes unwinding information specific to this function. + * It references the CIE and provides function-specific CFI instructions. + * + * The PC-relative offset is calculated after the entire EH frame is built + * to ensure accurate positioning relative to the synthesized DSO layout. + */ + DWRF_SECTION(FDE, + DWRF_U32((uint32_t)(p - framep)); // Offset to CIE (backwards reference) + /* + * In perf jitdump mode the FDE PC field is encoded PC-relative and + * points back to code_start. Record where that field lives so we can + * patch in the final offset after the rest of the synthetic DSO + * layout is known. + */ + ctx->fde_p = p; // Remember where PC offset field is located for later calculation + DWRF_U32(0); // Placeholder for PC-relative offset (calculated below) + DWRF_U32(ctx->code_size); // Address range covered by this FDE (code length) + DWRF_U8(0); // Augmentation data length (none) + + /* + * Architecture-specific CFI instructions + * + * These instructions describe how registers are saved and restored + * during function calls. Each architecture has different calling + * conventions and register usage patterns. + */ +#ifdef __x86_64__ + /* x86_64 calling convention unwinding rules */ +# if defined(__CET__) && (__CET__ & 1) + DWRF_U8(DWRF_CFA_advance_loc | 4); // Advance past endbr64 (4 bytes) +# endif + DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance past push %rbp (1 byte) + DWRF_U8(DWRF_CFA_def_cfa_offset); // def_cfa_offset 16 + DWRF_UV(16); // New offset: SP + 16 + DWRF_U8(DWRF_CFA_offset | DWRF_REG_BP); // offset r6 at cfa-16 + DWRF_UV(2); // Offset factor: 2 * 8 = 16 bytes + DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance past mov %rsp,%rbp (3 bytes) + DWRF_U8(DWRF_CFA_def_cfa_register); // def_cfa_register r6 + DWRF_UV(DWRF_REG_BP); // Use base pointer register + DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance past call *%rcx (2 bytes) + pop %rbp (1 byte) = 3 + DWRF_U8(DWRF_CFA_def_cfa); // def_cfa r7 ofs 8 + DWRF_UV(DWRF_REG_SP); // Use stack pointer register + DWRF_UV(8); // New offset: SP + 8 +#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) + /* AArch64 calling convention unwinding rules */ + DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance by 1 instruction (4 bytes) + DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 16 + DWRF_UV(16); // Stack pointer moved by 16 bytes + DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // x29 (frame pointer) saved + DWRF_UV(2); // At CFA-16 (2 * 8 = 16 bytes from CFA) + DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // x30 (link register) saved + DWRF_UV(1); // At CFA-8 (1 * 8 = 8 bytes from CFA) + DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance by 3 instructions (12 bytes) + DWRF_U8(DWRF_CFA_def_cfa_register); // CFA = FP (x29) + 16 + DWRF_UV(DWRF_REG_FP); + DWRF_U8(DWRF_CFA_restore | DWRF_REG_RA); // Restore x30 - NO DWRF_UV() after this! + DWRF_U8(DWRF_CFA_restore | DWRF_REG_FP); // Restore x29 - NO DWRF_UV() after this! + DWRF_U8(DWRF_CFA_def_cfa); // CFA = SP + 0 (stack restored) + DWRF_UV(DWRF_REG_SP); + DWRF_UV(0); + +#else +# error "Unsupported target architecture" +#endif + + DWRF_ALIGNNOP(sizeof(uintptr_t)); // Align to pointer boundary + ) + + ctx->p = p; // Update context pointer to end of generated data + + /* Calculate and update the PC-relative offset in the FDE + * + * When perf processes the jitdump, it creates a synthesized DSO with this layout: + * + * Synthesized DSO Memory Layout: + * ┌─────────────────────────────────────────────────────────────┐ < code_start + * │ Code Section │ + * │ (round_up(code_size, 8) bytes) │ + * ├─────────────────────────────────────────────────────────────┤ < start of EH frame data + * │ EH Frame Data │ + * │ ┌─────────────────────────────────────────────────────┐ │ + * │ │ CIE data │ │ + * │ └─────────────────────────────────────────────────────┘ │ + * │ ┌─────────────────────────────────────────────────────┐ │ + * │ │ FDE Header: │ │ + * │ │ - CIE offset (4 bytes) │ │ + * │ │ - PC offset (4 bytes) <─ fde_offset_in_frame ─────┼────┼─> points to code_start + * │ │ - address range (4 bytes) │ │ (this specific field) + * │ │ CFI Instructions... │ │ + * │ └─────────────────────────────────────────────────────┘ │ + * ├─────────────────────────────────────────────────────────────┤ < reference_point + * │ EhFrameHeader │ + * │ (navigation metadata) │ + * └─────────────────────────────────────────────────────────────┘ + * + * The PC offset field in the FDE must contain the distance from itself to code_start: + * + * distance = code_start - fde_pc_field + * + * Where: + * fde_pc_field_location = reference_point - eh_frame_size + fde_offset_in_frame + * code_start_location = reference_point - eh_frame_size - round_up(code_size, 8) + * + * Therefore: + * distance = code_start_location - fde_pc_field_location + * = (ref - eh_frame_size - rounded_code_size) - (ref - eh_frame_size + fde_offset_in_frame) + * = -rounded_code_size - fde_offset_in_frame + * = -(round_up(code_size, 8) + fde_offset_in_frame) + * + * Note: fde_offset_in_frame is the offset from EH frame start to the PC offset field. + * + */ + int32_t rounded_code_size = + (int32_t)_Py_SIZE_ROUND_UP(ctx->code_size, 8); + int32_t fde_offset_in_frame = (int32_t)(ctx->fde_p - framep); + *(int32_t *)ctx->fde_p = -(rounded_code_size + fde_offset_in_frame); +} + +/* + * Build .eh_frame data for the GDB JIT interface. + * + * The executor runs inside the frame established by _PyJIT_Entry, but the + * synthetic executor FDE collapses that state into a single logical JIT frame + * that unwinds directly into _PyEval_*. Executor stencils never touch the + * frame pointer - enforced by Tools/jit/_optimizers.py _validate() and + * -mframe-pointer=reserved - so the steady-state rule is valid at every PC + * and the FDE body is empty. Tools/jit/_targets.py derives the initial CFI + * rules from the row active at the executor call in the compiled shim object. + */ +#if defined(PY_HAVE_JIT_GDB_UNWIND) +static void elf_init_ehframe_gdb(ELFObjectContext* ctx) { + int fde_ptr_enc = DWRF_EH_PE_absptr; + uint8_t* p = ctx->p; + uint8_t* framep = p; + + DWRF_SECTION(CIE, + DWRF_U32(0); // CIE ID + DWRF_U8(DWRF_CIE_VERSION); + DWRF_STR("zR"); // aug data length + FDE ptr encoding follow + DWRF_UV(JIT_UNWIND_CODE_ALIGNMENT_FACTOR); + DWRF_SV(JIT_UNWIND_DATA_ALIGNMENT_FACTOR); + DWRF_U8(JIT_UNWIND_RA_REG); + DWRF_UV(1); // Augmentation data length + DWRF_U8(fde_ptr_enc); // FDE pointer encoding + + /* Executor steady-state rule (our invariant, not the compiler's). */ + DWRF_U8(DWRF_CFA_def_cfa); + DWRF_UV(JIT_UNWIND_CFA_REG); + DWRF_UV(JIT_UNWIND_CFA_OFFSET); + DWRF_U8(DWRF_CFA_offset | JIT_UNWIND_FP_REG); + DWRF_UV(JIT_UNWIND_FP_OFFSET); + DWRF_U8(DWRF_CFA_offset | JIT_UNWIND_RA_REG); + DWRF_UV(JIT_UNWIND_RA_OFFSET); + DWRF_ALIGNNOP(sizeof(uintptr_t)); + ) + + DWRF_SECTION(FDE, + DWRF_U32((uint32_t)(p - framep)); // Offset to CIE (backwards reference) + DWRF_ADDR(ctx->code_addr); // Absolute code start + DWRF_ADDR((uintptr_t)ctx->code_size); // Code range covered + DWRF_U8(0); // Augmentation data length (none) + DWRF_ALIGNNOP(sizeof(uintptr_t)); + ) + + ctx->p = p; +} +#endif + +#if defined(PY_HAVE_JIT_GDB_UNWIND) +enum { + JIT_NOACTION = 0, + JIT_REGISTER_FN = 1, + JIT_UNREGISTER_FN = 2, +}; + +struct jit_code_entry { + struct jit_code_entry *next; + struct jit_code_entry *prev; + const char *symfile_addr; + uint64_t symfile_size; + const void *code_addr; +}; + +struct jit_descriptor { + uint32_t version; + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; +}; + +PyMutex _Py_jit_debug_mutex = {0}; + +Py_EXPORTED_SYMBOL volatile struct jit_descriptor __jit_debug_descriptor = { + 1, JIT_NOACTION, NULL, NULL +}; + +Py_EXPORTED_SYMBOL void __attribute__((noinline)) +__jit_debug_register_code(void) +{ + /* Keep this call visible to debuggers and not optimized away. */ + (void)__jit_debug_descriptor.action_flag; +#if defined(__GNUC__) || defined(__clang__) + __asm__ __volatile__("" ::: "memory"); +#endif +} + +static uint16_t +gdb_jit_machine_id(void) +{ + /* Map the current target to ELF e_machine; return 0 to skip registration. */ +#if defined(__x86_64__) || defined(_M_X64) + return EM_X86_64; +#elif defined(__aarch64__) && !defined(__ILP32__) + return EM_AARCH64; +#else + return 0; +#endif +} + +static struct jit_code_entry * +gdb_jit_register_code( + const void *code_addr, + size_t code_size, + const char *symname, + const uint8_t *eh_frame, + size_t eh_frame_size +) +{ + /* + * Build a minimal in-memory ELF for GDB's JIT interface and link it into + * __jit_debug_descriptor so debuggers can resolve JIT code. + */ + if (code_addr == NULL || code_size == 0 || symname == NULL) { + return NULL; + } + + const uint16_t machine = gdb_jit_machine_id(); + if (machine == 0) { + return NULL; + } + + enum { + SH_NULL = 0, + SH_TEXT, + SH_EH_FRAME, + SH_SHSTRTAB, + SH_STRTAB, + SH_SYMTAB, + SH_NUM, + }; + static const char shstrtab[] = + "\0.text\0.eh_frame\0.shstrtab\0.strtab\0.symtab"; + _Static_assert(sizeof(shstrtab) == + 1 + sizeof(".text") + sizeof(".eh_frame") + + sizeof(".shstrtab") + sizeof(".strtab") + sizeof(".symtab"), + "shstrtab size mismatch"); + const size_t shstrtab_size = sizeof(shstrtab); + const size_t sh_text = 1; + const size_t sh_eh_frame = sh_text + sizeof(".text"); + const size_t sh_shstrtab = sh_eh_frame + sizeof(".eh_frame"); + const size_t sh_strtab = sh_shstrtab + sizeof(".shstrtab"); + const size_t sh_symtab = sh_strtab + sizeof(".strtab"); + const size_t text_size = code_size; + const size_t text_padded = _Py_SIZE_ROUND_UP(text_size, 8); + const size_t strtab_size = 1 + strlen(symname) + 1; + const size_t symtab_size = 3 * sizeof(Elf64_Sym); + + size_t offset = sizeof(Elf64_Ehdr); + offset = _Py_SIZE_ROUND_UP(offset, 16); + const size_t text_off = offset; + const size_t eh_off = text_off + text_padded; + offset = eh_off + eh_frame_size; + const size_t shstr_off = offset; + offset += shstrtab_size; + const size_t str_off = offset; + offset += strtab_size; + /* Elf64_Sym requires 8-byte alignment for st_value/st_size. */ + offset = _Py_SIZE_ROUND_UP(offset, 8); + const size_t sym_off = offset; + offset += symtab_size; + offset = _Py_SIZE_ROUND_UP(offset, sizeof(Elf64_Shdr)); + const size_t sh_off = offset; + + const size_t shnum = SH_NUM; + const size_t total_size = sh_off + shnum * sizeof(Elf64_Shdr); + uint8_t *buf = (uint8_t *)PyMem_RawMalloc(total_size); + if (buf == NULL) { + return NULL; + } + memset(buf, 0, total_size); + + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)buf; + memcpy(ehdr->e_ident, ELFMAG, SELFMAG); + ehdr->e_ident[EI_CLASS] = ELFCLASS64; + ehdr->e_ident[EI_DATA] = ELFDATA2LSB; + ehdr->e_ident[EI_VERSION] = EV_CURRENT; + ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE; + ehdr->e_type = ET_DYN; + ehdr->e_machine = machine; + ehdr->e_version = EV_CURRENT; + ehdr->e_entry = 0; + ehdr->e_phoff = 0; + ehdr->e_shoff = sh_off; + ehdr->e_ehsize = sizeof(Elf64_Ehdr); + ehdr->e_shentsize = sizeof(Elf64_Shdr); + ehdr->e_shnum = shnum; + ehdr->e_shstrndx = SH_SHSTRTAB; + + memcpy(buf + text_off, code_addr, text_size); + memcpy(buf + eh_off, eh_frame, eh_frame_size); + + char *shstr = (char *)(buf + shstr_off); + memcpy(shstr, shstrtab, shstrtab_size); + + char *strtab = (char *)(buf + str_off); + strtab[0] = '\0'; + memcpy(strtab + 1, symname, strlen(symname)); + strtab[strtab_size - 1] = '\0'; + + Elf64_Sym *syms = (Elf64_Sym *)(buf + sym_off); + memset(syms, 0, symtab_size); + /* Section symbol for .text (local) */ + syms[1].st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION); + syms[1].st_shndx = 1; + /* Function symbol */ + syms[2].st_name = 1; + syms[2].st_info = ELF64_ST_INFO(STB_GLOBAL, STT_FUNC); + syms[2].st_other = STV_DEFAULT; + syms[2].st_shndx = 1; + /* For ET_DYN/ET_EXEC, st_value is the absolute virtual address. */ + syms[2].st_value = (Elf64_Addr)(uintptr_t)code_addr; + syms[2].st_size = code_size; + + Elf64_Shdr *shdrs = (Elf64_Shdr *)(buf + sh_off); + memset(shdrs, 0, shnum * sizeof(Elf64_Shdr)); + + shdrs[SH_TEXT].sh_name = sh_text; + shdrs[SH_TEXT].sh_type = SHT_PROGBITS; + shdrs[SH_TEXT].sh_flags = SHF_ALLOC | SHF_EXECINSTR; + shdrs[SH_TEXT].sh_addr = (Elf64_Addr)(uintptr_t)code_addr; + shdrs[SH_TEXT].sh_offset = text_off; + shdrs[SH_TEXT].sh_size = text_size; + shdrs[SH_TEXT].sh_addralign = 16; + + shdrs[SH_EH_FRAME].sh_name = sh_eh_frame; + shdrs[SH_EH_FRAME].sh_type = SHT_PROGBITS; + shdrs[SH_EH_FRAME].sh_flags = SHF_ALLOC; + shdrs[SH_EH_FRAME].sh_addr = + (Elf64_Addr)((uintptr_t)code_addr + text_padded); + shdrs[SH_EH_FRAME].sh_offset = eh_off; + shdrs[SH_EH_FRAME].sh_size = eh_frame_size; + shdrs[SH_EH_FRAME].sh_addralign = 8; + + shdrs[SH_SHSTRTAB].sh_name = sh_shstrtab; + shdrs[SH_SHSTRTAB].sh_type = SHT_STRTAB; + shdrs[SH_SHSTRTAB].sh_offset = shstr_off; + shdrs[SH_SHSTRTAB].sh_size = shstrtab_size; + shdrs[SH_SHSTRTAB].sh_addralign = 1; + + shdrs[SH_STRTAB].sh_name = sh_strtab; + shdrs[SH_STRTAB].sh_type = SHT_STRTAB; + shdrs[SH_STRTAB].sh_offset = str_off; + shdrs[SH_STRTAB].sh_size = strtab_size; + shdrs[SH_STRTAB].sh_addralign = 1; + + shdrs[SH_SYMTAB].sh_name = sh_symtab; + shdrs[SH_SYMTAB].sh_type = SHT_SYMTAB; + shdrs[SH_SYMTAB].sh_offset = sym_off; + shdrs[SH_SYMTAB].sh_size = symtab_size; + shdrs[SH_SYMTAB].sh_link = SH_STRTAB; + shdrs[SH_SYMTAB].sh_info = 2; + shdrs[SH_SYMTAB].sh_addralign = 8; + shdrs[SH_SYMTAB].sh_entsize = sizeof(Elf64_Sym); + + struct jit_code_entry *entry = PyMem_RawMalloc(sizeof(*entry)); + if (entry == NULL) { + PyMem_RawFree(buf); + return NULL; + } + entry->symfile_addr = (const char *)buf; + entry->symfile_size = total_size; + entry->code_addr = code_addr; + + PyMutex_Lock(&_Py_jit_debug_mutex); + entry->prev = NULL; + entry->next = __jit_debug_descriptor.first_entry; + if (entry->next != NULL) { + entry->next->prev = entry; + } + __jit_debug_descriptor.first_entry = entry; + __jit_debug_descriptor.relevant_entry = entry; + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + __jit_debug_register_code(); + __jit_debug_descriptor.action_flag = JIT_NOACTION; + __jit_debug_descriptor.relevant_entry = NULL; + PyMutex_Unlock(&_Py_jit_debug_mutex); + return entry; +} +#endif // defined(PY_HAVE_JIT_GDB_UNWIND) + +void * +_PyJitUnwind_GdbRegisterCode(const void *code_addr, + size_t code_size, + const char *entry, + const char *filename) +{ +#if defined(PY_HAVE_JIT_GDB_UNWIND) + /* GDB expects a stable symbol name and absolute addresses in .eh_frame. */ + if (entry == NULL) { + entry = ""; + } + if (filename == NULL) { + filename = ""; + } + size_t name_size = snprintf(NULL, 0, "py::%s:%s", entry, filename) + 1; + char *name = (char *)PyMem_RawMalloc(name_size); + if (name == NULL) { + return NULL; + } + snprintf(name, name_size, "py::%s:%s", entry, filename); + + uint8_t buffer[1024]; + size_t eh_frame_size = _PyJitUnwind_BuildEhFrame( + buffer, sizeof(buffer), code_addr, code_size, 1); + if (eh_frame_size == 0) { + PyMem_RawFree(name); + return NULL; + } + + void *handle = gdb_jit_register_code(code_addr, code_size, name, + buffer, eh_frame_size); + PyMem_RawFree(name); + return handle; +#else + (void)code_addr; + (void)code_size; + (void)entry; + (void)filename; + return NULL; +#endif +} + +void +_PyJitUnwind_GdbUnregisterCode(void *handle) +{ +#if defined(PY_HAVE_JIT_GDB_UNWIND) + struct jit_code_entry *entry = (struct jit_code_entry *)handle; + if (entry == NULL) { + return; + } + + PyMutex_Lock(&_Py_jit_debug_mutex); + if (entry->prev != NULL) { + entry->prev->next = entry->next; + } + else { + __jit_debug_descriptor.first_entry = entry->next; + } + if (entry->next != NULL) { + entry->next->prev = entry->prev; + } + + __jit_debug_descriptor.relevant_entry = entry; + __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; + __jit_debug_register_code(); + __jit_debug_descriptor.action_flag = JIT_NOACTION; + __jit_debug_descriptor.relevant_entry = NULL; + + PyMutex_Unlock(&_Py_jit_debug_mutex); + + PyMem_RawFree((void *)entry->symfile_addr); + PyMem_RawFree(entry); +#else + (void)handle; +#endif +} + +#endif // defined(PY_HAVE_PERF_TRAMPOLINE) || defined(PY_HAVE_JIT_GDB_UNWIND) diff --git a/Python/optimizer.c b/Python/optimizer.c index 820a0771a2c..11658fca0da 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1448,6 +1448,7 @@ allocate_executor(int exit_count, int length) res->trace = (_PyUOpInstruction *)(res->exits + exit_count); res->code_size = length; res->exit_count = exit_count; + res->jit_gdb_handle = NULL; return res; } diff --git a/Python/perf_jit_trampoline.c b/Python/perf_jit_trampoline.c index 0ba856ea610..0c460282fec 100644 --- a/Python/perf_jit_trampoline.c +++ b/Python/perf_jit_trampoline.c @@ -62,6 +62,7 @@ #include "pycore_frame.h" #include "pycore_interp.h" #include "pycore_mmap.h" // _PyAnnotateMemoryMap() +#include "pycore_jit_unwind.h" #include "pycore_runtime.h" // _PyRuntime #ifdef PY_HAVE_PERF_TRAMPOLINE @@ -73,6 +74,7 @@ #include // File control operations #include // Standard I/O operations #include // Standard library functions +#include // memcpy, strlen #include // Memory mapping functions (mmap) #include // System data types #include // System calls (sysconf, getpid) @@ -246,6 +248,25 @@ typedef struct { */ } CodeUnwindingInfoEvent; +/* + * EH Frame Header structure for DWARF unwinding + * + * This header provides metadata about the .eh_frame data that follows. + * It uses PC-relative and data-relative encodings to keep the synthesized + * DSO self-contained when perf injects it. + */ +typedef struct __attribute__((packed)) { + uint8_t version; + uint8_t eh_frame_ptr_enc; + uint8_t fde_count_enc; + uint8_t table_enc; + int32_t eh_frame_ptr; + uint32_t eh_fde_count; + int32_t from; + int32_t to; +} EhFrameHeader; +_Static_assert(sizeof(EhFrameHeader) == 20, "EhFrameHeader layout mismatch"); + // ============================================================================= // GLOBAL STATE MANAGEMENT // ============================================================================= @@ -259,10 +280,11 @@ typedef struct { */ typedef struct { FILE* perf_map; // File handle for the jitdump file - PyThread_type_lock map_lock; // Thread synchronization lock + PyMutex map_lock; // Thread synchronization lock void* mapped_buffer; // Memory-mapped region (signals perf we're active) size_t mapped_size; // Size of the mapped region - int code_id; // Counter for unique code region identifiers + uint32_t code_id; // Counter for unique code region identifiers + uint64_t build_id_salt; // Per-process salt for unique synthetic DSOs } PerfMapJitState; /* Global singleton instance */ @@ -316,40 +338,6 @@ static int64_t get_current_time_microseconds(void) { return ((int64_t)(tv.tv_sec) * 1000000) + tv.tv_usec; } -// ============================================================================= -// UTILITY FUNCTIONS -// ============================================================================= - -/* - * Round up a value to the next multiple of a given number - * - * This is essential for maintaining proper alignment requirements in the - * jitdump format. Many structures need to be aligned to specific boundaries - * (typically 8 or 16 bytes) for efficient processing by perf. - * - * Args: - * value: The value to round up - * multiple: The multiple to round up to - * - * Returns: The smallest value >= input that is a multiple of 'multiple' - */ -static size_t round_up(int64_t value, int64_t multiple) { - if (multiple == 0) { - return value; // Avoid division by zero - } - - int64_t remainder = value % multiple; - if (remainder == 0) { - return value; // Already aligned - } - - /* Calculate how much to add to reach the next multiple */ - int64_t difference = multiple - remainder; - int64_t rounded_up_value = value + difference; - - return rounded_up_value; -} - // ============================================================================= // FILE I/O UTILITIES // ============================================================================= @@ -406,623 +394,6 @@ static void perf_map_jit_write_header(int pid, FILE* out_file) { perf_map_jit_write_fully(&header, sizeof(header)); } -// ============================================================================= -// DWARF CONSTANTS AND UTILITIES -// ============================================================================= - -/* - * DWARF (Debug With Arbitrary Record Formats) constants - * - * DWARF is a debugging data format used to provide stack unwinding information. - * These constants define the various encoding types and opcodes used in - * DWARF Call Frame Information (CFI) records. - */ - -/* DWARF Call Frame Information version */ -#define DWRF_CIE_VERSION 1 - -/* DWARF CFA (Call Frame Address) opcodes */ -enum { - DWRF_CFA_nop = 0x0, // No operation - DWRF_CFA_offset_extended = 0x5, // Extended offset instruction - DWRF_CFA_def_cfa = 0xc, // Define CFA rule - DWRF_CFA_def_cfa_register = 0xd, // Define CFA register - DWRF_CFA_def_cfa_offset = 0xe, // Define CFA offset - DWRF_CFA_offset_extended_sf = 0x11, // Extended signed offset - DWRF_CFA_advance_loc = 0x40, // Advance location counter - DWRF_CFA_offset = 0x80, // Simple offset instruction - DWRF_CFA_restore = 0xc0 // Restore register -}; - -/* DWARF Exception Handling pointer encodings */ -enum { - DWRF_EH_PE_absptr = 0x00, // Absolute pointer - DWRF_EH_PE_omit = 0xff, // Omitted value - - /* Data type encodings */ - DWRF_EH_PE_uleb128 = 0x01, // Unsigned LEB128 - DWRF_EH_PE_udata2 = 0x02, // Unsigned 2-byte - DWRF_EH_PE_udata4 = 0x03, // Unsigned 4-byte - DWRF_EH_PE_udata8 = 0x04, // Unsigned 8-byte - DWRF_EH_PE_sleb128 = 0x09, // Signed LEB128 - DWRF_EH_PE_sdata2 = 0x0a, // Signed 2-byte - DWRF_EH_PE_sdata4 = 0x0b, // Signed 4-byte - DWRF_EH_PE_sdata8 = 0x0c, // Signed 8-byte - DWRF_EH_PE_signed = 0x08, // Signed flag - - /* Reference type encodings */ - DWRF_EH_PE_pcrel = 0x10, // PC-relative - DWRF_EH_PE_textrel = 0x20, // Text-relative - DWRF_EH_PE_datarel = 0x30, // Data-relative - DWRF_EH_PE_funcrel = 0x40, // Function-relative - DWRF_EH_PE_aligned = 0x50, // Aligned - DWRF_EH_PE_indirect = 0x80 // Indirect -}; - -/* Additional DWARF constants for debug information */ -enum { DWRF_TAG_compile_unit = 0x11 }; -enum { DWRF_children_no = 0, DWRF_children_yes = 1 }; -enum { - DWRF_AT_name = 0x03, // Name attribute - DWRF_AT_stmt_list = 0x10, // Statement list - DWRF_AT_low_pc = 0x11, // Low PC address - DWRF_AT_high_pc = 0x12 // High PC address -}; -enum { - DWRF_FORM_addr = 0x01, // Address form - DWRF_FORM_data4 = 0x06, // 4-byte data - DWRF_FORM_string = 0x08 // String form -}; - -/* Line number program opcodes */ -enum { - DWRF_LNS_extended_op = 0, // Extended opcode - DWRF_LNS_copy = 1, // Copy operation - DWRF_LNS_advance_pc = 2, // Advance program counter - DWRF_LNS_advance_line = 3 // Advance line number -}; - -/* Line number extended opcodes */ -enum { - DWRF_LNE_end_sequence = 1, // End of sequence - DWRF_LNE_set_address = 2 // Set address -}; - -/* - * Architecture-specific DWARF register numbers - * - * These constants define the register numbering scheme used by DWARF - * for each supported architecture. The numbers must match the ABI - * specification for proper stack unwinding. - */ -enum { -#ifdef __x86_64__ - /* x86_64 register numbering (note: order is defined by x86_64 ABI) */ - DWRF_REG_AX, // RAX - DWRF_REG_DX, // RDX - DWRF_REG_CX, // RCX - DWRF_REG_BX, // RBX - DWRF_REG_SI, // RSI - DWRF_REG_DI, // RDI - DWRF_REG_BP, // RBP - DWRF_REG_SP, // RSP - DWRF_REG_8, // R8 - DWRF_REG_9, // R9 - DWRF_REG_10, // R10 - DWRF_REG_11, // R11 - DWRF_REG_12, // R12 - DWRF_REG_13, // R13 - DWRF_REG_14, // R14 - DWRF_REG_15, // R15 - DWRF_REG_RA, // Return address (RIP) -#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) - /* AArch64 register numbering */ - DWRF_REG_FP = 29, // Frame Pointer - DWRF_REG_RA = 30, // Link register (return address) - DWRF_REG_SP = 31, // Stack pointer -#else -# error "Unsupported target architecture" -#endif -}; - -/* DWARF encoding constants used in EH frame headers */ -static const uint8_t DwarfUData4 = 0x03; // Unsigned 4-byte data -static const uint8_t DwarfSData4 = 0x0b; // Signed 4-byte data -static const uint8_t DwarfPcRel = 0x10; // PC-relative encoding -static const uint8_t DwarfDataRel = 0x30; // Data-relative encoding - -// ============================================================================= -// ELF OBJECT CONTEXT -// ============================================================================= - -/* - * Context for building ELF/DWARF structures - * - * This structure maintains state while constructing DWARF unwind information. - * It acts as a simple buffer manager with pointers to track current position - * and important landmarks within the buffer. - */ -typedef struct ELFObjectContext { - uint8_t* p; // Current write position in buffer - uint8_t* startp; // Start of buffer (for offset calculations) - uint8_t* eh_frame_p; // Start of EH frame data (for relative offsets) - uint8_t* fde_p; // Start of FDE data (for PC-relative calculations) - uint32_t code_size; // Size of the code being described -} ELFObjectContext; - -/* - * EH Frame Header structure for DWARF unwinding - * - * This structure provides metadata about the DWARF unwinding information - * that follows. It's required by the perf jitdump format to enable proper - * stack unwinding during profiling. - */ -typedef struct { - unsigned char version; // EH frame version (always 1) - unsigned char eh_frame_ptr_enc; // Encoding of EH frame pointer - unsigned char fde_count_enc; // Encoding of FDE count - unsigned char table_enc; // Encoding of table entries - int32_t eh_frame_ptr; // Pointer to EH frame data - int32_t eh_fde_count; // Number of FDEs (Frame Description Entries) - int32_t from; // Start address of code range - int32_t to; // End address of code range -} EhFrameHeader; - -// ============================================================================= -// DWARF GENERATION UTILITIES -// ============================================================================= - -/* - * Append a null-terminated string to the ELF context buffer - * - * Args: - * ctx: ELF object context - * str: String to append (must be null-terminated) - * - * Returns: Offset from start of buffer where string was written - */ -static uint32_t elfctx_append_string(ELFObjectContext* ctx, const char* str) { - uint8_t* p = ctx->p; - uint32_t ofs = (uint32_t)(p - ctx->startp); - - /* Copy string including null terminator */ - do { - *p++ = (uint8_t)*str; - } while (*str++); - - ctx->p = p; - return ofs; -} - -/* - * Append a SLEB128 (Signed Little Endian Base 128) value - * - * SLEB128 is a variable-length encoding used extensively in DWARF. - * It efficiently encodes small numbers in fewer bytes. - * - * Args: - * ctx: ELF object context - * v: Signed value to encode - */ -static void elfctx_append_sleb128(ELFObjectContext* ctx, int32_t v) { - uint8_t* p = ctx->p; - - /* Encode 7 bits at a time, with continuation bit in MSB */ - for (; (uint32_t)(v + 0x40) >= 0x80; v >>= 7) { - *p++ = (uint8_t)((v & 0x7f) | 0x80); // Set continuation bit - } - *p++ = (uint8_t)(v & 0x7f); // Final byte without continuation bit - - ctx->p = p; -} - -/* - * Append a ULEB128 (Unsigned Little Endian Base 128) value - * - * Similar to SLEB128 but for unsigned values. - * - * Args: - * ctx: ELF object context - * v: Unsigned value to encode - */ -static void elfctx_append_uleb128(ELFObjectContext* ctx, uint32_t v) { - uint8_t* p = ctx->p; - - /* Encode 7 bits at a time, with continuation bit in MSB */ - for (; v >= 0x80; v >>= 7) { - *p++ = (char)((v & 0x7f) | 0x80); // Set continuation bit - } - *p++ = (char)v; // Final byte without continuation bit - - ctx->p = p; -} - -/* - * Macros for generating DWARF structures - * - * These macros provide a convenient way to write various data types - * to the DWARF buffer while automatically advancing the pointer. - */ -#define DWRF_U8(x) (*p++ = (x)) // Write unsigned 8-bit -#define DWRF_I8(x) (*(int8_t*)p = (x), p++) // Write signed 8-bit -#define DWRF_U16(x) (*(uint16_t*)p = (x), p += 2) // Write unsigned 16-bit -#define DWRF_U32(x) (*(uint32_t*)p = (x), p += 4) // Write unsigned 32-bit -#define DWRF_ADDR(x) (*(uintptr_t*)p = (x), p += sizeof(uintptr_t)) // Write address -#define DWRF_UV(x) (ctx->p = p, elfctx_append_uleb128(ctx, (x)), p = ctx->p) // Write ULEB128 -#define DWRF_SV(x) (ctx->p = p, elfctx_append_sleb128(ctx, (x)), p = ctx->p) // Write SLEB128 -#define DWRF_STR(str) (ctx->p = p, elfctx_append_string(ctx, (str)), p = ctx->p) // Write string - -/* Align to specified boundary with NOP instructions */ -#define DWRF_ALIGNNOP(s) \ - while ((uintptr_t)p & ((s)-1)) { \ - *p++ = DWRF_CFA_nop; \ - } - -/* Write a DWARF section with automatic size calculation */ -#define DWRF_SECTION(name, stmt) \ - { \ - uint32_t* szp_##name = (uint32_t*)p; \ - p += 4; \ - stmt; \ - *szp_##name = (uint32_t)((p - (uint8_t*)szp_##name) - 4); \ - } - -// ============================================================================= -// DWARF EH FRAME GENERATION -// ============================================================================= - -static void elf_init_ehframe(ELFObjectContext* ctx); - -/* - * Initialize DWARF .eh_frame section for a code region - * - * The .eh_frame section contains Call Frame Information (CFI) that describes - * how to unwind the stack at any point in the code. This is essential for - * proper profiling as it allows perf to generate accurate call graphs. - * - * The function generates two main components: - * 1. CIE (Common Information Entry) - describes calling conventions - * 2. FDE (Frame Description Entry) - describes specific function unwinding - * - * Args: - * ctx: ELF object context containing code size and buffer pointers - */ -static size_t calculate_eh_frame_size(void) { - /* Calculate the EH frame size for the trampoline function */ - extern void *_Py_trampoline_func_start; - extern void *_Py_trampoline_func_end; - - size_t code_size = (char*)&_Py_trampoline_func_end - (char*)&_Py_trampoline_func_start; - - ELFObjectContext ctx; - char buffer[1024]; // Buffer for DWARF data (1KB should be sufficient) - ctx.code_size = code_size; - ctx.startp = ctx.p = (uint8_t*)buffer; - ctx.fde_p = NULL; - - elf_init_ehframe(&ctx); - return ctx.p - ctx.startp; -} - -static void elf_init_ehframe(ELFObjectContext* ctx) { - uint8_t* p = ctx->p; - uint8_t* framep = p; // Remember start of frame data - - /* - * DWARF Unwind Table for Trampoline Function - * - * This section defines DWARF Call Frame Information (CFI) using encoded macros - * like `DWRF_U8`, `DWRF_UV`, and `DWRF_SECTION` to describe how the trampoline function - * preserves and restores registers. This is used by profiling tools (e.g., `perf`) - * and debuggers for stack unwinding in JIT-compiled code. - * - * ------------------------------------------------- - * TO REGENERATE THIS TABLE FROM GCC OBJECTS: - * ------------------------------------------------- - * - * 1. Create a trampoline source file (e.g., `trampoline.c`): - * - * #include - * typedef PyObject* (*py_evaluator)(void*, void*, int); - * PyObject* trampoline(void *ts, void *f, int throwflag, py_evaluator evaluator) { - * return evaluator(ts, f, throwflag); - * } - * - * 2. Compile to an object file with frame pointer preservation: - * - * gcc trampoline.c -I. -I./Include -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -c - * - * 3. Extract DWARF unwind info from the object file: - * - * readelf -w trampoline.o - * - * Example output from `.eh_frame`: - * - * 00000000 CIE - * Version: 1 - * Augmentation: "zR" - * Code alignment factor: 4 - * Data alignment factor: -8 - * Return address column: 30 - * DW_CFA_def_cfa: r31 (sp) ofs 0 - * - * 00000014 FDE cie=00000000 pc=0..14 - * DW_CFA_advance_loc: 4 - * DW_CFA_def_cfa_offset: 16 - * DW_CFA_offset: r29 at cfa-16 - * DW_CFA_offset: r30 at cfa-8 - * DW_CFA_advance_loc: 12 - * DW_CFA_restore: r30 - * DW_CFA_restore: r29 - * DW_CFA_def_cfa_offset: 0 - * - * -- These values can be verified by comparing with `readelf -w` or `llvm-dwarfdump --eh-frame`. - * - * ---------------------------------- - * HOW TO TRANSLATE TO DWRF_* MACROS: - * ---------------------------------- - * - * After compiling your trampoline with: - * - * gcc trampoline.c -I. -I./Include -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -c - * - * run: - * - * readelf -w trampoline.o - * - * to inspect the generated `.eh_frame` data. You will see two main components: - * - * 1. A CIE (Common Information Entry): shared configuration used by all FDEs. - * 2. An FDE (Frame Description Entry): function-specific unwind instructions. - * - * --------------------- - * Translating the CIE: - * --------------------- - * From `readelf -w`, you might see: - * - * 00000000 0000000000000010 00000000 CIE - * Version: 1 - * Augmentation: "zR" - * Code alignment factor: 4 - * Data alignment factor: -8 - * Return address column: 30 - * Augmentation data: 1b - * DW_CFA_def_cfa: r31 (sp) ofs 0 - * - * Map this to: - * - * DWRF_SECTION(CIE, - * DWRF_U32(0); // CIE ID (always 0 for CIEs) - * DWRF_U8(DWRF_CIE_VERSION); // Version: 1 - * DWRF_STR("zR"); // Augmentation string "zR" - * DWRF_UV(4); // Code alignment factor = 4 - * DWRF_SV(-8); // Data alignment factor = -8 - * DWRF_U8(DWRF_REG_RA); // Return address register (e.g., x30 = 30) - * DWRF_UV(1); // Augmentation data length = 1 - * DWRF_U8(DWRF_EH_PE_pcrel | DWRF_EH_PE_sdata4); // Encoding for FDE pointers - * - * DWRF_U8(DWRF_CFA_def_cfa); // DW_CFA_def_cfa - * DWRF_UV(DWRF_REG_SP); // Register: SP (r31) - * DWRF_UV(0); // Offset = 0 - * - * DWRF_ALIGNNOP(sizeof(uintptr_t)); // Align to pointer size boundary - * ) - * - * Notes: - * - Use `DWRF_UV` for unsigned LEB128, `DWRF_SV` for signed LEB128. - * - `DWRF_REG_RA` and `DWRF_REG_SP` are architecture-defined constants. - * - * --------------------- - * Translating the FDE: - * --------------------- - * From `readelf -w`: - * - * 00000014 0000000000000020 00000018 FDE cie=00000000 pc=0000000000000000..0000000000000014 - * DW_CFA_advance_loc: 4 - * DW_CFA_def_cfa_offset: 16 - * DW_CFA_offset: r29 at cfa-16 - * DW_CFA_offset: r30 at cfa-8 - * DW_CFA_advance_loc: 12 - * DW_CFA_restore: r30 - * DW_CFA_restore: r29 - * DW_CFA_def_cfa_offset: 0 - * - * Map the FDE header and instructions to: - * - * DWRF_SECTION(FDE, - * DWRF_U32((uint32_t)(p - framep)); // Offset to CIE (relative from here) - * DWRF_U32(pc_relative_offset); // PC-relative location of the code (calculated dynamically) - * DWRF_U32(ctx->code_size); // Code range covered by this FDE - * DWRF_U8(0); // Augmentation data length (none) - * - * DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance location by 1 unit (1 * 4 = 4 bytes) - * DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 16 - * DWRF_UV(16); - * - * DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // Save x29 (frame pointer) - * DWRF_UV(2); // At offset 2 * 8 = 16 bytes - * - * DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // Save x30 (return address) - * DWRF_UV(1); // At offset 1 * 8 = 8 bytes - * - * DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance location by 3 units (3 * 4 = 12 bytes) - * - * DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // Restore x30 - * DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // Restore x29 - * - * DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP - * DWRF_UV(0); - * ) - * - * To regenerate: - * 1. Get the `code alignment factor`, `data alignment factor`, and `RA column` from the CIE. - * 2. Note the range of the function from the FDE's `pc=...` line and map it to the JIT code as - * the code is in a different address space every time. - * 3. For each `DW_CFA_*` entry, use the corresponding `DWRF_*` macro: - * - `DW_CFA_def_cfa_offset` → DWRF_U8(DWRF_CFA_def_cfa_offset), DWRF_UV(value) - * - `DW_CFA_offset: rX` → DWRF_U8(DWRF_CFA_offset | reg), DWRF_UV(offset) - * - `DW_CFA_restore: rX` → DWRF_U8(DWRF_CFA_offset | reg) // restore is same as reusing offset - * - `DW_CFA_advance_loc: N` → DWRF_U8(DWRF_CFA_advance_loc | (N / code_alignment_factor)) - * 4. Use `DWRF_REG_FP`, `DWRF_REG_RA`, etc., for register numbers. - * 5. Use `sizeof(uintptr_t)` (typically 8) for pointer size calculations and alignment. - */ - - /* - * Emit DWARF EH CIE (Common Information Entry) - * - * The CIE describes the calling conventions and basic unwinding rules - * that apply to all functions in this compilation unit. - */ - DWRF_SECTION(CIE, - DWRF_U32(0); // CIE ID (0 indicates this is a CIE) - DWRF_U8(DWRF_CIE_VERSION); // CIE version (1) - DWRF_STR("zR"); // Augmentation string ("zR" = has LSDA) -#ifdef __x86_64__ - DWRF_UV(1); // Code alignment factor (x86_64: 1 byte) -#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) - DWRF_UV(4); // Code alignment factor (AArch64: 4 bytes per instruction) -#endif - DWRF_SV(-(int64_t)sizeof(uintptr_t)); // Data alignment factor (negative) - DWRF_U8(DWRF_REG_RA); // Return address register number - DWRF_UV(1); // Augmentation data length - DWRF_U8(DWRF_EH_PE_pcrel | DWRF_EH_PE_sdata4); // FDE pointer encoding - - /* Initial CFI instructions - describe default calling convention */ -#ifdef __x86_64__ - /* x86_64 initial CFI state */ - DWRF_U8(DWRF_CFA_def_cfa); // Define CFA (Call Frame Address) - DWRF_UV(DWRF_REG_SP); // CFA = SP register - DWRF_UV(sizeof(uintptr_t)); // CFA = SP + pointer_size - DWRF_U8(DWRF_CFA_offset|DWRF_REG_RA); // Return address is saved - DWRF_UV(1); // At offset 1 from CFA -#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) - /* AArch64 initial CFI state */ - DWRF_U8(DWRF_CFA_def_cfa); // Define CFA (Call Frame Address) - DWRF_UV(DWRF_REG_SP); // CFA = SP register - DWRF_UV(0); // CFA = SP + 0 (AArch64 starts with offset 0) - // No initial register saves in AArch64 CIE -#endif - DWRF_ALIGNNOP(sizeof(uintptr_t)); // Align to pointer boundary - ) - - ctx->eh_frame_p = p; // Remember start of FDE data - - /* - * Emit DWARF EH FDE (Frame Description Entry) - * - * The FDE describes unwinding information specific to this function. - * It references the CIE and provides function-specific CFI instructions. - * - * The PC-relative offset is calculated after the entire EH frame is built - * to ensure accurate positioning relative to the synthesized DSO layout. - */ - DWRF_SECTION(FDE, - DWRF_U32((uint32_t)(p - framep)); // Offset to CIE (backwards reference) - ctx->fde_p = p; // Remember where PC offset field is located for later calculation - DWRF_U32(0); // Placeholder for PC-relative offset (calculated at end of elf_init_ehframe) - DWRF_U32(ctx->code_size); // Address range covered by this FDE (code length) - DWRF_U8(0); // Augmentation data length (none) - - /* - * Architecture-specific CFI instructions - * - * These instructions describe how registers are saved and restored - * during function calls. Each architecture has different calling - * conventions and register usage patterns. - */ -#ifdef __x86_64__ - /* x86_64 calling convention unwinding rules with frame pointer */ -# if defined(__CET__) && (__CET__ & 1) - DWRF_U8(DWRF_CFA_advance_loc | 4); // Advance past endbr64 (4 bytes) -# endif - DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance past push %rbp (1 byte) - DWRF_U8(DWRF_CFA_def_cfa_offset); // def_cfa_offset 16 - DWRF_UV(16); // New offset: SP + 16 - DWRF_U8(DWRF_CFA_offset | DWRF_REG_BP); // offset r6 at cfa-16 - DWRF_UV(2); // Offset factor: 2 * 8 = 16 bytes - DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance past mov %rsp,%rbp (3 bytes) - DWRF_U8(DWRF_CFA_def_cfa_register); // def_cfa_register r6 - DWRF_UV(DWRF_REG_BP); // Use base pointer register - DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance past call *%rcx (2 bytes) + pop %rbp (1 byte) = 3 - DWRF_U8(DWRF_CFA_def_cfa); // def_cfa r7 ofs 8 - DWRF_UV(DWRF_REG_SP); // Use stack pointer register - DWRF_UV(8); // New offset: SP + 8 -#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) - /* AArch64 calling convention unwinding rules */ - DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance by 1 instruction (4 bytes) - DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 16 - DWRF_UV(16); // Stack pointer moved by 16 bytes - DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // x29 (frame pointer) saved - DWRF_UV(2); // At CFA-16 (2 * 8 = 16 bytes from CFA) - DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // x30 (link register) saved - DWRF_UV(1); // At CFA-8 (1 * 8 = 8 bytes from CFA) - DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance by 3 instructions (12 bytes) - DWRF_U8(DWRF_CFA_restore | DWRF_REG_RA); // Restore x30 - NO DWRF_UV() after this! - DWRF_U8(DWRF_CFA_restore | DWRF_REG_FP); // Restore x29 - NO DWRF_UV() after this! - DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 0 (stack restored) - DWRF_UV(0); // Back to original stack position -#else -# error "Unsupported target architecture" -#endif - - DWRF_ALIGNNOP(sizeof(uintptr_t)); // Align to pointer boundary - ) - - ctx->p = p; // Update context pointer to end of generated data - - /* Calculate and update the PC-relative offset in the FDE - * - * When perf processes the jitdump, it creates a synthesized DSO with this layout: - * - * Synthesized DSO Memory Layout: - * ┌─────────────────────────────────────────────────────────────┐ < code_start - * │ Code Section │ - * │ (round_up(code_size, 8) bytes) │ - * ├─────────────────────────────────────────────────────────────┤ < start of EH frame data - * │ EH Frame Data │ - * │ ┌─────────────────────────────────────────────────────┐ │ - * │ │ CIE data │ │ - * │ └─────────────────────────────────────────────────────┘ │ - * │ ┌─────────────────────────────────────────────────────┐ │ - * │ │ FDE Header: │ │ - * │ │ - CIE offset (4 bytes) │ │ - * │ │ - PC offset (4 bytes) <─ fde_offset_in_frame ─────┼────┼─> points to code_start - * │ │ - address range (4 bytes) │ │ (this specific field) - * │ │ CFI Instructions... │ │ - * │ └─────────────────────────────────────────────────────┘ │ - * ├─────────────────────────────────────────────────────────────┤ < reference_point - * │ EhFrameHeader │ - * │ (navigation metadata) │ - * └─────────────────────────────────────────────────────────────┘ - * - * The PC offset field in the FDE must contain the distance from itself to code_start: - * - * distance = code_start - fde_pc_field - * - * Where: - * fde_pc_field_location = reference_point - eh_frame_size + fde_offset_in_frame - * code_start_location = reference_point - eh_frame_size - round_up(code_size, 8) - * - * Therefore: - * distance = code_start_location - fde_pc_field_location - * = (ref - eh_frame_size - rounded_code_size) - (ref - eh_frame_size + fde_offset_in_frame) - * = -rounded_code_size - fde_offset_in_frame - * = -(round_up(code_size, 8) + fde_offset_in_frame) - * - * Note: fde_offset_in_frame is the offset from EH frame start to the PC offset field, - * - */ - if (ctx->fde_p != NULL) { - int32_t fde_offset_in_frame = (ctx->fde_p - ctx->startp); - int32_t rounded_code_size = round_up(ctx->code_size, 8); - int32_t pc_relative_offset = -(rounded_code_size + fde_offset_in_frame); - - - // Update the PC-relative offset in the FDE - *(int32_t*)ctx->fde_p = pc_relative_offset; - } -} - // ============================================================================= // JITDUMP INITIALIZATION // ============================================================================= @@ -1042,6 +413,12 @@ static void elf_init_ehframe(ELFObjectContext* ctx) { * Returns: Pointer to initialized state, or NULL on failure */ static void* perf_map_jit_init(void) { + PyMutex_Lock(&perf_jit_map_state.map_lock); + if (perf_jit_map_state.perf_map != NULL) { + PyMutex_Unlock(&perf_jit_map_state.map_lock); + return &perf_jit_map_state; + } + char filename[100]; int pid = getpid(); @@ -1051,6 +428,7 @@ static void* perf_map_jit_init(void) { /* Create/open the jitdump file with appropriate permissions */ const int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666); if (fd == -1) { + PyMutex_Unlock(&perf_jit_map_state.map_lock); return NULL; // Failed to create file } @@ -1058,6 +436,7 @@ static void* perf_map_jit_init(void) { const long page_size = sysconf(_SC_PAGESIZE); if (page_size == -1) { close(fd); + PyMutex_Unlock(&perf_jit_map_state.map_lock); return NULL; // Failed to get page size } @@ -1086,6 +465,7 @@ static void* perf_map_jit_init(void) { if (perf_jit_map_state.mapped_buffer == MAP_FAILED) { perf_jit_map_state.mapped_buffer = NULL; close(fd); + PyMutex_Unlock(&perf_jit_map_state.map_lock); return NULL; // Memory mapping failed } (void)_PyAnnotateMemoryMap(perf_jit_map_state.mapped_buffer, page_size, @@ -1098,6 +478,7 @@ static void* perf_map_jit_init(void) { perf_jit_map_state.perf_map = fdopen(fd, "w+"); if (perf_jit_map_state.perf_map == NULL) { close(fd); + PyMutex_Unlock(&perf_jit_map_state.map_lock); return NULL; // Failed to create FILE* } @@ -1113,28 +494,18 @@ static void* perf_map_jit_init(void) { /* Write the jitdump file header */ perf_map_jit_write_header(pid, perf_jit_map_state.perf_map); - /* - * Initialize thread synchronization lock - * - * Multiple threads may attempt to write to the jitdump file - * simultaneously. This lock ensures thread-safe access to the - * global jitdump state. - */ - perf_jit_map_state.map_lock = PyThread_allocate_lock(); - if (perf_jit_map_state.map_lock == NULL) { - fclose(perf_jit_map_state.perf_map); - return NULL; // Failed to create lock - } - /* Initialize code ID counter */ perf_jit_map_state.code_id = 0; + perf_jit_map_state.build_id_salt = + ((uint64_t)pid << 32) ^ (uint64_t)get_current_monotonic_ticks(); /* Calculate padding size based on actual unwind info requirements */ - size_t eh_frame_size = calculate_eh_frame_size(); + size_t eh_frame_size = _PyJitUnwind_EhFrameSize(0); size_t unwind_data_size = sizeof(EhFrameHeader) + eh_frame_size; - trampoline_api.code_padding = round_up(unwind_data_size, 16); + trampoline_api.code_padding = _Py_SIZE_ROUND_UP(unwind_data_size, 16); trampoline_api.code_alignment = 32; + PyMutex_Unlock(&perf_jit_map_state.map_lock); return &perf_jit_map_state; } @@ -1143,54 +514,31 @@ static void* perf_map_jit_init(void) { // ============================================================================= /* - * Write a complete jitdump entry for a Python function + * Write a complete jitdump entry for a code region with a provided name. * - * This is the main function called by Python's trampoline system whenever - * a new piece of JIT-compiled code needs to be recorded. It writes both - * the unwinding information and the code load event to the jitdump file. - * - * The function performs these steps: - * 1. Initialize jitdump system if not already done - * 2. Extract function name and filename from Python code object - * 3. Generate DWARF unwinding information - * 4. Write unwinding info event to jitdump file - * 5. Write code load event to jitdump file - * - * Args: - * state: Jitdump state (currently unused, uses global state) - * code_addr: Address where the compiled code resides - * code_size: Size of the compiled code in bytes - * co: Python code object containing metadata - * - * IMPORTANT: This function signature is part of Python's internal API - * and must not be changed without coordinating with core Python development. + * This shares the same implementation as the trampoline callback, but + * allows callers that don't have a PyCodeObject to reuse the jitdump + * infrastructure. */ -static void perf_map_jit_write_entry(void *state, const void *code_addr, - unsigned int code_size, PyCodeObject *co) +static void perf_map_jit_write_entry_with_name( + void *state, + const void *code_addr, + size_t code_size, + const char *entry, + const char *filename +) { /* Initialize jitdump system on first use */ - if (perf_jit_map_state.perf_map == NULL) { - void* ret = perf_map_jit_init(); - if(ret == NULL){ - return; // Initialization failed, silently abort - } + void* ret = perf_map_jit_init(); + if (ret == NULL) { + return; // Initialization failed, silently abort } - /* - * Extract function information from Python code object - * - * We create a human-readable function name by combining the qualified - * name (includes class/module context) with the filename. This helps - * developers identify functions in perf reports. - */ - const char *entry = ""; - if (co->co_qualname != NULL) { - entry = PyUnicode_AsUTF8(co->co_qualname); + if (entry == NULL) { + entry = ""; } - - const char *filename = ""; - if (co->co_filename != NULL) { - filename = PyUnicode_AsUTF8(co->co_filename); + if (filename == NULL) { + filename = ""; } /* @@ -1218,15 +566,20 @@ static void perf_map_jit_write_entry(void *state, const void *code_addr, * Without it, perf cannot generate accurate call graphs, especially * in optimized code where frame pointers may be omitted. */ - ELFObjectContext ctx; - char buffer[1024]; // Buffer for DWARF data (1KB should be sufficient) - ctx.code_size = code_size; - ctx.startp = ctx.p = (uint8_t*)buffer; - ctx.fde_p = NULL; // Initialize to NULL, will be set when FDE is written + uint8_t buffer[1024]; // Buffer for DWARF data (1KB should be sufficient) + size_t eh_frame_size = _PyJitUnwind_BuildEhFrame( + buffer, sizeof(buffer), code_addr, code_size, 0); + if (eh_frame_size == 0) { + PyMem_RawFree(perf_map_entry); + return; + } - /* Generate EH frame (Exception Handling frame) data */ - elf_init_ehframe(&ctx); - int eh_frame_size = ctx.p - ctx.startp; + /* + * A logical jitdump entry is written as multiple records and also consumes + * a process-global code_id. Serialize the whole sequence so concurrent JIT + * compilation cannot interleave records or reuse an ID. + */ + PyMutex_Lock(&perf_jit_map_state.map_lock); /* * Write Code Unwinding Information Event @@ -1244,12 +597,12 @@ static void perf_map_jit_write_entry(void *state, const void *code_addr, assert(ev2.unwind_data_size <= (uint64_t)trampoline_api.code_padding); ev2.eh_frame_hdr_size = sizeof(EhFrameHeader); - ev2.mapped_size = round_up(ev2.unwind_data_size, 16); // 16-byte alignment + ev2.mapped_size = _Py_SIZE_ROUND_UP(ev2.unwind_data_size, 16); // 16-byte alignment /* Calculate total event size with padding */ - int content_size = sizeof(ev2) + sizeof(EhFrameHeader) + eh_frame_size; - int padding_size = round_up(content_size, 8) - content_size; // 8-byte align - ev2.base.size = content_size + padding_size; + int content_size = (int)(sizeof(ev2) + sizeof(EhFrameHeader) + eh_frame_size); + int padding_size = (int)_Py_SIZE_ROUND_UP((size_t)content_size, 8) - content_size; // 8-byte align + ev2.base.size = (uint32_t)(content_size + padding_size); /* Write the unwinding info event header */ perf_map_jit_write_fully(&ev2, sizeof(ev2)); @@ -1263,20 +616,21 @@ static void perf_map_jit_write_entry(void *state, const void *code_addr, */ EhFrameHeader f; f.version = 1; - f.eh_frame_ptr_enc = DwarfSData4 | DwarfPcRel; // PC-relative signed 4-byte - f.fde_count_enc = DwarfUData4; // Unsigned 4-byte count - f.table_enc = DwarfSData4 | DwarfDataRel; // Data-relative signed 4-byte + f.eh_frame_ptr_enc = DWRF_EH_PE_sdata4 | DWRF_EH_PE_pcrel; + f.fde_count_enc = DWRF_EH_PE_udata4; + f.table_enc = DWRF_EH_PE_sdata4 | DWRF_EH_PE_datarel; /* Calculate relative offsets for EH frame navigation */ - f.eh_frame_ptr = -(eh_frame_size + 4 * sizeof(unsigned char)); + f.eh_frame_ptr = -(int32_t)(eh_frame_size + 4 * sizeof(unsigned char)); f.eh_fde_count = 1; // We generate exactly one FDE per function - f.from = -(round_up(code_size, 8) + eh_frame_size); - - int cie_size = ctx.eh_frame_p - ctx.startp; - f.to = -(eh_frame_size - cie_size); + f.from = -(int32_t)(_Py_SIZE_ROUND_UP(code_size, 8) + eh_frame_size); + uint32_t cie_payload_size; + memcpy(&cie_payload_size, buffer, sizeof(cie_payload_size)); + int cie_size = (int)(sizeof(cie_payload_size) + cie_payload_size); + f.to = -(int32_t)(eh_frame_size - cie_size); /* Write EH frame data and header */ - perf_map_jit_write_fully(ctx.startp, eh_frame_size); + perf_map_jit_write_fully(buffer, eh_frame_size); perf_map_jit_write_fully(&f, sizeof(f)); /* Write padding to maintain alignment */ @@ -1313,12 +667,86 @@ static void perf_map_jit_write_entry(void *state, const void *code_addr, /* Write code load event and associated data */ perf_map_jit_write_fully(&ev, sizeof(ev)); perf_map_jit_write_fully(perf_map_entry, name_length+1); // Include null terminator - perf_map_jit_write_fully((void*)(base), size); // Copy actual machine code + /* + * Ensure each synthetic DSO has unique .text bytes. + * + * perf merges DSOs that share a build-id. Since trampolines can share + * identical code and unwind bytes, perf may resolve all JIT frames to + * the first symbol it saw (including entries from previous runs when + * build-id caching is enabled). Patch a small marker in the emitted + * bytes to make the build-id depend on a per-process salt and code id + * without modifying the live code. + */ + uint64_t marker = perf_jit_map_state.build_id_salt ^ + ((uint64_t)perf_jit_map_state.code_id << 32) ^ + (uint64_t)code_size; + if (size >= sizeof(marker)) { + size_t prefix = size - sizeof(marker); + perf_map_jit_write_fully((void *)(base), prefix); + perf_map_jit_write_fully(&marker, sizeof(marker)); + } + else if (size > 0) { + uint8_t tmp[sizeof(marker)]; + memcpy(tmp, (void *)(base), size); + for (size_t i = 0; i < size; i++) { + tmp[i] ^= (uint8_t)(marker >> (i * 8)); + } + perf_map_jit_write_fully(tmp, size); + } /* Clean up allocated memory */ + PyMutex_Unlock(&perf_jit_map_state.map_lock); PyMem_RawFree(perf_map_entry); } +/* + * Write a complete jitdump entry for a Python function + * + * This is the main function called by Python's trampoline system whenever + * a new piece of JIT-compiled code needs to be recorded. It writes both + * the unwinding information and the code load event to the jitdump file. + * + * The function performs these steps: + * 1. Initialize jitdump system if not already done + * 2. Extract function name and filename from Python code object + * 3. Generate DWARF unwinding information + * 4. Write unwinding info event to jitdump file + * 5. Write code load event to jitdump file + * + * Args: + * state: Jitdump state (currently unused, uses global state) + * code_addr: Address where the compiled code resides + * code_size: Size of the compiled code in bytes + * co: Python code object containing metadata + * + * IMPORTANT: This function signature is part of Python's internal API + * and must not be changed without coordinating with core Python development. + */ +static void perf_map_jit_write_entry(void *state, const void *code_addr, + size_t code_size, PyCodeObject *co) +{ + const char *entry = ""; + const char *filename = ""; + if (co != NULL) { + if (co->co_qualname != NULL) { + entry = PyUnicode_AsUTF8(co->co_qualname); + } + if (co->co_filename != NULL) { + filename = PyUnicode_AsUTF8(co->co_filename); + } + } + perf_map_jit_write_entry_with_name(state, code_addr, code_size, + entry, filename); +} + +void +_PyPerfJit_WriteNamedCode(const void *code_addr, size_t code_size, + const char *entry, const char *filename) +{ + perf_map_jit_write_entry_with_name( + NULL, code_addr, code_size, entry, filename); +} + // ============================================================================= // CLEANUP AND FINALIZATION // ============================================================================= @@ -1346,15 +774,12 @@ static int perf_map_jit_fini(void* state) { * writing to the file when we close it. This prevents corruption * and ensures all data is properly flushed. */ + PyMutex_Lock(&perf_jit_map_state.map_lock); if (perf_jit_map_state.perf_map != NULL) { - PyThread_acquire_lock(perf_jit_map_state.map_lock, 1); fclose(perf_jit_map_state.perf_map); // This also flushes buffers - PyThread_release_lock(perf_jit_map_state.map_lock); - - /* Clean up synchronization primitive */ - PyThread_free_lock(perf_jit_map_state.map_lock); perf_jit_map_state.perf_map = NULL; } + PyMutex_Unlock(&perf_jit_map_state.map_lock); /* * Unmap the memory region diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c index 0d835f3b7f5..58c61e64bfc 100644 --- a/Python/perf_trampoline.c +++ b/Python/perf_trampoline.c @@ -243,7 +243,7 @@ perf_trampoline_code_watcher(PyCodeEvent event, PyCodeObject *co) static void perf_map_write_entry(void *state, const void *code_addr, - unsigned int code_size, PyCodeObject *co) + size_t code_size, PyCodeObject *co) { const char *entry = ""; if (co->co_qualname != NULL) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 1ee0b3bec68..c6447d03369 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2707,7 +2707,7 @@ PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void) { PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry( const void *code_addr, - unsigned int code_size, + size_t code_size, const char *entry_name ) { #ifndef MS_WINDOWS @@ -2718,7 +2718,7 @@ PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry( } } PyThread_acquire_lock(perf_map_state.map_lock, 1); - fprintf(perf_map_state.perf_map, "%" PRIxPTR " %x %s\n", (uintptr_t) code_addr, code_size, entry_name); + fprintf(perf_map_state.perf_map, "%" PRIxPTR " %zx %s\n", (uintptr_t) code_addr, code_size, entry_name); fflush(perf_map_state.perf_map); PyThread_release_lock(perf_map_state.map_lock); #endif diff --git a/Tools/build/smelly.py b/Tools/build/smelly.py index 7197d70bc8b..17547d4d916 100755 --- a/Tools/build/smelly.py +++ b/Tools/build/smelly.py @@ -25,6 +25,8 @@ # "Legacy": some old symbols are prefixed by "PY_". EXCEPTIONS = frozenset({ 'PY_TIMEOUT_MAX', + '__jit_debug_descriptor', + '__jit_debug_register_code', }) IGNORED_EXTENSION = "_ctypes_test" diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index a251a045b91..a16d5773d55 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -324,8 +324,10 @@ def format_tsv_lines(lines): _abs('Objects/stringlib/unicode_format.h'): (10_000, 400), _abs('Objects/typeobject.c'): (380_000, 13_000), _abs('Python/compile.c'): (20_000, 500), + _abs('Python/jit_unwind.c'): (20_000, 300), _abs('Python/optimizer.c'): (100_000, 5_000), _abs('Python/parking_lot.c'): (40_000, 1000), + _abs('Python/perf_jit_trampoline.c'): (40_000, 1000), _abs('Python/pylifecycle.c'): (750_000, 5000), _abs('Python/pystate.c'): (750_000, 5000), _abs('Python/initconfig.c'): (50_000, 500), diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index d2489387f46..aa89e312b62 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -386,6 +386,8 @@ Python/intrinsics.c - _PyIntrinsics_UnaryFunctions - Python/intrinsics.c - _PyIntrinsics_BinaryFunctions - Python/lock.c - TIME_TO_BE_FAIR_NS - Python/opcode_targets.h - opcode_targets - +Python/jit_unwind.c - __jit_debug_descriptor - +Python/jit_unwind.c - _Py_jit_debug_mutex - Python/perf_trampoline.c - _Py_perfmap_callbacks - Python/perf_jit_trampoline.c - _Py_perfmap_jit_callbacks - Python/perf_jit_trampoline.c - perf_jit_map_state - diff --git a/Tools/jit/README.md b/Tools/jit/README.md index 9361f39dcc6..2a687bb9e89 100644 --- a/Tools/jit/README.md +++ b/Tools/jit/README.md @@ -9,7 +9,7 @@ ## Installing LLVM The JIT compiler does not require end users to install any third-party dependencies, but part of it must be *built* using LLVM[^why-llvm]. You are *not* required to build the rest of CPython using LLVM, or even the same version of LLVM (in fact, this is uncommon). -LLVM version 21 is the officially supported version. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-21`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code. +LLVM version 21 is the officially supported version. The tools `clang`, `llvm-readobj`, `llvm-objdump`, and `llvm-dwarfdump` need to be installed and discoverable (version suffixes, like `clang-21`, are okay). You can customize the LLVM configuration using environment variables before running configure: @@ -85,7 +85,7 @@ ## Miscellaneous [^pep-744]: [PEP 744](https://peps.python.org/pep-0744/) -[^why-llvm]: Clang is specifically needed because it's the only C compiler with support for guaranteed tail calls (`musttail`), which are required by CPython's continuation-passing-style approach to JIT compilation. Since LLVM also includes other functionalities we need (namely, object file parsing and disassembly), it's convenient to only support one toolchain at this time. +[^why-llvm]: Clang is specifically needed because it's the only C compiler with support for guaranteed tail calls (`musttail`), which are required by CPython's continuation-passing-style approach to JIT compilation. Since LLVM also includes other functionalities we need (namely, object file parsing, disassembly, and DWARF inspection), it's convenient to only support one toolchain at this time. ### Understanding JIT behavior diff --git a/Tools/jit/_dwarf.py b/Tools/jit/_dwarf.py new file mode 100644 index 00000000000..5b6b148562e --- /dev/null +++ b/Tools/jit/_dwarf.py @@ -0,0 +1,236 @@ +"""Utilities for deriving JIT unwind information from DWARF CFI.""" + +import dataclasses +import pathlib +import re +import typing + +_LLVMRun = typing.Callable[..., typing.Awaitable[str]] + + +@dataclasses.dataclass(frozen=True) +class UnwindInfo: + code_alignment_factor: int + data_alignment_factor: int + return_address_register: int + cfa_register: int + cfa_offset: int + frame_pointer_register: int + frame_pointer_offset: int + return_address_offset: int + + +@dataclasses.dataclass(frozen=True) +class ELFUnwindConfig: + frame_pointer: str + return_address: str + register_numbers: typing.Mapping[str, int] + call_instruction_prefixes: tuple[str, ...] + + def is_call_instruction(self, instruction: str) -> bool: + return instruction.startswith(self.call_instruction_prefixes) + + +@dataclasses.dataclass(frozen=True) +class _UnwindRow: + pc: int + cfa_register: str + cfa_offset: int + saved_registers: dict[str, int] + + +class ELFUnwindInfo: + def __init__( + self, + target_name: str, + *, + config: ELFUnwindConfig, + verbose: bool = False, + llvm_version: str, + llvm_tools_install_dir: str | None = None, + llvm_run: _LLVMRun, + ) -> None: + self.target_name = target_name + self.config = config + self.verbose = verbose + self.llvm_version = llvm_version + self.llvm_tools_install_dir = llvm_tools_install_dir + self.llvm_run = llvm_run + + @staticmethod + def _parse_dwarfdump_int( + dump: str, field: str, *, required: bool = True + ) -> int | None: + match = re.search(rf"^\s*{field}:\s+(-?\d+)$", dump, re.MULTILINE) + if match is None: + if required: + raise ValueError(f"missing {field} in llvm-dwarfdump output") + return None + return int(match.group(1)) + + @staticmethod + def _parse_dwarfdump_rows(dump: str) -> list[_UnwindRow]: + row_pattern = re.compile( + r"^\s*0x(?P[0-9a-f]+):\s+" + r"CFA=(?P[A-Z][A-Z0-9]*)" + r"(?P[+-]\d+)?" + r"(?::\s*(?P.*))?$" + ) + saved_pattern = re.compile( + r"(?P[A-Z][A-Z0-9]*)=\[CFA(?P[+-]\d+)?\]" + ) + rows = [] + for line in dump.splitlines(): + row_match = row_pattern.match(line) + if row_match is None: + continue + saved_registers = {} + saved = row_match["saved"] + if saved: + for saved_match in saved_pattern.finditer(saved): + offset = saved_match["offset"] + saved_registers[saved_match["register"]] = ( + int(offset) if offset is not None else 0 + ) + cfa_offset = row_match["cfa_offset"] + rows.append( + _UnwindRow( + pc=int(row_match["pc"], 16), + cfa_register=row_match["cfa_register"], + cfa_offset=int(cfa_offset) if cfa_offset is not None else 0, + saved_registers=saved_registers, + ) + ) + if not rows: + raise ValueError("missing interpreted CFI rows in llvm-dwarfdump output") + return rows + + @staticmethod + def _parse_objdump_instructions(dump: str) -> list[tuple[int, str]]: + instructions = [] + for line in dump.splitlines(): + match = re.match( + r"^\s*(?P[0-9a-f]+):\s+" + r"(?:(?:[0-9a-f]{2}|[0-9a-f]{8})\s+)+" + r"(?P.+)$", + line, + ) + if match: + instructions.append( + ( + int(match["pc"], 16), + re.sub(r"\s+", " ", match["instruction"].strip()), + ) + ) + if not instructions: + raise ValueError("missing instructions in llvm-objdump output") + return instructions + + def _reg_number(self, register: str) -> int: + try: + return self.config.register_numbers[register] + except KeyError as exc: + raise ValueError( + f"unsupported register {register!r} in llvm-dwarfdump output" + ) from exc + + @staticmethod + def _encoded_cfa_offset(byte_offset: int, data_alignment_factor: int) -> int: + if data_alignment_factor == 0: + raise ValueError("DWARF data alignment factor must not be zero") + if byte_offset % data_alignment_factor: + raise ValueError( + f"offset {byte_offset} is not a multiple of " + f"data alignment factor {data_alignment_factor}" + ) + return byte_offset // data_alignment_factor + + async def _read_objdump(self, output: pathlib.Path) -> str: + return await self.llvm_run( + "llvm-objdump", + ["-d", f"{output}"], + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, + ) + + async def _read_eh_frame(self, output: pathlib.Path) -> str: + return await self.llvm_run( + "llvm-dwarfdump", + ["--eh-frame", f"{output}"], + echo=self.verbose, + llvm_version=self.llvm_version, + llvm_tools_install_dir=self.llvm_tools_install_dir, + ) + + def _executor_call_pc(self, disassembly: str) -> int: + calls = [ + pc + for pc, instruction in self._parse_objdump_instructions(disassembly) + if self.config.is_call_instruction(instruction) + ] + if len(calls) != 1: + raise ValueError( + f"{self.target_name} JIT shim should contain exactly one executor call" + ) + call_pc = calls[0] + return call_pc + + def _active_row(self, eh_frame: str, call_pc: int) -> _UnwindRow: + rows = self._parse_dwarfdump_rows(eh_frame) + active_rows = [row for row in rows if row.pc <= call_pc] + if not active_rows: + raise ValueError( + f"{self.target_name} JIT shim has no CFI row for executor call " + f"at 0x{call_pc:x}" + ) + return max(active_rows, key=lambda row: row.pc) + + def _check_saved_registers(self, row: _UnwindRow) -> None: + if ( + self.config.frame_pointer not in row.saved_registers + or self.config.return_address not in row.saved_registers + ): + raise ValueError( + f"{self.target_name} JIT shim CFI row at 0x{row.pc:x} " + f"does not save {self.config.frame_pointer} and " + f"{self.config.return_address}" + ) + + def _build_unwind_info(self, eh_frame: str, active_row: _UnwindRow) -> UnwindInfo: + code_alignment_factor = self._parse_dwarfdump_int( + eh_frame, "Code alignment factor" + ) + data_alignment_factor = self._parse_dwarfdump_int( + eh_frame, "Data alignment factor" + ) + return_address_register = self._parse_dwarfdump_int( + eh_frame, "Return address column" + ) + assert code_alignment_factor is not None + assert data_alignment_factor is not None + assert return_address_register is not None + return UnwindInfo( + code_alignment_factor=code_alignment_factor, + data_alignment_factor=data_alignment_factor, + return_address_register=return_address_register, + cfa_register=self._reg_number(active_row.cfa_register), + cfa_offset=active_row.cfa_offset, + frame_pointer_register=self._reg_number(self.config.frame_pointer), + frame_pointer_offset=self._encoded_cfa_offset( + active_row.saved_registers[self.config.frame_pointer], + data_alignment_factor, + ), + return_address_offset=self._encoded_cfa_offset( + active_row.saved_registers[self.config.return_address], + data_alignment_factor, + ), + ) + + async def extract(self, output: pathlib.Path) -> UnwindInfo: + disassembly = await self._read_objdump(output) + call_pc = self._executor_call_pc(disassembly) + eh_frame = await self._read_eh_frame(output) + active_row = self._active_row(eh_frame, call_pc) + self._check_saved_registers(active_row) + return self._build_unwind_info(eh_frame, active_row) diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index 15cac3de3fe..ceee383ea68 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -12,6 +12,7 @@ import typing import shlex +import _dwarf import _llvm import _optimizers import _schema @@ -37,6 +38,27 @@ ) +_ELF_UNWIND_AARCH64 = _dwarf.ELFUnwindConfig( + frame_pointer="W29", + return_address="W30", + register_numbers={ + "W29": 29, + "W30": 30, + }, + call_instruction_prefixes=("blr ",), +) + +_ELF_UNWIND_X86_64 = _dwarf.ELFUnwindConfig( + frame_pointer="RBP", + return_address="RIP", + register_numbers={ + "RBP": 6, + "RIP": 16, + }, + call_instruction_prefixes=("callq ", "call "), +) + + @dataclasses.dataclass class _Target(typing.Generic[_S, _R]): triple: str @@ -52,6 +74,7 @@ class _Target(typing.Generic[_S, _R]): verbose: bool = False cflags: str = "" frame_pointers: bool = False + unwind: _dwarf.ELFUnwindConfig | None = None llvm_version: str = _llvm._LLVM_VERSION llvm_tools_install_dir: str | None = None known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) @@ -88,6 +111,32 @@ def _compute_digest(self) -> str: hasher.update(pathlib.Path(dirpath, filename).read_bytes()) return hasher.hexdigest() + def _write_generated_header( + self, + output: pathlib.Path, + *, + digest: str, + comment: str, + lines: typing.Iterable[str], + ) -> None: + output_new = output.with_name(f"{output.name}.new") + try: + with output_new.open("w") as file: + file.write(digest) + if comment: + file.write(f"// {comment}\n") + file.write("\n") + for line in lines: + file.write(f"{line}\n") + try: + output_new.replace(output) + except FileNotFoundError: + # another process probably already moved the file + if not output.is_file(): + raise + finally: + output_new.unlink(missing_ok=True) + async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: group = _stencils.StencilGroup() args = ["--disassemble", "--reloc", f"{path}"] @@ -234,7 +283,7 @@ async def _build_shim_object(self, output: pathlib.Path) -> None: args_o += self._shim_compile_args() args_o += [ "-c", - # The linked shim is a real function in the final binary, so + # The shim is a real function in the final binary, so # keep unwind info for debuggers and stack walkers. "-fasynchronous-unwind-tables", ] @@ -251,6 +300,11 @@ async def _build_shim_object(self, output: pathlib.Path) -> None: llvm_tools_install_dir=self.llvm_tools_install_dir, ) + async def _get_shim_unwind_info( + self, output: pathlib.Path + ) -> _dwarf.UnwindInfo | None: + return None + async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: generated_cases = PYTHON_EXECUTOR_CASES_C_H.read_text() cases_and_opnames = sorted( @@ -289,6 +343,7 @@ def build( force: bool = False, jit_stencils: pathlib.Path, jit_shim_object: pathlib.Path, + jit_unwind_info: pathlib.Path, ) -> None: """Build jit_stencils.h and the shim object in the given directory.""" jit_stencils.parent.mkdir(parents=True, exist_ok=True) @@ -300,39 +355,42 @@ def build( outline = "=" * len(warning) print("\n".join(["", outline, warning, request, outline, ""])) digest = f"// {self._compute_digest()}\n" + # The generated headers include the input digest as their first line. + # If every generated artifact is current, skip the expensive rebuild. if ( not force and jit_stencils.exists() and jit_stencils.read_text().startswith(digest) and jit_shim_object.exists() + and jit_unwind_info.exists() + and jit_unwind_info.read_text().startswith(digest) ): return + # Build the shim first so its compiled DWARF CFI can be used to derive + # the unwind rules emitted into jit_unwind_info-.h. ASYNCIO_RUNNER.run(self._build_shim_object(jit_shim_object)) + unwind_info = ASYNCIO_RUNNER.run(self._get_shim_unwind_info(jit_shim_object)) + self._write_generated_header( + jit_unwind_info, + digest=digest, + comment=comment, + lines=_writer.dump_unwind_info(unwind_info), + ) + # Build the uop stencils after the shim metadata has been emitted. stencil_groups = ASYNCIO_RUNNER.run(self._build_stencils()) - jit_stencils_new = jit_stencils.parent / "jit_stencils.h.new" - try: - with jit_stencils_new.open("w") as file: - file.write(digest) - if comment: - file.write(f"// {comment}\n") - file.write("\n") - for line in _writer.dump(stencil_groups, self.known_symbols): - file.write(f"{line}\n") - try: - jit_stencils_new.replace(jit_stencils) - except FileNotFoundError: - # another process probably already moved the file - if not jit_stencils.is_file(): - raise - finally: - jit_stencils_new.unlink(missing_ok=True) + self._write_generated_header( + jit_stencils, + digest=digest, + comment=comment, + lines=_writer.dump(stencil_groups, self.known_symbols), + ) class _COFF( _Target[_schema.COFFSection, _schema.COFFRelocation] ): # pylint: disable = too-few-public-methods def _shim_compile_args(self) -> list[str]: - # The linked shim is part of pythoncore, not a shared extension. + # The shim is part of pythoncore, not a shared extension. # On Windows, Py_BUILD_CORE_MODULE makes public APIs import from # pythonXY.lib, which creates a self-dependency when linking # pythoncore.dll. Build the shim with builtin/core semantics. @@ -450,6 +508,19 @@ class _ELF( symbol_prefix = "" re_global = re.compile(r'\s*\.globl\s+(?P