From 3b276f3f59aba213dce4bd995d4fe66620003e90 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 2 Mar 2026 11:47:32 +0100 Subject: [PATCH 001/196] gh-144748: Make PyErr_CheckSignals raise the exception scheduled by PyThreadState_SetAsyncExc (GH-145178) Co-authored-by: Peter Bierma --- Doc/c-api/exceptions.rst | 5 ++ Doc/c-api/threads.rst | 29 ++++++++---- Include/internal/pycore_ceval.h | 3 ++ Lib/test/test_threading.py | 47 +++++++++++++++++++ ...-02-24-14-46-05.gh-issue-144748.uhnFtE.rst | 2 + Modules/Setup.stdlib.in | 2 +- Modules/_testlimitedcapi.c | 3 ++ Modules/_testlimitedcapi/parts.h | 1 + Modules/_testlimitedcapi/threadstate.c | 25 ++++++++++ Modules/signalmodule.c | 16 +++++-- PCbuild/_testlimitedcapi.vcxproj | 1 + PCbuild/_testlimitedcapi.vcxproj.filters | 1 + Python/ceval_gil.c | 21 +++++++-- 13 files changed, 138 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-02-24-14-46-05.gh-issue-144748.uhnFtE.rst create mode 100644 Modules/_testlimitedcapi/threadstate.c diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 72b013612d77f5..aef191d3a29ac6 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -699,6 +699,8 @@ Signal Handling - Executing a pending :ref:`remote debugger ` script. + - Raise the exception set by :c:func:`PyThreadState_SetAsyncExc`. + If any handler raises an exception, immediately return ``-1`` with that exception set. Any remaining interruptions are left to be processed on the next @@ -714,6 +716,9 @@ Signal Handling This function may now execute a remote debugger script, if remote debugging is enabled. + .. versionchanged:: next + The exception set by :c:func:`PyThreadState_SetAsyncExc` is now raised. + .. c:function:: void PyErr_SetInterrupt() diff --git a/Doc/c-api/threads.rst b/Doc/c-api/threads.rst index 46e713f4b5f96f..41c7fbda2302cf 100644 --- a/Doc/c-api/threads.rst +++ b/Doc/c-api/threads.rst @@ -699,13 +699,25 @@ pointer and a void pointer argument. .. c:function:: int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) - Asynchronously raise an exception in a thread. The *id* argument is the thread - id of the target thread; *exc* is the exception object to be raised. This - function does not steal any references to *exc*. To prevent naive misuse, you - must write your own C extension to call this. Must be called with an :term:`attached thread state`. - Returns the number of thread states modified; this is normally one, but will be - zero if the thread id isn't found. If *exc* is ``NULL``, the pending - exception (if any) for the thread is cleared. This raises no exceptions. + Schedule an exception to be raised asynchronously in a thread. + If the thread has a previously scheduled exception, it is overwritten. + + The *id* argument is the thread id of the target thread, as returned by + :c:func:`PyThread_get_thread_ident`. + *exc* is the class of the exception to be raised, or ``NULL`` to clear + the pending exception (if any). + + Return the number of affected thread states. + This is normally ``1`` if *id* is found, even when no change was + made (the given *exc* was already pending, or *exc* is ``NULL`` but + no exception is pending). + If the thread id isn't found, return ``0``. This raises no exceptions. + + To prevent naive misuse, you must write your own C extension to call this. + This function must be called with an :term:`attached thread state`. + This function does not steal any references to *exc*. + This function does not necessarily interrupt system calls such as + :py:func:`~time.sleep`. .. versionchanged:: 3.7 The type of the *id* parameter changed from :c:expr:`long` to @@ -743,7 +755,8 @@ Operating system thread APIs :term:`attached thread state`. .. seealso:: - :py:func:`threading.get_ident` + :py:func:`threading.get_ident` and :py:attr:`threading.Thread.ident` + expose this identifier to Python. .. c:function:: PyObject *PyThread_GetInfo(void) diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 1ee1f830827576..f27ec4350bb2c8 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -286,6 +286,9 @@ PyAPI_FUNC(PyObject *)_Py_MakeCoro(PyFunctionObject *func); and asynchronous exception */ PyAPI_FUNC(int) _Py_HandlePending(PyThreadState *tstate); +/* Raise exception set by PyThreadState_SetAsyncExc, if any */ +PyAPI_FUNC(int) _PyEval_RaiseAsyncExc(PyThreadState *tstate); + extern PyObject * _PyEval_GetFrameLocals(void); typedef PyObject *(*conversion_func)(PyObject *); diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index bdfd03b1e58f62..0ca91ce0d7899d 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -412,6 +412,53 @@ def run(self): t.join() # else the thread is still running, and we have no way to kill it + @cpython_only + @unittest.skipUnless(hasattr(signal, "pthread_kill"), "need pthread_kill") + @unittest.skipUnless(hasattr(signal, "SIGUSR1"), "need SIGUSR1") + def test_PyThreadState_SetAsyncExc_interrupts_sleep(self): + _testcapi = import_module("_testlimitedcapi") + + worker_started = threading.Event() + + class InjectedException(Exception): + """Custom exception for testing""" + + caught_exception = None + + def catch_exception(): + nonlocal caught_exception + day_as_seconds = 60 * 60 * 24 + try: + worker_started.set() + time.sleep(day_as_seconds) + except InjectedException as exc: + caught_exception = exc + + thread = threading.Thread(target=catch_exception) + thread.start() + worker_started.wait() + + signal.signal(signal.SIGUSR1, lambda sig, frame: None) + + result = _testcapi.threadstate_set_async_exc( + thread.ident, InjectedException) + self.assertEqual(result, 1) + + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if not thread.is_alive(): + break + try: + signal.pthread_kill(thread.ident, signal.SIGUSR1) + except OSError: + # The thread might have terminated between the is_alive check + # and the pthread_kill + break + + thread.join() + signal.signal(signal.SIGUSR1, signal.SIG_DFL) + + self.assertIsInstance(caught_exception, InjectedException) + def test_limbo_cleanup(self): # Issue 7481: Failure to start thread should cleanup the limbo map. def fail_new_thread(*args, **kwargs): 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 new file mode 100644 index 00000000000000..bda7003be94e54 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-02-24-14-46-05.gh-issue-144748.uhnFtE.rst @@ -0,0 +1,2 @@ +:c:func:`PyErr_CheckSignals` now raises the exception scheduled by +:c:func:`PyThreadState_SetAsyncExc`, if any. diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 1dd0512832adf7..39be41d9d2a426 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -176,7 +176,7 @@ @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__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/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.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 @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_testlimitedcapi.c b/Modules/_testlimitedcapi.c index 4dae99ec92a085..d3eb02d4727347 100644 --- a/Modules/_testlimitedcapi.c +++ b/Modules/_testlimitedcapi.c @@ -77,6 +77,9 @@ PyInit__testlimitedcapi(void) if (_PyTestLimitedCAPI_Init_Sys(mod) < 0) { return NULL; } + if (_PyTestLimitedCAPI_Init_ThreadState(mod) < 0) { + return NULL; + } if (_PyTestLimitedCAPI_Init_Tuple(mod) < 0) { return NULL; } diff --git a/Modules/_testlimitedcapi/parts.h b/Modules/_testlimitedcapi/parts.h index 60f6f03011a65c..1cbb4f5659af0f 100644 --- a/Modules/_testlimitedcapi/parts.h +++ b/Modules/_testlimitedcapi/parts.h @@ -38,6 +38,7 @@ int _PyTestLimitedCAPI_Init_Long(PyObject *module); int _PyTestLimitedCAPI_Init_PyOS(PyObject *module); int _PyTestLimitedCAPI_Init_Set(PyObject *module); int _PyTestLimitedCAPI_Init_Sys(PyObject *module); +int _PyTestLimitedCAPI_Init_ThreadState(PyObject *module); int _PyTestLimitedCAPI_Init_Tuple(PyObject *module); int _PyTestLimitedCAPI_Init_Unicode(PyObject *module); int _PyTestLimitedCAPI_Init_VectorcallLimited(PyObject *module); diff --git a/Modules/_testlimitedcapi/threadstate.c b/Modules/_testlimitedcapi/threadstate.c new file mode 100644 index 00000000000000..f2539d97150d69 --- /dev/null +++ b/Modules/_testlimitedcapi/threadstate.c @@ -0,0 +1,25 @@ +#include "parts.h" +#include "util.h" + +static PyObject * +threadstate_set_async_exc(PyObject *module, PyObject *args) +{ + unsigned long id; + PyObject *exc; + if (!PyArg_ParseTuple(args, "kO", &id, &exc)) { + return NULL; + } + int result = PyThreadState_SetAsyncExc(id, exc); + return PyLong_FromLong(result); +} + +static PyMethodDef test_methods[] = { + {"threadstate_set_async_exc", threadstate_set_async_exc, METH_VARARGS, NULL}, + {NULL}, +}; + +int +_PyTestLimitedCAPI_Init_ThreadState(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 4d0e224ff757e7..5060e4097d33c9 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1781,20 +1781,28 @@ PyErr_CheckSignals(void) Python code to ensure signals are handled. Checking for the GC here allows long running native code to clean cycles created using the C-API even if it doesn't run the evaluation loop */ - if (_Py_eval_breaker_bit_is_set(tstate, _PY_GC_SCHEDULED_BIT)) { + uintptr_t breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); + if (breaker & _PY_GC_SCHEDULED_BIT) { _Py_unset_eval_breaker_bit(tstate, _PY_GC_SCHEDULED_BIT); _Py_RunGC(tstate); } + if (breaker & _PY_ASYNC_EXCEPTION_BIT) { + if (_PyEval_RaiseAsyncExc(tstate) < 0) { + return -1; + } + } #if defined(Py_REMOTE_DEBUG) && defined(Py_SUPPORTS_REMOTE_DEBUG) _PyRunRemoteDebugger(tstate); #endif - if (!_Py_ThreadCanHandleSignals(tstate->interp)) { - return 0; + if (_Py_ThreadCanHandleSignals(tstate->interp)) { + if (_PyErr_CheckSignalsTstate(tstate) < 0) { + return -1; + } } - return _PyErr_CheckSignalsTstate(tstate); + return 0; } diff --git a/PCbuild/_testlimitedcapi.vcxproj b/PCbuild/_testlimitedcapi.vcxproj index 36c41fc9824fda..935467dfcb3283 100644 --- a/PCbuild/_testlimitedcapi.vcxproj +++ b/PCbuild/_testlimitedcapi.vcxproj @@ -110,6 +110,7 @@ + diff --git a/PCbuild/_testlimitedcapi.vcxproj.filters b/PCbuild/_testlimitedcapi.vcxproj.filters index 62ecb2f70ffa2d..5e0a0f65cfcc3d 100644 --- a/PCbuild/_testlimitedcapi.vcxproj.filters +++ b/PCbuild/_testlimitedcapi.vcxproj.filters @@ -26,6 +26,7 @@ + diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 88cc66e97f3424..2425bc1b39f0dc 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -1423,11 +1423,7 @@ _Py_HandlePending(PyThreadState *tstate) /* Check for asynchronous exception. */ if ((breaker & _PY_ASYNC_EXCEPTION_BIT) != 0) { - _Py_unset_eval_breaker_bit(tstate, _PY_ASYNC_EXCEPTION_BIT); - PyObject *exc = _Py_atomic_exchange_ptr(&tstate->async_exc, NULL); - if (exc != NULL) { - _PyErr_SetNone(tstate, exc); - Py_DECREF(exc); + if (_PyEval_RaiseAsyncExc(tstate) < 0) { return -1; } } @@ -1438,3 +1434,18 @@ _Py_HandlePending(PyThreadState *tstate) return 0; } + +int +_PyEval_RaiseAsyncExc(PyThreadState *tstate) +{ + assert(tstate != NULL); + assert(tstate == _PyThreadState_GET()); + _Py_unset_eval_breaker_bit(tstate, _PY_ASYNC_EXCEPTION_BIT); + PyObject *exc = _Py_atomic_exchange_ptr(&tstate->async_exc, NULL); + if (exc != NULL) { + _PyErr_SetNone(tstate, exc); + Py_DECREF(exc); + return -1; + } + return 0; +} From 8bcb3eaa67959ec32bc4d683a79a0a67885925db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Mon, 2 Mar 2026 12:01:32 +0100 Subject: [PATCH 002/196] gh-144851: Fix `__lazy_import__` crash with user-defined filters (#144852) --- Lib/test/test_lazy_import/__init__.py | 5 +++++ Python/import.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index df19af05246dcd..5d30ec2299789b 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -391,6 +391,11 @@ def test_dunder_lazy_import(self): import test.test_lazy_import.data.dunder_lazy_import self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) + def test_dunder_lazy_import_with_custom_filter(self): + sys.set_lazy_imports_filter(lambda importer, imported, fromlist: False) + import test.test_lazy_import.data.dunder_lazy_import + self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + def test_dunder_lazy_import_used(self): """Using __lazy_import__ result should trigger module load.""" import test.test_lazy_import.data.dunder_lazy_import_used diff --git a/Python/import.c b/Python/import.c index 4c234a4a70437c..dfc4d5707bfdba 100644 --- a/Python/import.c +++ b/Python/import.c @@ -4512,6 +4512,10 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, assert(!PyErr_Occurred()); modname = Py_NewRef(Py_None); } + if (fromlist == NULL) { + assert(!PyErr_Occurred()); + fromlist = Py_NewRef(Py_None); + } PyObject *args[] = {modname, name, fromlist}; PyObject *res = PyObject_Vectorcall(filter, args, 3, NULL); From e54225545866d780b12d8e70c33d25fc13b2c3a9 Mon Sep 17 00:00:00 2001 From: Facundo Batista Date: Mon, 2 Mar 2026 08:56:28 -0300 Subject: [PATCH 003/196] gh-144835: Added missing explanations for some parameters in glob and iglob. (#144836) * Added missing explanations for some parameters in glob and iglob. * News entry. * Added proper 'func' indication in News file. * Consistent use of backticks. * Improved wording. * consistent wording between the two docstrings --------- Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com> --- Lib/glob.py | 27 ++++++++++++++++--- ...-02-15-12-02-20.gh-issue-144835.w_oS_J.rst | 2 ++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-15-12-02-20.gh-issue-144835.w_oS_J.rst diff --git a/Lib/glob.py b/Lib/glob.py index c2f8ce279aba64..575e4bcba5be0d 100644 --- a/Lib/glob.py +++ b/Lib/glob.py @@ -15,7 +15,7 @@ def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, include_hidden=False): - """Return a list of paths matching a pathname pattern. + """Return a list of paths matching a `pathname` pattern. The pattern may contain simple shell-style wildcards a la fnmatch. Unlike fnmatch, filenames starting with a @@ -25,6 +25,15 @@ def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, The order of the returned list is undefined. Sort it if you need a particular order. + If `root_dir` is not None, it should be a path-like object specifying the + root directory for searching. It has the same effect as changing the + current directory before calling it (without actually + changing it). If pathname is relative, the result will contain + paths relative to `root_dir`. + + If `dir_fd` is not None, it should be a file descriptor referring to a + directory, and paths will then be relative to that directory. + If `include_hidden` is true, the patterns '*', '?', '**' will match hidden directories. @@ -36,7 +45,7 @@ def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False, include_hidden=False): - """Return an iterator which yields the paths matching a pathname pattern. + """Return an iterator which yields the paths matching a `pathname` pattern. The pattern may contain simple shell-style wildcards a la fnmatch. However, unlike fnmatch, filenames starting with a @@ -46,7 +55,19 @@ def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False, The order of the returned paths is undefined. Sort them if you need a particular order. - If recursive is true, the pattern '**' will match any files and + If `root_dir` is not None, it should be a path-like object specifying + the root directory for searching. It has the same effect as changing + the current directory before calling it (without actually + changing it). If pathname is relative, the result will contain + paths relative to `root_dir`. + + If `dir_fd` is not None, it should be a file descriptor referring to a + directory, and paths will then be relative to that directory. + + If `include_hidden` is true, the patterns '*', '?', '**' will match hidden + directories. + + If `recursive` is true, the pattern '**' will match any files and zero or more directories and subdirectories. """ sys.audit("glob.glob", pathname, recursive) 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 new file mode 100644 index 00000000000000..9d603b51c48a93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-15-12-02-20.gh-issue-144835.w_oS_J.rst @@ -0,0 +1,2 @@ +Added missing explanations for some parameters in :func:`glob.glob` and +:func:`glob.iglob`. From b611db491d16ebbb4c833e9a184bb987e41f9fbe Mon Sep 17 00:00:00 2001 From: zhong <60600792+superboy-zjc@users.noreply.github.com> Date: Mon, 2 Mar 2026 20:30:38 +0800 Subject: [PATCH 004/196] gh-142781: Fix type confusion in zoneinfo weak cache (GH-142925) 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: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- Lib/test/test_zoneinfo/test_zoneinfo.py | 38 +++++++++++++++++++ ...-12-18-00-14-16.gh-issue-142781.gcOeYF.rst | 2 + Modules/_zoneinfo.c | 11 +++++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2025-12-18-00-14-16.gh-issue-142781.gcOeYF.rst diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py b/Lib/test/test_zoneinfo/test_zoneinfo.py index 581072d0701d65..a5dea802a9898d 100644 --- a/Lib/test/test_zoneinfo/test_zoneinfo.py +++ b/Lib/test/test_zoneinfo/test_zoneinfo.py @@ -1577,6 +1577,44 @@ class EvilZoneInfo(self.klass): class CZoneInfoCacheTest(ZoneInfoCacheTest): module = c_zoneinfo + def test_inconsistent_weak_cache_get(self): + class Cache: + def get(self, key, default=None): + return 1337 + + class ZI(self.klass): + pass + # Class attribute must be set after class creation + # to override zoneinfo.ZoneInfo.__init_subclass__. + ZI._weak_cache = Cache() + + with self.assertRaises(RuntimeError) as te: + ZI("America/Los_Angeles") + self.assertEqual( + str(te.exception), + "Unexpected instance of int in ZI weak cache for key 'America/Los_Angeles'" + ) + + def test_inconsistent_weak_cache_setdefault(self): + class Cache: + def get(self, key, default=None): + return default + def setdefault(self, key, value): + return 1337 + + class ZI(self.klass): + pass + # Class attribute must be set after class creation + # to override zoneinfo.ZoneInfo.__init_subclass__. + ZI._weak_cache = Cache() + + with self.assertRaises(RuntimeError) as te: + ZI("America/Los_Angeles") + self.assertEqual( + str(te.exception), + "Unexpected instance of int in ZI weak cache for key 'America/Los_Angeles'" + ) + class ZoneInfoPickleTest(TzPathUserMixin, ZoneInfoTestBase): module = py_zoneinfo 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 new file mode 100644 index 00000000000000..772e05766c5c69 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-18-00-14-16.gh-issue-142781.gcOeYF.rst @@ -0,0 +1,2 @@ +:mod:`zoneinfo`: fix a crash when instantiating :class:`~zoneinfo.ZoneInfo` +objects for which the internal class-level cache is inconsistent. diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index e07dfd19efa06d..39671d1ab51dfa 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -335,6 +335,7 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key) return NULL; } + ((PyZoneInfo_ZoneInfo *)tmp)->source = SOURCE_CACHE; instance = PyObject_CallMethod(weak_cache, "setdefault", "OO", key, tmp); Py_DECREF(tmp); @@ -342,7 +343,15 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key) Py_DECREF(weak_cache); return NULL; } - ((PyZoneInfo_ZoneInfo *)instance)->source = SOURCE_CACHE; + } + + if (!PyObject_TypeCheck(instance, type)) { + PyErr_Format(PyExc_RuntimeError, + "Unexpected instance of %T in %s weak cache for key %R", + instance, _PyType_Name(type), key); + Py_DECREF(instance); + Py_DECREF(weak_cache); + return NULL; } update_strong_cache(state, type, key, instance); From 201d251567738c234081329a244449e08fa86245 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 2 Mar 2026 10:54:26 -0500 Subject: [PATCH 005/196] DOC: clarify and expand documentation about PYTHONUSERBASE and PYTHONNOUSERSITE (#144637) --- Doc/library/site.rst | 3 ++- Doc/library/sys_path_init.rst | 25 ++++++++++++++----------- Doc/using/cmdline.rst | 8 ++++++-- Lib/site.py | 6 ++++-- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Doc/library/site.rst b/Doc/library/site.rst index 4686c9fc92ced2..04895ae4ec524b 100644 --- a/Doc/library/site.rst +++ b/Doc/library/site.rst @@ -64,7 +64,8 @@ When running under a :ref:`virtual environment ` to :data:`sys.path`. + This is equivalent to the :option:`-s` option. If this is set, Python won't + add the :data:`user site-packages directory ` to + :data:`sys.path`. .. seealso:: @@ -964,6 +965,9 @@ conflict. and :ref:`installation paths ` for ``python -m pip install --user``. + To disable the user site-packages, see :envvar:`PYTHONNOUSERSITE` or the :option:`-s` + option. + .. seealso:: :pep:`370` -- Per user site-packages directory diff --git a/Lib/site.py b/Lib/site.py index 1b7a656551b853..5f09a7dd8c91c0 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -18,9 +18,11 @@ it is also checked for site-packages (sys.base_prefix and sys.base_exec_prefix will always be the "real" prefixes of the Python installation). If "pyvenv.cfg" (a bootstrap configuration file) contains -the key "include-system-site-packages" set to anything other than "false" +the key "include-system-site-packages" is set to "true" (case-insensitive), the system-level prefixes will still also be -searched for site-packages; otherwise they won't. +searched for site-packages; otherwise they won't. If the system-level +prefixes are not included then the user site prefixes are also implicitly +not searched for site-packages. All of the resulting site-specific directories, if they exist, are appended to sys.path, and also inspected for path configuration From 1cf5abedeb97ff6ed222afd28e650b9ecc384094 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Mon, 2 Mar 2026 16:10:15 +0000 Subject: [PATCH 006/196] gh-145307: Defer loading psapi.dll until ctypes.util.dllist() is called. (GH-145308) --- Lib/ctypes/util.py | 26 ++++++++++++------- ...-02-27-10-57-20.gh-issue-145307.ueoT7j.rst | 2 ++ 2 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2026-02-27-10-57-20.gh-issue-145307.ueoT7j.rst diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 378f12167c6842..3b21658433b2ed 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -85,15 +85,10 @@ def find_library(name): wintypes.DWORD, ) - _psapi = ctypes.WinDLL('psapi', use_last_error=True) - _enum_process_modules = _psapi["EnumProcessModules"] - _enum_process_modules.restype = wintypes.BOOL - _enum_process_modules.argtypes = ( - wintypes.HANDLE, - ctypes.POINTER(wintypes.HMODULE), - wintypes.DWORD, - wintypes.LPDWORD, - ) + # gh-145307: We defer loading psapi.dll until _get_module_handles is called. + # Loading additional DLLs at startup for functionality that may never be + # used is wasteful. + _enum_process_modules = None def _get_module_filename(module: wintypes.HMODULE): name = (wintypes.WCHAR * 32767)() # UNICODE_STRING_MAX_CHARS @@ -101,8 +96,19 @@ def _get_module_filename(module: wintypes.HMODULE): return name.value return None - def _get_module_handles(): + global _enum_process_modules + if _enum_process_modules is None: + _psapi = ctypes.WinDLL('psapi', use_last_error=True) + _enum_process_modules = _psapi["EnumProcessModules"] + _enum_process_modules.restype = wintypes.BOOL + _enum_process_modules.argtypes = ( + wintypes.HANDLE, + ctypes.POINTER(wintypes.HMODULE), + wintypes.DWORD, + wintypes.LPDWORD, + ) + process = _get_current_process() space_needed = wintypes.DWORD() n = 1024 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 new file mode 100644 index 00000000000000..6f039197962e10 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-02-27-10-57-20.gh-issue-145307.ueoT7j.rst @@ -0,0 +1,2 @@ +Defers loading of the ``psapi.dll`` module until it is used by +:func:`ctypes.util.dllist`. From 107863ee17788e83ffa63368a33f7afe6f7a1410 Mon Sep 17 00:00:00 2001 From: Hai Zhu Date: Tue, 3 Mar 2026 01:02:38 +0800 Subject: [PATCH 007/196] gh-144569: Avoid creating temporary objects in `BINARY_SLICE` for list, tuple, and unicode (GH-144590) * Scalar replacement of BINARY_SLICE for list, tuple, and unicode --- Include/cpython/ceval.h | 3 + Include/internal/pycore_list.h | 1 + Include/internal/pycore_tuple.h | 1 + Include/internal/pycore_unicodeobject.h | 1 + ...-02-08-13-14-00.gh-issue-144569.pjlJVe.rst | 1 + Modules/_testinternalcapi/test_cases.c.h | 55 +++++++++---- Objects/listobject.c | 24 ++++++ Objects/tupleobject.c | 19 +++++ Objects/unicodeobject.c | 12 +++ Python/bytecodes.c | 29 +++++-- Python/ceval.c | 44 ++++++---- Python/executor_cases.c.h | 82 ++++++++++++++----- Python/generated_cases.c.h | 55 +++++++++---- 13 files changed, 253 insertions(+), 74 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-13-14-00.gh-issue-144569.pjlJVe.rst diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h index ca8109e3248a8d..bbab8d35b75cb2 100644 --- a/Include/cpython/ceval.h +++ b/Include/cpython/ceval.h @@ -23,6 +23,9 @@ _PyEval_RequestCodeExtraIndex(freefunc f) { PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *); PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) _PyEval_UnpackIndices(PyObject *, PyObject *, + Py_ssize_t, + Py_ssize_t *, Py_ssize_t *); // Trampoline API diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h index b39639a9063260..6b92dc5d111f3b 100644 --- a/Include/internal/pycore_list.h +++ b/Include/internal/pycore_list.h @@ -14,6 +14,7 @@ extern "C" { PyAPI_FUNC(PyObject*) _PyList_Extend(PyListObject *, PyObject *); PyAPI_FUNC(PyObject) *_PyList_SliceSubscript(PyObject*, PyObject*); +PyAPI_FUNC(PyObject *) _PyList_BinarySlice(PyObject *, PyObject *, PyObject *); extern void _PyList_DebugMallocStats(FILE *out); // _PyList_GetItemRef should be used only when the object is known as a list // because it doesn't raise TypeError when the object is not a list, whereas PyList_GetItemRef does. diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 46db02593ad106..00562bef769920 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -25,6 +25,7 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *); PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t); PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t); +PyAPI_FUNC(PyObject *) _PyTuple_BinarySlice(PyObject *, PyObject *, PyObject *); typedef struct { PyObject_HEAD diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index 97dda73f9b584d..af6cb84e9ff905 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -32,6 +32,7 @@ extern PyObject* _PyUnicode_ResizeCompact( PyObject *unicode, Py_ssize_t length); extern PyObject* _PyUnicode_GetEmpty(void); +PyAPI_FUNC(PyObject*) _PyUnicode_BinarySlice(PyObject *, PyObject *, PyObject *); /* Generic helper macro to convert characters of different types. 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 new file mode 100644 index 00000000000000..bdd0d6c2f7b944 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-13-14-00.gh-issue-144569.pjlJVe.rst @@ -0,0 +1 @@ +Optimize ``BINARY_SLICE`` for list, tuple, and unicode by avoiding temporary ``slice`` object creation. diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 395c429f7ef3db..79320a4bff17fb 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -1396,28 +1396,53 @@ stop = stack_pointer[-1]; start = stack_pointer[-2]; container = stack_pointer[-3]; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - if (slice == NULL) { - res_o = NULL; + if (PyList_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); } - else { - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + else if (PyTuple_CheckExact(container_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; } - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + else if (PyUnicode_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + } _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(container); + _PyStackRef tmp = stop; + stop = PyStackRef_NULL; + stack_pointer[-1] = stop; + PyStackRef_CLOSE(tmp); + tmp = start; + start = PyStackRef_NULL; + stack_pointer[-2] = start; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-3] = container; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (res_o == NULL) { JUMP_TO_LABEL(error); } diff --git a/Objects/listobject.c b/Objects/listobject.c index 4a98c8e54ab03f..3921b7cd7b69bc 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -716,6 +716,30 @@ list_slice_lock_held(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh) return (PyObject *)np; } +PyObject * +_PyList_BinarySlice(PyObject *container, PyObject *start, PyObject *stop) +{ + assert(PyList_CheckExact(container)); + Py_ssize_t istart = 0; + Py_ssize_t istop = PY_SSIZE_T_MAX; + /* Unpack the index values before acquiring the lock, since + * _PyEval_SliceIndex may call __index__ which could execute + * arbitrary Python code. */ + if (!_PyEval_SliceIndex(start, &istart)) { + return NULL; + } + if (!_PyEval_SliceIndex(stop, &istop)) { + return NULL; + } + PyObject *ret; + Py_BEGIN_CRITICAL_SECTION(container); + Py_ssize_t len = Py_SIZE(container); + PySlice_AdjustIndices(len, &istart, &istop, 1); + ret = list_slice_lock_held((PyListObject *)container, istart, istop); + Py_END_CRITICAL_SECTION(); + return ret; +} + PyObject * PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 169ac69701da11..3c68955495d566 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -472,6 +472,25 @@ tuple_slice(PyTupleObject *a, Py_ssize_t ilow, return PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow); } +PyObject * +_PyTuple_BinarySlice(PyObject *container, PyObject *start, PyObject *stop) +{ + assert(PyTuple_CheckExact(container)); + Py_ssize_t len = Py_SIZE(container); + Py_ssize_t istart, istop; + if (!_PyEval_UnpackIndices(start, stop, len, &istart, &istop)) { + return NULL; + } + if (istart == 0 && istop == len) { + return Py_NewRef(container); + } + if (istop < istart) { + istop = istart; + } + return PyTuple_FromArray(((PyTupleObject *)container)->ob_item + istart, + istop - istart); +} + PyObject * PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 213bae5ca86cd4..7aa85a942e449e 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -12312,6 +12312,18 @@ _PyUnicode_XStrip(PyObject *self, int striptype, PyObject *sepobj) return PyUnicode_Substring(self, i, j); } +PyObject* +_PyUnicode_BinarySlice(PyObject *container, PyObject *start_o, PyObject *stop_o) +{ + assert(PyUnicode_CheckExact(container)); + Py_ssize_t len = PyUnicode_GET_LENGTH(container); + Py_ssize_t istart, istop; + if (!_PyEval_UnpackIndices(start_o, stop_o, len, &istart, &istop)) { + return NULL; + } + return PyUnicode_Substring(container, istart, istop); +} + PyObject* PyUnicode_Substring(PyObject *self, Py_ssize_t start, Py_ssize_t end) { diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 41323c4f54d9ed..8caad077ec07ec 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -866,19 +866,30 @@ dummy_func( } op(_BINARY_SLICE, (container, start, stop -- res)) { - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - // Can't use ERROR_IF() here, because we haven't - // DECREF'ed container yet, and we still own slice. - if (slice == NULL) { - res_o = NULL; + if (PyList_CheckExact(container_o)) { + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); + } + else if (PyTuple_CheckExact(container_o)) { + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); + } + else if (PyUnicode_CheckExact(container_o)) { + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); } else { - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + } } - PyStackRef_CLOSE(container); + DECREF_INPUTS(); ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } diff --git a/Python/ceval.c b/Python/ceval.c index 2cd7c7bfd28d09..3ad46cf1ec85ff 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1,6 +1,7 @@ /* Execute compiled code */ #include "ceval.h" +#include "pycore_long.h" int Py_GetRecursionLimit(void) @@ -2883,23 +2884,10 @@ PyEval_GetFuncDesc(PyObject *func) int _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi) { - PyThreadState *tstate = _PyThreadState_GET(); - if (!Py_IsNone(v)) { - Py_ssize_t x; - if (_PyIndex_Check(v)) { - x = PyNumber_AsSsize_t(v, NULL); - if (x == -1 && _PyErr_Occurred(tstate)) - return 0; - } - else { - _PyErr_SetString(tstate, PyExc_TypeError, - "slice indices must be integers or " - "None or have an __index__ method"); - return 0; - } - *pi = x; + if (Py_IsNone(v)) { + return 1; } - return 1; + return _PyEval_SliceIndexNotNone(v, pi); } int @@ -2907,6 +2895,10 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi) { PyThreadState *tstate = _PyThreadState_GET(); Py_ssize_t x; + if (PyLong_CheckExact(v) && _PyLong_IsCompact((PyLongObject *)v)) { + *pi = _PyLong_CompactValue((PyLongObject *)v); + return 1; + } if (_PyIndex_Check(v)) { x = PyNumber_AsSsize_t(v, NULL); if (x == -1 && _PyErr_Occurred(tstate)) @@ -2922,6 +2914,26 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi) return 1; } +int +_PyEval_UnpackIndices(PyObject *start, PyObject *stop, + Py_ssize_t len, + Py_ssize_t *istart, Py_ssize_t *istop) +{ + if (len < 0) { + return 0; + } + *istart = 0; + *istop = PY_SSIZE_T_MAX; + if (!_PyEval_SliceIndex(start, istart)) { + return 0; + } + if (!_PyEval_SliceIndex(stop, istop)) { + return 0; + } + PySlice_AdjustIndices(len, istart, istop, 1); + return 1; +} + PyObject * _PyEval_ImportName(PyThreadState *tstate, PyObject *builtins, PyObject *globals, PyObject *locals, PyObject *name, diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 4a67ede8a02265..6708a9282077c4 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -5198,33 +5198,77 @@ stop = _stack_item_2; start = _stack_item_1; container = _stack_item_0; - stack_pointer[0] = container; - stack_pointer[1] = start; - stack_pointer[2] = stop; - stack_pointer += 3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - if (slice == NULL) { - res_o = NULL; + if (PyList_CheckExact(container_o)) { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); } - else { - stack_pointer += -2; + else if (PyTuple_CheckExact(container_o)) { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; } - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + else if (PyUnicode_CheckExact(container_o)) { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + stack_pointer[0] = container; + stack_pointer[1] = start; + stack_pointer[2] = stop; + stack_pointer += 3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + } + stack_pointer += 3; + } _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(container); + _PyStackRef tmp = stop; + stop = PyStackRef_NULL; + stack_pointer[-3] = container; + stack_pointer[-2] = start; + stack_pointer[-1] = stop; + PyStackRef_CLOSE(tmp); + tmp = start; + start = PyStackRef_NULL; + stack_pointer[-2] = start; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-3] = container; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (res_o == NULL) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 12362943465e3d..42098c59040f07 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1396,28 +1396,53 @@ stop = stack_pointer[-1]; start = stack_pointer[-2]; container = stack_pointer[-3]; - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), - PyStackRef_AsPyObjectSteal(stop)); - stack_pointer = _PyFrame_GetStackPointer(frame); + PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); + PyObject *start_o = PyStackRef_AsPyObjectBorrow(start); + PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop); PyObject *res_o; - if (slice == NULL) { - res_o = NULL; + if (PyList_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyList_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); } - else { - stack_pointer += -2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + else if (PyTuple_CheckExact(container_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); - res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); - Py_DECREF(slice); + res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; } - stack_pointer += -3; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + else if (PyUnicode_CheckExact(container_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + PyObject *slice = PySlice_New(start_o, stop_o, NULL); + if (slice == NULL) { + res_o = NULL; + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + res_o = PyObject_GetItem(container_o, slice); + Py_DECREF(slice); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + } _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(container); + _PyStackRef tmp = stop; + stop = PyStackRef_NULL; + stack_pointer[-1] = stop; + PyStackRef_CLOSE(tmp); + tmp = start; + start = PyStackRef_NULL; + stack_pointer[-2] = start; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-3] = container; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); if (res_o == NULL) { JUMP_TO_LABEL(error); } From 02288bf0225bea892eaab0d3e13c271761849e22 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Mon, 2 Mar 2026 12:25:13 -0500 Subject: [PATCH 008/196] gh-130555: Fix use-after-free in dict.clear() with embedded values (gh-145268) --- Lib/test/test_dict.py | 63 +++++++++++++++++++ ...-02-26-12-00-00.gh-issue-130555.TMSOIu.rst | 3 + Objects/dictobject.c | 31 ++++++--- 3 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-12-00-00.gh-issue-130555.TMSOIu.rst diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 8a4e19c95a36ef..f28155fe50148d 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1680,6 +1680,69 @@ def test_hash_collision_remove_add(self): self.assertEqual(len(d), len(items), d) self.assertEqual(d, dict(items)) + def test_clear_reentrant_embedded(self): + # gh-130555: dict.clear() must be safe when values are embedded + # in an object and a destructor mutates the dict. + class MyObj: pass + class ClearOnDelete: + def __del__(self): + nonlocal x + del x + + x = MyObj() + x.a = ClearOnDelete() + + d = x.__dict__ + d.clear() + + def test_clear_reentrant_cycle(self): + # gh-130555: dict.clear() must be safe for embedded dicts when the + # object is part of a reference cycle and the last reference to the + # dict is via the cycle. + class MyObj: pass + obj = MyObj() + obj.f = obj + obj.attr = "attr" + + d = obj.__dict__ + del obj + + d.clear() + + def test_clear_reentrant_force_combined(self): + # gh-130555: dict.clear() must be safe when a destructor forces the + # dict from embedded/split to combined (setting ma_values to NULL). + class MyObj: pass + class ForceConvert: + def __del__(self): + d[1] = "trigger" + + x = MyObj() + x.a = ForceConvert() + x.b = "other" + + d = x.__dict__ + d.clear() + + def test_clear_reentrant_delete(self): + # gh-130555: dict.clear() must be safe when a destructor deletes + # a key from the same embedded dict. + class MyObj: pass + class DelKey: + def __del__(self): + try: + del d['b'] + except KeyError: + pass + + x = MyObj() + x.a = DelKey() + x.b = "value_b" + x.c = "value_c" + + d = x.__dict__ + d.clear() + class CAPITest(unittest.TestCase): 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 new file mode 100644 index 00000000000000..5a2106480fb843 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-12-00-00.gh-issue-130555.TMSOIu.rst @@ -0,0 +1,3 @@ +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/Objects/dictobject.c b/Objects/dictobject.c index 35ca9933bfa8ae..bcd3c862fd59b2 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2969,6 +2969,21 @@ _PyDict_DelItemIf(PyObject *op, PyObject *key, return res; } +static void +clear_embedded_values(PyDictValues *values, Py_ssize_t nentries) +{ + PyObject *refs[SHARED_KEYS_MAX_SIZE]; + assert(nentries <= SHARED_KEYS_MAX_SIZE); + for (Py_ssize_t i = 0; i < nentries; i++) { + refs[i] = values->values[i]; + values->values[i] = NULL; + } + values->size = 0; + for (Py_ssize_t i = 0; i < nentries; i++) { + Py_XDECREF(refs[i]); + } +} + static void clear_lock_held(PyObject *op) { @@ -2997,20 +3012,18 @@ clear_lock_held(PyObject *op) assert(oldkeys->dk_refcnt == 1); dictkeys_decref(oldkeys, IS_DICT_SHARED(mp)); } + else if (oldvalues->embedded) { + clear_embedded_values(oldvalues, oldkeys->dk_nentries); + } else { + set_values(mp, NULL); + set_keys(mp, Py_EMPTY_KEYS); n = oldkeys->dk_nentries; for (i = 0; i < n; i++) { Py_CLEAR(oldvalues->values[i]); } - if (oldvalues->embedded) { - oldvalues->size = 0; - } - else { - set_values(mp, NULL); - set_keys(mp, Py_EMPTY_KEYS); - free_values(oldvalues, IS_DICT_SHARED(mp)); - dictkeys_decref(oldkeys, false); - } + free_values(oldvalues, IS_DICT_SHARED(mp)); + dictkeys_decref(oldkeys, false); } ASSERT_CONSISTENT(mp); } From 5c3a47b94a39f87c36b1f36704d80775802ad034 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 3 Mar 2026 03:07:49 +0900 Subject: [PATCH 009/196] gh-145335: Fix crash when passing -1 as fd in os.pathconf (#145390) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Lib/test/test_os/test_os.py | 10 ++++++++++ .../2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst | 2 ++ Modules/posixmodule.c | 9 +++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst diff --git a/Lib/test/test_os/test_os.py b/Lib/test/test_os/test_os.py index 82c55c8ba33065..1f241609da80cd 100644 --- a/Lib/test/test_os/test_os.py +++ b/Lib/test/test_os/test_os.py @@ -2778,6 +2778,16 @@ def test_fpathconf_bad_fd(self): self.check(os.pathconf, "PC_NAME_MAX") self.check(os.fpathconf, "PC_NAME_MAX") + @unittest.skipUnless(hasattr(os, 'pathconf'), 'test needs os.pathconf()') + @unittest.skipIf( + support.linked_to_musl(), + 'musl fpathconf ignores the file descriptor and returns a constant', + ) + def test_pathconf_negative_fd_uses_fd_semantics(self): + with self.assertRaises(OSError) as ctx: + os.pathconf(-1, 1) + self.assertEqual(ctx.exception.errno, errno.EBADF) + @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()') def test_ftruncate(self): self.check(os.truncate, 0) 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 new file mode 100644 index 00000000000000..42ed85c7da31ac --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst @@ -0,0 +1,2 @@ +Fix a crash in :func:`os.pathconf` when called with ``-1`` as the path +argument. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 8d38e034aa6b5e..b82f08e7dc4291 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1280,6 +1280,8 @@ get_posix_state(PyObject *module) * Contains a file descriptor if path.accept_fd was true * and the caller provided a signed integer instead of any * sort of string. + * path.is_fd + * True if path was provided as a file descriptor. * * WARNING: if your "path" parameter is optional, and is * unspecified, path_converter will never get called. @@ -1332,6 +1334,7 @@ typedef struct { const wchar_t *wide; const char *narrow; int fd; + bool is_fd; int value_error; Py_ssize_t length; PyObject *object; @@ -1341,7 +1344,7 @@ typedef struct { #define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \ make_wide, suppress_value_error, allow_fd) \ {function_name, argument_name, nullable, nonstrict, make_wide, \ - suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL} + suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL} #ifdef MS_WINDOWS #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ nonstrict, suppress_value_error, allow_fd) \ @@ -1475,6 +1478,7 @@ path_converter(PyObject *o, void *p) } path->wide = NULL; path->narrow = NULL; + path->is_fd = true; goto success_exit; } else { @@ -14328,8 +14332,9 @@ os_pathconf_impl(PyObject *module, path_t *path, int name) errno = 0; #ifdef HAVE_FPATHCONF - if (path->fd != -1) + if (path->is_fd) { limit = fpathconf(path->fd, name); + } else #endif limit = pathconf(path->narrow, name); From 3ab39d2308c591b8dcee60e5e733ab0b5e5d8ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Mon, 2 Mar 2026 18:51:45 +0000 Subject: [PATCH 010/196] GH-145273: warn when we can't find the standard library (#145274) --- Lib/test/support/__init__.py | 5 ++-- Lib/test/test_embed.py | 30 ++++++++++++++++--- ...-02-26-20-51-54.gh-issue-145273.B5QcUp.rst | 2 ++ Modules/getpath.py | 23 ++++++++++++-- 4 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-20-51-54.gh-issue-145273.B5QcUp.rst diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 307bac65ae50a8..d4d3c7f1aefa66 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1716,9 +1716,10 @@ def _platform_specific(self): )) self._env = {k.upper(): os.getenv(k) for k in os.environ} - self._env["PYTHONHOME"] = os.path.dirname(self.real) + home = os.path.dirname(self.real) if sysconfig.is_python_build(): - self._env["PYTHONPATH"] = STDLIB_DIR + home = os.path.join(home, sysconfig.get_config_var('VPATH')) + self._env["PYTHONHOME"] = home else: def _platform_specific(self): pass diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 35246d7c484439..b3f0cb5d35de5d 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1491,8 +1491,12 @@ def test_init_setpythonhome(self): } self.default_program_name(config) env = {'TESTHOME': home, 'PYTHONPATH': paths_str} + # When running from source, TESTHOME will be the build directory, which + # isn't a valid home unless _is_python_build is set. getpath will then + # fail to find the standard library and show a warning, so we need to + # ignore stderr. self.check_all_configs("test_init_setpythonhome", config, - api=API_COMPAT, env=env) + api=API_COMPAT, env=env, ignore_stderr=True) def test_init_is_python_build_with_home(self): # Test _Py_path_config._is_python_build configuration (gh-91985) @@ -1528,15 +1532,26 @@ def test_init_is_python_build_with_home(self): 'exec_prefix': exec_prefix, 'base_exec_prefix': exec_prefix, 'pythonpath_env': paths_str, - 'stdlib_dir': stdlib, + 'stdlib_dir': stdlib, # Only correct on _is_python_build==0! } # The code above is taken from test_init_setpythonhome() env = {'TESTHOME': home, 'PYTHONPATH': paths_str} env['NEGATIVE_ISPYTHONBUILD'] = '1' config['_is_python_build'] = 0 + # This configuration doesn't set a valid stdlibdir/plststdlibdir because + # with _is_python_build=0 getpath doesn't check for the build directory + # landmarks in PYTHONHOME/Py_SetPythonHome. + # getpath correctly shows a warning, which messes up check_all_configs, + # so we need to ignore stderr. self.check_all_configs("test_init_is_python_build", config, - api=API_COMPAT, env=env) + api=API_COMPAT, env=env, ignore_stderr=True) + + # config['stdlib_dir'] = os.path.join(home, 'Lib') + # FIXME: This test does not check if stdlib_dir is calculated correctly. + # test_init_is_python_build runs the initialization twice, + # setting stdlib_dir in _Py_path_config on the first run, which + # then overrides the stdlib_dir calculation (as of GH-108730). env['NEGATIVE_ISPYTHONBUILD'] = '0' config['_is_python_build'] = 1 @@ -1551,8 +1566,14 @@ def test_init_is_python_build_with_home(self): expected_paths[0] = self.module_search_paths(prefix=prefix)[0] config.update(prefix=prefix, base_prefix=prefix, exec_prefix=exec_prefix, base_exec_prefix=exec_prefix) + # This also shows the bad stdlib warning, getpath is run twice. The + # first time with _is_python_build=0, which results in the warning just + # as explained above. However, the second time a valid standard library + # should be found, but the stdlib_dir is cached in _Py_path_config from + # the first run, which ovewrites it, so it also shows the warning. + # Also ignore stderr. self.check_all_configs("test_init_is_python_build", config, - api=API_COMPAT, env=env) + api=API_COMPAT, env=env, ignore_stderr=True) def copy_paths_by_env(self, config): all_configs = self._get_expected_config() @@ -1612,6 +1633,7 @@ def test_init_pybuilddir_win32(self): prefix = os.path.normpath(os.path.join(tmpdir, vpath)) # The stdlib dir is dirname(executable) + VPATH + 'Lib' stdlibdir = os.path.normpath(os.path.join(tmpdir, vpath, 'Lib')) + os.mkdir(stdlibdir) filename = os.path.join(tmpdir, 'pybuilddir.txt') with open(filename, "w", encoding="utf8") as fp: 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 new file mode 100644 index 00000000000000..8d9e4a872d0d7a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-20-51-54.gh-issue-145273.B5QcUp.rst @@ -0,0 +1,2 @@ +A warning is now shown during :ref:`sys-path-init` if it can't find a valid +standard library. diff --git a/Modules/getpath.py b/Modules/getpath.py index ceb605a75c85f4..e06297b7b63a7b 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -236,6 +236,7 @@ def search_up(prefix, *landmarks, test=isfile): real_executable_dir = None platstdlib_dir = None +stdlib_zip = None # ****************************************************************************** # CALCULATE program_name @@ -697,12 +698,13 @@ def search_up(prefix, *landmarks, test=isfile): library_dir = dirname(library) else: library_dir = executable_dir - pythonpath.append(joinpath(library_dir, ZIP_LANDMARK)) + stdlib_zip = joinpath(library_dir, ZIP_LANDMARK) elif build_prefix: # QUIRK: POSIX uses the default prefix when in the build directory - pythonpath.append(joinpath(PREFIX, ZIP_LANDMARK)) + stdlib_zip = joinpath(PREFIX, ZIP_LANDMARK) else: - pythonpath.append(joinpath(base_prefix, ZIP_LANDMARK)) + stdlib_zip = joinpath(base_prefix, ZIP_LANDMARK) + pythonpath.append(stdlib_zip) if os_name == 'nt' and use_environment and winreg: # QUIRK: Windows also lists paths in the registry. Paths are stored @@ -767,6 +769,21 @@ def search_up(prefix, *landmarks, test=isfile): config['module_search_paths_set'] = 1 +# ****************************************************************************** +# SANITY CHECKS +# ****************************************************************************** + +# Warn if the standard library is missing +if not stdlib_zip or not isfile(stdlib_zip): + home_hint = f"The Python 'home' directory was set to {home!r}, is this correct?" + if 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 and not build_prefix) or not isdir(platstdlib_dir): + hint = home_hint if home else f'sys.exec_prefix is set to {exec_prefix}, is this correct?' + warn('WARN: Could not find the platform standard library directory! ' + hint) + + # ****************************************************************************** # POSIX prefix/exec_prefix QUIRKS # ****************************************************************************** From eb611a8515d8d7af714b57a5f955a98011000d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Mon, 2 Mar 2026 19:19:05 +0000 Subject: [PATCH 011/196] GH-145275: add -X pathconfig_warnings and PYTHON_PATHCONFIG_WARNINGS (#145277) --- Doc/using/cmdline.rst | 15 ++++++++ ...-02-26-21-07-38.gh-issue-145275.qE-3O1.rst | 3 ++ Python/initconfig.c | 34 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-07-38.gh-issue-145275.qE-3O1.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index f4085ff842aea9..84b8575284b793 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -687,6 +687,13 @@ Miscellaneous options .. versionadded:: 3.14 + * :samp:`-X pathconfig_warnings={0,1}` if true (``1``) then + :ref:`sys-path-init` is allowed to log warnings into stderr. + If false (``0``) suppress these warnings. Set to true by default. + See also :envvar:`PYTHON_PATHCONFIG_WARNINGS`. + + .. versionadded:: next + * :samp:`-X tlbc={0,1}` enables (1, the default) or disables (0) thread-local bytecode in builds configured with :option:`--disable-gil`. When disabled, this also disables the specializing interpreter. See also @@ -1354,6 +1361,14 @@ conflict. .. versionadded:: 3.14 +.. envvar:: PYTHON_PATHCONFIG_WARNINGS + + If true (``1``) then :ref:`sys-path-init` is allowed to log warnings into + stderr. If false (``0``) suppress these warnings. Set to true by default. + See also :option:`-X pathconfig_warnings<-X>`. + + .. versionadded:: next + .. envvar:: PYTHON_JIT On builds where experimental just-in-time compilation is available, this 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 new file mode 100644 index 00000000000000..1723a7c8c10717 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-26-21-07-38.gh-issue-145275.qE-3O1.rst @@ -0,0 +1,3 @@ +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/Python/initconfig.c b/Python/initconfig.c index 5ffee9eaf9f550..57629ff8c57380 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -357,6 +357,9 @@ The following implementation-specific options are available:\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 \ of N frames (default: 1); also PYTHONTRACEMALLOC=N\n\ -X utf8[=0|1]: enable (1) or disable (0) UTF-8 mode; also PYTHONUTF8\n\ @@ -2350,6 +2353,32 @@ config_init_lazy_imports(PyConfig *config) return _PyStatus_OK(); } +static PyStatus +config_init_pathconfig_warnings(PyConfig *config) +{ + const char *env = config_get_env(config, "PYTHON_PATHCONFIG_WARNINGS"); + if (env) { + int enabled; + if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) { + return _PyStatus_ERR( + "PYTHON_PATHCONFIG_WARNINGS=N: N is missing or invalid"); + } + config->pathconfig_warnings = enabled; + } + + const wchar_t *xoption = config_get_xoption(config, L"pathconfig_warnings"); + if (xoption) { + int enabled; + const wchar_t *sep = wcschr(xoption, L'='); + if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) { + return _PyStatus_ERR( + "-X pathconfig_warnings=n: n is missing or invalid"); + } + config->pathconfig_warnings = enabled; + } + return _PyStatus_OK(); +} + static PyStatus config_read_complex_options(PyConfig *config) { @@ -2446,6 +2475,11 @@ config_read_complex_options(PyConfig *config) return status; } + status = config_init_pathconfig_warnings(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); } From 592e8f0865cfd5af65fbcdbd185c3dd576c838e7 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 2 Mar 2026 14:32:06 -0500 Subject: [PATCH 012/196] gh-130327: Always traverse managed dictionaries, even when inline values are available (#130469) --- Lib/test/test_dict.py | 20 +++++++++++++++++++ ...-02-19-21-06-30.gh-issue-130327.z3TaR8.rst | 2 ++ Objects/dictobject.c | 17 +++++++++------- 3 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-02-19-21-06-30.gh-issue-130327.z3TaR8.rst diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index f28155fe50148d..162b0b38f8555d 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1569,6 +1569,26 @@ def make_pairs(): self.assertEqual(d.get(key3_3), 44) self.assertGreaterEqual(eq_count, 1) + def test_overwrite_managed_dict(self): + # GH-130327: Overwriting an object's managed dictionary with another object's + # skipped traversal in favor of inline values, causing the GC to believe that + # the __dict__ wasn't reachable. + import gc + + class Shenanigans: + pass + + to_be_deleted = Shenanigans() + to_be_deleted.attr = "whatever" + holds_reference = Shenanigans() + holds_reference.__dict__ = to_be_deleted.__dict__ + holds_reference.ref = {"circular": to_be_deleted, "data": 42} + + del to_be_deleted + gc.collect() + self.assertEqual(holds_reference.ref['data'], 42) + self.assertEqual(holds_reference.attr, "whatever") + def test_unhashable_key(self): d = {'a': 1} key = [1, 2, 3] 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 new file mode 100644 index 00000000000000..9b9a282b5ab414 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-19-21-06-30.gh-issue-130327.z3TaR8.rst @@ -0,0 +1,2 @@ +Fix erroneous clearing of an object's :attr:`~object.__dict__` if +overwritten at runtime. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index bcd3c862fd59b2..5894fdb614ebdc 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4825,10 +4825,8 @@ dict_traverse(PyObject *op, visitproc visit, void *arg) if (DK_IS_UNICODE(keys)) { if (_PyDict_HasSplitTable(mp)) { - if (!mp->ma_values->embedded) { - for (i = 0; i < n; i++) { - Py_VISIT(mp->ma_values->values[i]); - } + for (i = 0; i < n; i++) { + Py_VISIT(mp->ma_values->values[i]); } } else { @@ -7413,16 +7411,21 @@ PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { return 0; } - if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) { + PyDictObject *dict = _PyObject_ManagedDictPointer(obj)->dict; + if (dict != NULL) { + // GH-130327: If there's a managed dictionary available, we should + // *always* traverse it. The dict is responsible for traversing the + // inline values if it points to them. + Py_VISIT(dict); + } + else if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) { PyDictValues *values = _PyObject_InlineValues(obj); if (values->valid) { for (Py_ssize_t i = 0; i < values->capacity; i++) { Py_VISIT(values->values[i]); } - return 0; } } - Py_VISIT(_PyObject_ManagedDictPointer(obj)->dict); return 0; } From f8d2f9fe67f8ab279cf7c5f6fa6a4feb588ce8f0 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:45:03 +0000 Subject: [PATCH 013/196] gh-145118: Add `frozendict` support to `type()` (#145124) --- Lib/test/test_builtin.py | 6 ++++ ...-02-22-19-05-03.gh-issue-145118.bU6Sic.rst | 1 + Objects/typeobject.c | 28 +++++++++++++++---- 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 7b69374b1868d1..eabfdcd447f2bb 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -2993,6 +2993,12 @@ def test_type_doc(self): A.__doc__ = doc self.assertEqual(A.__doc__, doc) + def test_type_frozendict(self): + A = type('A', (), frozendict({'x': 4, 'y': 2})) + self.assertEqual(A.x, 4) + self.assertEqual(A.y, 2) + self.assertEqual(A.__name__, 'A') + def test_bad_args(self): with self.assertRaises(TypeError): type() 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 new file mode 100644 index 00000000000000..24507d4a411f85 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-22-19-05-03.gh-issue-145118.bU6Sic.rst @@ -0,0 +1 @@ +:func:`type` now accepts :class:`frozendict` as an argument. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ad26339c9c34df..d77d981085f4da 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4872,9 +4872,21 @@ type_new_get_slots(type_new_ctx *ctx, PyObject *dict) static PyTypeObject* type_new_init(type_new_ctx *ctx) { - PyObject *dict = PyDict_Copy(ctx->orig_dict); - if (dict == NULL) { - goto error; + PyObject *dict; + if (PyFrozenDict_Check(ctx->orig_dict)) { + dict = PyDict_New(); + if (dict == NULL) { + goto error; + } + if (PyDict_Merge(dict, ctx->orig_dict, 1) < 0) { + goto error; + } + } + else { + dict = PyDict_Copy(ctx->orig_dict); + if (dict == NULL) { + goto error; + } } if (type_new_get_slots(ctx, dict) < 0) { @@ -5037,13 +5049,19 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) /* Parse arguments: (name, bases, dict) */ PyObject *name, *bases, *orig_dict; - if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", + if (!PyArg_ParseTuple(args, "UO!O:type.__new__", &name, &PyTuple_Type, &bases, - &PyDict_Type, &orig_dict)) + &orig_dict)) { return NULL; } + if (!PyAnyDict_Check(orig_dict)) { + PyErr_Format(PyExc_TypeError, + "type.__new__() argument 3 must be dict or frozendict, not %T", + orig_dict); + return NULL; + } type_new_ctx ctx = { .metatype = metatype, From 539a985faca498e345e471476cb377c1c57ea07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Mon, 2 Mar 2026 20:23:22 +0000 Subject: [PATCH 014/196] GH-145273: drop build_prefix check from missing stdlib warning (#145437) --- Makefile.pre.in | 2 +- Modules/getpath.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index da8d5483fd32e8..120a6add38507f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1004,7 +1004,7 @@ platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt # or removed in case of failure. pybuilddir.txt: $(PYTHON_FOR_BUILD_DEPS) @echo "none" > ./pybuilddir.txt - $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars ;\ + $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -X pathconfig_warnings=0 -m sysconfig --generate-posix-vars ;\ if test $$? -ne 0 ; then \ echo "generate-posix-vars failed" ; \ rm -f ./pybuilddir.txt ; \ diff --git a/Modules/getpath.py b/Modules/getpath.py index e06297b7b63a7b..20e050787700bf 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -779,7 +779,7 @@ def search_up(prefix, *landmarks, test=isfile): if 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 and not build_prefix) or not isdir(platstdlib_dir): + elif not platstdlib_dir or not isdir(platstdlib_dir): hint = home_hint if home else f'sys.exec_prefix is set to {exec_prefix}, is this correct?' warn('WARN: Could not find the platform standard library directory! ' + hint) From f739e2ca62497d15a90ea56f2a92ce0fe85ea85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Mon, 2 Mar 2026 20:48:07 +0000 Subject: [PATCH 015/196] Add `sysconfig[VPATH]` to `test.pythoninfo` (#145434) --- Lib/test/pythoninfo.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index fdd8989f9cb3f8..6df59946574a17 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -539,6 +539,7 @@ def collect_sysconfig(info_add): 'SHELL', 'SOABI', 'TEST_MODULES', + 'VAPTH', 'abs_builddir', 'abs_srcdir', 'prefix', From 9124bc194a03cfde7dfa7ab78e00e0191dc443b4 Mon Sep 17 00:00:00 2001 From: "C.A.M. Gerlach" Date: Mon, 2 Mar 2026 13:10:26 -0800 Subject: [PATCH 016/196] Hide "object" prefix on dunders in contextlib docs & selectivly link some more (#145436) --- Doc/library/contextlib.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index eec9ed1ba2581e..5c6403879ab505 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -21,9 +21,9 @@ Functions and classes provided: .. class:: AbstractContextManager An :term:`abstract base class` for classes that implement - :meth:`object.__enter__` and :meth:`object.__exit__`. A default - implementation for :meth:`object.__enter__` is provided which returns - ``self`` while :meth:`object.__exit__` is an abstract method which by default + :meth:`~object.__enter__` and :meth:`~object.__exit__`. A default + implementation for :meth:`~object.__enter__` is provided which returns + ``self`` while :meth:`~object.__exit__` is an abstract method which by default returns ``None``. See also the definition of :ref:`typecontextmanager`. .. versionadded:: 3.6 @@ -32,9 +32,9 @@ Functions and classes provided: .. class:: AbstractAsyncContextManager An :term:`abstract base class` for classes that implement - :meth:`object.__aenter__` and :meth:`object.__aexit__`. A default - implementation for :meth:`object.__aenter__` is provided which returns - ``self`` while :meth:`object.__aexit__` is an abstract method which by default + :meth:`~object.__aenter__` and :meth:`~object.__aexit__`. A default + implementation for :meth:`~object.__aenter__` is provided which returns + ``self`` while :meth:`~object.__aexit__` is an abstract method which by default returns ``None``. See also the definition of :ref:`async-context-managers`. @@ -228,7 +228,7 @@ Functions and classes provided: .. function:: nullcontext(enter_result=None) - Return a context manager that returns *enter_result* from ``__enter__``, but + Return a context manager that returns *enter_result* from :meth:`~object.__enter__`, but otherwise does nothing. It is intended to be used as a stand-in for an optional context manager, for example:: @@ -335,7 +335,7 @@ Functions and classes provided: For example, the output of :func:`help` normally is sent to *sys.stdout*. You can capture that output in a string by redirecting the output to an :class:`io.StringIO` object. The replacement stream is returned from the - ``__enter__`` method and so is available as the target of the + :meth:`~object.__enter__` method and so is available as the target of the :keyword:`with` statement:: with redirect_stdout(io.StringIO()) as f: @@ -396,7 +396,8 @@ Functions and classes provided: A base class that enables a context manager to also be used as a decorator. Context managers inheriting from ``ContextDecorator`` have to implement - ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional + :meth:`~object.__enter__` and :meth:`~object.__exit__` as normal. + ``__exit__`` retains its optional exception handling even when used as a decorator. ``ContextDecorator`` is used by :func:`contextmanager`, so you get this @@ -710,9 +711,9 @@ context management protocol. Catching exceptions from ``__enter__`` methods ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It is occasionally desirable to catch exceptions from an ``__enter__`` +It is occasionally desirable to catch exceptions from an :meth:`~object.__enter__` method implementation, *without* inadvertently catching exceptions from -the :keyword:`with` statement body or the context manager's ``__exit__`` +the :keyword:`with` statement body or the context manager's :meth:`~object.__exit__` method. By using :class:`ExitStack` the steps in the context management protocol can be separated slightly in order to allow this:: From 46c5c57226862bc078bcdf0c9f5b40951b8615a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Mon, 2 Mar 2026 21:11:27 +0000 Subject: [PATCH 017/196] GH-145273: skip stdlib warning on module_search_paths_set (#145442) --- Modules/getpath.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/getpath.py b/Modules/getpath.py index 20e050787700bf..2f4d635a29585c 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -773,8 +773,10 @@ def search_up(prefix, *landmarks, test=isfile): # SANITY CHECKS # ****************************************************************************** -# Warn if the standard library is missing -if not stdlib_zip or not isfile(stdlib_zip): +# 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)): home_hint = f"The Python 'home' directory was set to {home!r}, is this correct?" if not stdlib_dir or not isdir(stdlib_dir): hint = home_hint if home else f'sys.prefix is set to {prefix}, is this correct?' From ea90b032a016122e7871e91c5210f3b4e68768b4 Mon Sep 17 00:00:00 2001 From: Daniel Hollas Date: Mon, 2 Mar 2026 21:39:07 +0000 Subject: [PATCH 018/196] gh-117865: Speedup import of `inspect` module (#144756) Co-authored-by: Alex Waygood --- Lib/inspect.py | 8 ++++---- Lib/test/test_inspect/test_inspect.py | 9 +++++++++ .../2026-02-12-17-56-17.gh-issue-117865.jE1ema.rst | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-12-17-56-17.gh-issue-117865.jE1ema.rst diff --git a/Lib/inspect.py b/Lib/inspect.py index 5d8ebb3dd54000..dfc5503dee536e 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -153,9 +153,9 @@ import itertools import linecache import os -import re +lazy import re import sys -import tokenize +lazy import tokenize import token import types import functools @@ -163,9 +163,9 @@ from keyword import iskeyword from operator import attrgetter from collections import namedtuple, OrderedDict -from weakref import ref as make_weakref +from _weakref import ref as make_weakref -# Create constants for the compiler flags in Include/code.h +# Create constants for the compiler flags in Include/cpython/code.h # We try to get them from dis to avoid duplication mod_dict = globals() for k, v in dis.COMPILER_FLAG_NAMES.items(): diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 4ad32c649ea83c..68ea62f565d824 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -173,6 +173,15 @@ def __get__(self, instance, owner): return self.func.__get__(instance, owner) +class TestImportTime(unittest.TestCase): + + @cpython_only + def test_lazy_import(self): + import_helper.ensure_lazy_imports( + "inspect", {"re", "tokenize"} + ) + + class TestPredicates(IsTestBase): def test_excluding_predicates(self): 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 new file mode 100644 index 00000000000000..f45f6682869eb1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-12-17-56-17.gh-issue-117865.jE1ema.rst @@ -0,0 +1 @@ +Reduce the import time of :mod:`inspect` module by ~20%. From 6908372fb8182be5849aa3c4b141c821b303ab61 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Mar 2026 09:58:38 +0900 Subject: [PATCH 019/196] gh-145214: Narrow _GUARD_TOS_ANY_{SET,DICT} by using probable type (gh-145215) --- Include/internal/pycore_optimizer.h | 1 + Include/internal/pycore_uop_ids.h | 2066 ++++++++++++------------ Include/internal/pycore_uop_metadata.h | 84 + Python/bytecodes.c | 20 + Python/executor_cases.c.h | 340 ++++ Python/optimizer_analysis.c | 1 + Python/optimizer_bytecodes.c | 120 +- Python/optimizer_cases.c.h | 129 +- Python/optimizer_symbols.c | 28 + 9 files changed, 1728 insertions(+), 1061 deletions(-) diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index d9f7f59de1798e..c63f0167a0f64a 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -310,6 +310,7 @@ extern void _Py_uop_sym_set_recorded_type(JitOptContext *ctx, JitOptRef sym, PyT extern void _Py_uop_sym_set_recorded_gen_func(JitOptContext *ctx, JitOptRef ref, PyFunctionObject *value); extern PyCodeObject *_Py_uop_sym_get_probable_func_code(JitOptRef sym); extern PyObject *_Py_uop_sym_get_probable_value(JitOptRef sym); +extern PyTypeObject *_Py_uop_sym_get_probable_type(JitOptRef sym); extern JitOptRef *_Py_uop_sym_set_stack_depth(JitOptContext *ctx, int stack_depth, JitOptRef *current_sp); extern void _Py_uop_abstractcontext_init(JitOptContext *ctx, _PyBloomFilter *dependencies); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 760fe86783fb8a..38f290df2c770f 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -177,29 +177,33 @@ extern "C" { #define _GUARD_THIRD_NULL 432 #define _GUARD_TOS_ANY_DICT 433 #define _GUARD_TOS_ANY_SET 434 -#define _GUARD_TOS_FLOAT 435 -#define _GUARD_TOS_INT 436 -#define _GUARD_TOS_LIST 437 -#define _GUARD_TOS_OVERFLOWED 438 -#define _GUARD_TOS_SLICE 439 -#define _GUARD_TOS_TUPLE 440 -#define _GUARD_TOS_UNICODE 441 -#define _GUARD_TYPE_VERSION 442 -#define _GUARD_TYPE_VERSION_AND_LOCK 443 -#define _HANDLE_PENDING_AND_DEOPT 444 +#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_AND_LOCK 447 +#define _HANDLE_PENDING_AND_DEOPT 448 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 445 -#define _INIT_CALL_PY_EXACT_ARGS 446 -#define _INIT_CALL_PY_EXACT_ARGS_0 447 -#define _INIT_CALL_PY_EXACT_ARGS_1 448 -#define _INIT_CALL_PY_EXACT_ARGS_2 449 -#define _INIT_CALL_PY_EXACT_ARGS_3 450 -#define _INIT_CALL_PY_EXACT_ARGS_4 451 -#define _INSERT_1_LOAD_CONST_INLINE 452 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW 453 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW 454 -#define _INSERT_NULL 455 +#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 _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -209,1054 +213,1070 @@ 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 456 -#define _IS_OP 457 -#define _ITER_CHECK_LIST 458 -#define _ITER_CHECK_RANGE 459 -#define _ITER_CHECK_TUPLE 460 -#define _ITER_JUMP_LIST 461 -#define _ITER_JUMP_RANGE 462 -#define _ITER_JUMP_TUPLE 463 -#define _ITER_NEXT_LIST 464 -#define _ITER_NEXT_LIST_TIER_TWO 465 -#define _ITER_NEXT_RANGE 466 -#define _ITER_NEXT_TUPLE 467 +#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 _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 468 +#define _JUMP_TO_TOP 472 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 469 -#define _LOAD_ATTR_CLASS 470 +#define _LOAD_ATTR 473 +#define _LOAD_ATTR_CLASS 474 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 471 -#define _LOAD_ATTR_METHOD_LAZY_DICT 472 -#define _LOAD_ATTR_METHOD_NO_DICT 473 -#define _LOAD_ATTR_METHOD_WITH_VALUES 474 -#define _LOAD_ATTR_MODULE 475 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 476 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 477 -#define _LOAD_ATTR_PROPERTY_FRAME 478 -#define _LOAD_ATTR_SLOT 479 -#define _LOAD_ATTR_WITH_HINT 480 +#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_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 481 +#define _LOAD_BYTECODE 485 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 482 -#define _LOAD_CONST_INLINE_BORROW 483 -#define _LOAD_CONST_UNDER_INLINE 484 -#define _LOAD_CONST_UNDER_INLINE_BORROW 485 +#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_DEREF LOAD_DEREF -#define _LOAD_FAST 486 -#define _LOAD_FAST_0 487 -#define _LOAD_FAST_1 488 -#define _LOAD_FAST_2 489 -#define _LOAD_FAST_3 490 -#define _LOAD_FAST_4 491 -#define _LOAD_FAST_5 492 -#define _LOAD_FAST_6 493 -#define _LOAD_FAST_7 494 +#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_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 495 -#define _LOAD_FAST_BORROW_0 496 -#define _LOAD_FAST_BORROW_1 497 -#define _LOAD_FAST_BORROW_2 498 -#define _LOAD_FAST_BORROW_3 499 -#define _LOAD_FAST_BORROW_4 500 -#define _LOAD_FAST_BORROW_5 501 -#define _LOAD_FAST_BORROW_6 502 -#define _LOAD_FAST_BORROW_7 503 +#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_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 504 -#define _LOAD_GLOBAL_BUILTINS 505 -#define _LOAD_GLOBAL_MODULE 506 +#define _LOAD_GLOBAL 508 +#define _LOAD_GLOBAL_BUILTINS 509 +#define _LOAD_GLOBAL_MODULE 510 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 507 -#define _LOAD_SMALL_INT_0 508 -#define _LOAD_SMALL_INT_1 509 -#define _LOAD_SMALL_INT_2 510 -#define _LOAD_SMALL_INT_3 511 -#define _LOAD_SPECIAL 512 +#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_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 513 +#define _MAKE_CALLARGS_A_TUPLE 517 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 514 +#define _MAKE_WARM 518 #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 515 -#define _MAYBE_EXPAND_METHOD_KW 516 -#define _MONITOR_CALL 517 -#define _MONITOR_CALL_KW 518 -#define _MONITOR_JUMP_BACKWARD 519 -#define _MONITOR_RESUME 520 +#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 _NOP NOP -#define _POP_CALL 521 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 522 -#define _POP_CALL_ONE 523 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 524 -#define _POP_CALL_TWO 525 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 526 +#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_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 527 -#define _POP_JUMP_IF_TRUE 528 +#define _POP_JUMP_IF_FALSE 531 +#define _POP_JUMP_IF_TRUE 532 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 529 -#define _POP_TOP_INT 530 -#define _POP_TOP_LOAD_CONST_INLINE 531 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 532 -#define _POP_TOP_NOP 533 -#define _POP_TOP_UNICODE 534 -#define _POP_TWO 535 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 536 +#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 _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 537 +#define _PUSH_FRAME 541 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 538 -#define _PY_FRAME_EX 539 -#define _PY_FRAME_GENERAL 540 -#define _PY_FRAME_KW 541 -#define _QUICKEN_RESUME 542 -#define _RECORD_4OS 543 -#define _RECORD_BOUND_METHOD 544 -#define _RECORD_CALLABLE 545 -#define _RECORD_CODE 546 -#define _RECORD_NOS 547 -#define _RECORD_NOS_GEN_FUNC 548 -#define _RECORD_TOS 549 -#define _RECORD_TOS_TYPE 550 -#define _REPLACE_WITH_TRUE 551 +#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 _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 552 -#define _SEND 553 -#define _SEND_GEN_FRAME 554 +#define _SAVE_RETURN_OFFSET 556 +#define _SEND 557 +#define _SEND_GEN_FRAME 558 #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 555 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW 556 -#define _SPILL_OR_RELOAD 557 -#define _START_EXECUTOR 558 -#define _STORE_ATTR 559 -#define _STORE_ATTR_INSTANCE_VALUE 560 -#define _STORE_ATTR_SLOT 561 -#define _STORE_ATTR_WITH_HINT 562 +#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 _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 563 -#define _STORE_SUBSCR 564 -#define _STORE_SUBSCR_DICT 565 -#define _STORE_SUBSCR_LIST_INT 566 -#define _SWAP 567 -#define _SWAP_2 568 -#define _SWAP_3 569 -#define _SWAP_FAST 570 -#define _SWAP_FAST_0 571 -#define _SWAP_FAST_1 572 -#define _SWAP_FAST_2 573 -#define _SWAP_FAST_3 574 -#define _SWAP_FAST_4 575 -#define _SWAP_FAST_5 576 -#define _SWAP_FAST_6 577 -#define _SWAP_FAST_7 578 -#define _TIER2_RESUME_CHECK 579 -#define _TO_BOOL 580 +#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 _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 581 -#define _TO_BOOL_LIST 582 +#define _TO_BOOL_INT 585 +#define _TO_BOOL_LIST 586 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 583 +#define _TO_BOOL_STR 587 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 584 -#define _UNARY_NEGATIVE 585 +#define _UNARY_INVERT 588 +#define _UNARY_NEGATIVE 589 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 586 -#define _UNPACK_SEQUENCE_LIST 587 -#define _UNPACK_SEQUENCE_TUPLE 588 -#define _UNPACK_SEQUENCE_TWO_TUPLE 589 +#define _UNPACK_SEQUENCE 590 +#define _UNPACK_SEQUENCE_LIST 591 +#define _UNPACK_SEQUENCE_TUPLE 592 +#define _UNPACK_SEQUENCE_TWO_TUPLE 593 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 589 -#define _BINARY_OP_r23 590 -#define _BINARY_OP_ADD_FLOAT_r03 591 -#define _BINARY_OP_ADD_FLOAT_r13 592 -#define _BINARY_OP_ADD_FLOAT_r23 593 -#define _BINARY_OP_ADD_INT_r03 594 -#define _BINARY_OP_ADD_INT_r13 595 -#define _BINARY_OP_ADD_INT_r23 596 -#define _BINARY_OP_ADD_UNICODE_r03 597 -#define _BINARY_OP_ADD_UNICODE_r13 598 -#define _BINARY_OP_ADD_UNICODE_r23 599 -#define _BINARY_OP_EXTEND_r23 600 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 601 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 602 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 603 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 604 -#define _BINARY_OP_MULTIPLY_INT_r03 605 -#define _BINARY_OP_MULTIPLY_INT_r13 606 -#define _BINARY_OP_MULTIPLY_INT_r23 607 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 608 -#define _BINARY_OP_SUBSCR_DICT_r23 609 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 610 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 611 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 612 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 613 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 614 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 615 -#define _BINARY_OP_SUBSCR_STR_INT_r23 616 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 617 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 618 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 619 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 620 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 621 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 622 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 623 -#define _BINARY_OP_SUBTRACT_INT_r03 624 -#define _BINARY_OP_SUBTRACT_INT_r13 625 -#define _BINARY_OP_SUBTRACT_INT_r23 626 -#define _BINARY_SLICE_r31 627 -#define _BUILD_INTERPOLATION_r01 628 -#define _BUILD_LIST_r01 629 -#define _BUILD_MAP_r01 630 -#define _BUILD_SET_r01 631 -#define _BUILD_SLICE_r01 632 -#define _BUILD_STRING_r01 633 -#define _BUILD_TEMPLATE_r21 634 -#define _BUILD_TUPLE_r01 635 -#define _CALL_BUILTIN_CLASS_r01 636 -#define _CALL_BUILTIN_FAST_r01 637 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r01 638 -#define _CALL_BUILTIN_O_r03 639 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 640 -#define _CALL_INTRINSIC_1_r11 641 -#define _CALL_INTRINSIC_2_r21 642 -#define _CALL_ISINSTANCE_r31 643 -#define _CALL_KW_NON_PY_r11 644 -#define _CALL_LEN_r33 645 -#define _CALL_LIST_APPEND_r03 646 -#define _CALL_LIST_APPEND_r13 647 -#define _CALL_LIST_APPEND_r23 648 -#define _CALL_LIST_APPEND_r33 649 -#define _CALL_METHOD_DESCRIPTOR_FAST_r01 650 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 651 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 652 -#define _CALL_METHOD_DESCRIPTOR_O_r03 653 -#define _CALL_NON_PY_GENERAL_r01 654 -#define _CALL_STR_1_r32 655 -#define _CALL_TUPLE_1_r32 656 -#define _CALL_TYPE_1_r02 657 -#define _CALL_TYPE_1_r12 658 -#define _CALL_TYPE_1_r22 659 -#define _CALL_TYPE_1_r32 660 -#define _CHECK_AND_ALLOCATE_OBJECT_r00 661 -#define _CHECK_ATTR_CLASS_r01 662 -#define _CHECK_ATTR_CLASS_r11 663 -#define _CHECK_ATTR_CLASS_r22 664 -#define _CHECK_ATTR_CLASS_r33 665 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 666 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 667 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 668 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 669 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 670 -#define _CHECK_EG_MATCH_r22 671 -#define _CHECK_EXC_MATCH_r22 672 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 673 -#define _CHECK_FUNCTION_VERSION_r00 674 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 675 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 676 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 677 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 678 -#define _CHECK_FUNCTION_VERSION_KW_r11 679 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 680 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 681 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 682 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 683 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 684 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 685 -#define _CHECK_IS_PY_CALLABLE_EX_r03 686 -#define _CHECK_IS_PY_CALLABLE_EX_r13 687 -#define _CHECK_IS_PY_CALLABLE_EX_r23 688 -#define _CHECK_IS_PY_CALLABLE_EX_r33 689 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 690 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 691 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 692 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 693 -#define _CHECK_METHOD_VERSION_r00 694 -#define _CHECK_METHOD_VERSION_KW_r11 695 -#define _CHECK_PEP_523_r00 696 -#define _CHECK_PEP_523_r11 697 -#define _CHECK_PEP_523_r22 698 -#define _CHECK_PEP_523_r33 699 -#define _CHECK_PERIODIC_r00 700 -#define _CHECK_PERIODIC_AT_END_r00 701 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 702 -#define _CHECK_RECURSION_REMAINING_r00 703 -#define _CHECK_RECURSION_REMAINING_r11 704 -#define _CHECK_RECURSION_REMAINING_r22 705 -#define _CHECK_RECURSION_REMAINING_r33 706 -#define _CHECK_STACK_SPACE_r00 707 -#define _CHECK_STACK_SPACE_OPERAND_r00 708 -#define _CHECK_STACK_SPACE_OPERAND_r11 709 -#define _CHECK_STACK_SPACE_OPERAND_r22 710 -#define _CHECK_STACK_SPACE_OPERAND_r33 711 -#define _CHECK_VALIDITY_r00 712 -#define _CHECK_VALIDITY_r11 713 -#define _CHECK_VALIDITY_r22 714 -#define _CHECK_VALIDITY_r33 715 -#define _COLD_DYNAMIC_EXIT_r00 716 -#define _COLD_EXIT_r00 717 -#define _COMPARE_OP_r21 718 -#define _COMPARE_OP_FLOAT_r03 719 -#define _COMPARE_OP_FLOAT_r13 720 -#define _COMPARE_OP_FLOAT_r23 721 -#define _COMPARE_OP_INT_r23 722 -#define _COMPARE_OP_STR_r23 723 -#define _CONTAINS_OP_r23 724 -#define _CONTAINS_OP_DICT_r23 725 -#define _CONTAINS_OP_SET_r23 726 -#define _CONVERT_VALUE_r11 727 -#define _COPY_r01 728 -#define _COPY_1_r02 729 -#define _COPY_1_r12 730 -#define _COPY_1_r23 731 -#define _COPY_2_r03 732 -#define _COPY_2_r13 733 -#define _COPY_2_r23 734 -#define _COPY_3_r03 735 -#define _COPY_3_r13 736 -#define _COPY_3_r23 737 -#define _COPY_3_r33 738 -#define _COPY_FREE_VARS_r00 739 -#define _COPY_FREE_VARS_r11 740 -#define _COPY_FREE_VARS_r22 741 -#define _COPY_FREE_VARS_r33 742 -#define _CREATE_INIT_FRAME_r01 743 -#define _DELETE_ATTR_r10 744 -#define _DELETE_DEREF_r00 745 -#define _DELETE_FAST_r00 746 -#define _DELETE_GLOBAL_r00 747 -#define _DELETE_NAME_r00 748 -#define _DELETE_SUBSCR_r20 749 -#define _DEOPT_r00 750 -#define _DEOPT_r10 751 -#define _DEOPT_r20 752 -#define _DEOPT_r30 753 -#define _DICT_MERGE_r10 754 -#define _DICT_UPDATE_r10 755 -#define _DO_CALL_r01 756 -#define _DO_CALL_FUNCTION_EX_r31 757 -#define _DO_CALL_KW_r11 758 -#define _DYNAMIC_EXIT_r00 759 -#define _DYNAMIC_EXIT_r10 760 -#define _DYNAMIC_EXIT_r20 761 -#define _DYNAMIC_EXIT_r30 762 -#define _END_FOR_r10 763 -#define _END_SEND_r21 764 -#define _ERROR_POP_N_r00 765 -#define _EXIT_INIT_CHECK_r10 766 -#define _EXIT_TRACE_r00 767 -#define _EXIT_TRACE_r10 768 -#define _EXIT_TRACE_r20 769 -#define _EXIT_TRACE_r30 770 -#define _EXPAND_METHOD_r00 771 -#define _EXPAND_METHOD_KW_r11 772 -#define _FATAL_ERROR_r00 773 -#define _FATAL_ERROR_r11 774 -#define _FATAL_ERROR_r22 775 -#define _FATAL_ERROR_r33 776 -#define _FORMAT_SIMPLE_r11 777 -#define _FORMAT_WITH_SPEC_r21 778 -#define _FOR_ITER_r23 779 -#define _FOR_ITER_GEN_FRAME_r03 780 -#define _FOR_ITER_GEN_FRAME_r13 781 -#define _FOR_ITER_GEN_FRAME_r23 782 -#define _FOR_ITER_TIER_TWO_r23 783 -#define _GET_AITER_r11 784 -#define _GET_ANEXT_r12 785 -#define _GET_AWAITABLE_r11 786 -#define _GET_ITER_r12 787 -#define _GET_LEN_r12 788 -#define _GET_YIELD_FROM_ITER_r11 789 -#define _GUARD_BINARY_OP_EXTEND_r22 790 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 791 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 792 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 793 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 794 -#define _GUARD_BIT_IS_SET_POP_r00 795 -#define _GUARD_BIT_IS_SET_POP_r10 796 -#define _GUARD_BIT_IS_SET_POP_r21 797 -#define _GUARD_BIT_IS_SET_POP_r32 798 -#define _GUARD_BIT_IS_SET_POP_4_r00 799 -#define _GUARD_BIT_IS_SET_POP_4_r10 800 -#define _GUARD_BIT_IS_SET_POP_4_r21 801 -#define _GUARD_BIT_IS_SET_POP_4_r32 802 -#define _GUARD_BIT_IS_SET_POP_5_r00 803 -#define _GUARD_BIT_IS_SET_POP_5_r10 804 -#define _GUARD_BIT_IS_SET_POP_5_r21 805 -#define _GUARD_BIT_IS_SET_POP_5_r32 806 -#define _GUARD_BIT_IS_SET_POP_6_r00 807 -#define _GUARD_BIT_IS_SET_POP_6_r10 808 -#define _GUARD_BIT_IS_SET_POP_6_r21 809 -#define _GUARD_BIT_IS_SET_POP_6_r32 810 -#define _GUARD_BIT_IS_SET_POP_7_r00 811 -#define _GUARD_BIT_IS_SET_POP_7_r10 812 -#define _GUARD_BIT_IS_SET_POP_7_r21 813 -#define _GUARD_BIT_IS_SET_POP_7_r32 814 -#define _GUARD_BIT_IS_UNSET_POP_r00 815 -#define _GUARD_BIT_IS_UNSET_POP_r10 816 -#define _GUARD_BIT_IS_UNSET_POP_r21 817 -#define _GUARD_BIT_IS_UNSET_POP_r32 818 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 819 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 820 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 821 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 822 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 823 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 824 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 825 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 826 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 827 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 828 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 829 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 830 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 831 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 832 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 833 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 834 -#define _GUARD_CALLABLE_ISINSTANCE_r03 835 -#define _GUARD_CALLABLE_ISINSTANCE_r13 836 -#define _GUARD_CALLABLE_ISINSTANCE_r23 837 -#define _GUARD_CALLABLE_ISINSTANCE_r33 838 -#define _GUARD_CALLABLE_LEN_r03 839 -#define _GUARD_CALLABLE_LEN_r13 840 -#define _GUARD_CALLABLE_LEN_r23 841 -#define _GUARD_CALLABLE_LEN_r33 842 -#define _GUARD_CALLABLE_LIST_APPEND_r03 843 -#define _GUARD_CALLABLE_LIST_APPEND_r13 844 -#define _GUARD_CALLABLE_LIST_APPEND_r23 845 -#define _GUARD_CALLABLE_LIST_APPEND_r33 846 -#define _GUARD_CALLABLE_STR_1_r03 847 -#define _GUARD_CALLABLE_STR_1_r13 848 -#define _GUARD_CALLABLE_STR_1_r23 849 -#define _GUARD_CALLABLE_STR_1_r33 850 -#define _GUARD_CALLABLE_TUPLE_1_r03 851 -#define _GUARD_CALLABLE_TUPLE_1_r13 852 -#define _GUARD_CALLABLE_TUPLE_1_r23 853 -#define _GUARD_CALLABLE_TUPLE_1_r33 854 -#define _GUARD_CALLABLE_TYPE_1_r03 855 -#define _GUARD_CALLABLE_TYPE_1_r13 856 -#define _GUARD_CALLABLE_TYPE_1_r23 857 -#define _GUARD_CALLABLE_TYPE_1_r33 858 -#define _GUARD_CODE_VERSION_r00 859 -#define _GUARD_CODE_VERSION_r11 860 -#define _GUARD_CODE_VERSION_r22 861 -#define _GUARD_CODE_VERSION_r33 862 -#define _GUARD_DORV_NO_DICT_r01 863 -#define _GUARD_DORV_NO_DICT_r11 864 -#define _GUARD_DORV_NO_DICT_r22 865 -#define _GUARD_DORV_NO_DICT_r33 866 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 867 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 868 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 869 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 870 -#define _GUARD_GLOBALS_VERSION_r00 871 -#define _GUARD_GLOBALS_VERSION_r11 872 -#define _GUARD_GLOBALS_VERSION_r22 873 -#define _GUARD_GLOBALS_VERSION_r33 874 -#define _GUARD_IP_RETURN_GENERATOR_r00 875 -#define _GUARD_IP_RETURN_GENERATOR_r11 876 -#define _GUARD_IP_RETURN_GENERATOR_r22 877 -#define _GUARD_IP_RETURN_GENERATOR_r33 878 -#define _GUARD_IP_RETURN_VALUE_r00 879 -#define _GUARD_IP_RETURN_VALUE_r11 880 -#define _GUARD_IP_RETURN_VALUE_r22 881 -#define _GUARD_IP_RETURN_VALUE_r33 882 -#define _GUARD_IP_YIELD_VALUE_r00 883 -#define _GUARD_IP_YIELD_VALUE_r11 884 -#define _GUARD_IP_YIELD_VALUE_r22 885 -#define _GUARD_IP_YIELD_VALUE_r33 886 -#define _GUARD_IP__PUSH_FRAME_r00 887 -#define _GUARD_IP__PUSH_FRAME_r11 888 -#define _GUARD_IP__PUSH_FRAME_r22 889 -#define _GUARD_IP__PUSH_FRAME_r33 890 -#define _GUARD_IS_FALSE_POP_r00 891 -#define _GUARD_IS_FALSE_POP_r10 892 -#define _GUARD_IS_FALSE_POP_r21 893 -#define _GUARD_IS_FALSE_POP_r32 894 -#define _GUARD_IS_NONE_POP_r00 895 -#define _GUARD_IS_NONE_POP_r10 896 -#define _GUARD_IS_NONE_POP_r21 897 -#define _GUARD_IS_NONE_POP_r32 898 -#define _GUARD_IS_NOT_NONE_POP_r10 899 -#define _GUARD_IS_TRUE_POP_r00 900 -#define _GUARD_IS_TRUE_POP_r10 901 -#define _GUARD_IS_TRUE_POP_r21 902 -#define _GUARD_IS_TRUE_POP_r32 903 -#define _GUARD_KEYS_VERSION_r01 904 -#define _GUARD_KEYS_VERSION_r11 905 -#define _GUARD_KEYS_VERSION_r22 906 -#define _GUARD_KEYS_VERSION_r33 907 -#define _GUARD_NOS_ANY_DICT_r02 908 -#define _GUARD_NOS_ANY_DICT_r12 909 -#define _GUARD_NOS_ANY_DICT_r22 910 -#define _GUARD_NOS_ANY_DICT_r33 911 -#define _GUARD_NOS_COMPACT_ASCII_r02 912 -#define _GUARD_NOS_COMPACT_ASCII_r12 913 -#define _GUARD_NOS_COMPACT_ASCII_r22 914 -#define _GUARD_NOS_COMPACT_ASCII_r33 915 -#define _GUARD_NOS_DICT_r02 916 -#define _GUARD_NOS_DICT_r12 917 -#define _GUARD_NOS_DICT_r22 918 -#define _GUARD_NOS_DICT_r33 919 -#define _GUARD_NOS_FLOAT_r02 920 -#define _GUARD_NOS_FLOAT_r12 921 -#define _GUARD_NOS_FLOAT_r22 922 -#define _GUARD_NOS_FLOAT_r33 923 -#define _GUARD_NOS_INT_r02 924 -#define _GUARD_NOS_INT_r12 925 -#define _GUARD_NOS_INT_r22 926 -#define _GUARD_NOS_INT_r33 927 -#define _GUARD_NOS_LIST_r02 928 -#define _GUARD_NOS_LIST_r12 929 -#define _GUARD_NOS_LIST_r22 930 -#define _GUARD_NOS_LIST_r33 931 -#define _GUARD_NOS_NOT_NULL_r02 932 -#define _GUARD_NOS_NOT_NULL_r12 933 -#define _GUARD_NOS_NOT_NULL_r22 934 -#define _GUARD_NOS_NOT_NULL_r33 935 -#define _GUARD_NOS_NULL_r02 936 -#define _GUARD_NOS_NULL_r12 937 -#define _GUARD_NOS_NULL_r22 938 -#define _GUARD_NOS_NULL_r33 939 -#define _GUARD_NOS_OVERFLOWED_r02 940 -#define _GUARD_NOS_OVERFLOWED_r12 941 -#define _GUARD_NOS_OVERFLOWED_r22 942 -#define _GUARD_NOS_OVERFLOWED_r33 943 -#define _GUARD_NOS_TUPLE_r02 944 -#define _GUARD_NOS_TUPLE_r12 945 -#define _GUARD_NOS_TUPLE_r22 946 -#define _GUARD_NOS_TUPLE_r33 947 -#define _GUARD_NOS_UNICODE_r02 948 -#define _GUARD_NOS_UNICODE_r12 949 -#define _GUARD_NOS_UNICODE_r22 950 -#define _GUARD_NOS_UNICODE_r33 951 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 952 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 953 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 954 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 955 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 956 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 957 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 958 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 959 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 960 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 961 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 962 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 963 -#define _GUARD_THIRD_NULL_r03 964 -#define _GUARD_THIRD_NULL_r13 965 -#define _GUARD_THIRD_NULL_r23 966 -#define _GUARD_THIRD_NULL_r33 967 -#define _GUARD_TOS_ANY_DICT_r01 968 -#define _GUARD_TOS_ANY_DICT_r11 969 -#define _GUARD_TOS_ANY_DICT_r22 970 -#define _GUARD_TOS_ANY_DICT_r33 971 -#define _GUARD_TOS_ANY_SET_r01 972 -#define _GUARD_TOS_ANY_SET_r11 973 -#define _GUARD_TOS_ANY_SET_r22 974 -#define _GUARD_TOS_ANY_SET_r33 975 -#define _GUARD_TOS_FLOAT_r01 976 -#define _GUARD_TOS_FLOAT_r11 977 -#define _GUARD_TOS_FLOAT_r22 978 -#define _GUARD_TOS_FLOAT_r33 979 -#define _GUARD_TOS_INT_r01 980 -#define _GUARD_TOS_INT_r11 981 -#define _GUARD_TOS_INT_r22 982 -#define _GUARD_TOS_INT_r33 983 -#define _GUARD_TOS_LIST_r01 984 -#define _GUARD_TOS_LIST_r11 985 -#define _GUARD_TOS_LIST_r22 986 -#define _GUARD_TOS_LIST_r33 987 -#define _GUARD_TOS_OVERFLOWED_r01 988 -#define _GUARD_TOS_OVERFLOWED_r11 989 -#define _GUARD_TOS_OVERFLOWED_r22 990 -#define _GUARD_TOS_OVERFLOWED_r33 991 -#define _GUARD_TOS_SLICE_r01 992 -#define _GUARD_TOS_SLICE_r11 993 -#define _GUARD_TOS_SLICE_r22 994 -#define _GUARD_TOS_SLICE_r33 995 -#define _GUARD_TOS_TUPLE_r01 996 -#define _GUARD_TOS_TUPLE_r11 997 -#define _GUARD_TOS_TUPLE_r22 998 -#define _GUARD_TOS_TUPLE_r33 999 -#define _GUARD_TOS_UNICODE_r01 1000 -#define _GUARD_TOS_UNICODE_r11 1001 -#define _GUARD_TOS_UNICODE_r22 1002 -#define _GUARD_TOS_UNICODE_r33 1003 -#define _GUARD_TYPE_VERSION_r01 1004 -#define _GUARD_TYPE_VERSION_r11 1005 -#define _GUARD_TYPE_VERSION_r22 1006 -#define _GUARD_TYPE_VERSION_r33 1007 -#define _GUARD_TYPE_VERSION_AND_LOCK_r01 1008 -#define _GUARD_TYPE_VERSION_AND_LOCK_r11 1009 -#define _GUARD_TYPE_VERSION_AND_LOCK_r22 1010 -#define _GUARD_TYPE_VERSION_AND_LOCK_r33 1011 -#define _HANDLE_PENDING_AND_DEOPT_r00 1012 -#define _HANDLE_PENDING_AND_DEOPT_r10 1013 -#define _HANDLE_PENDING_AND_DEOPT_r20 1014 -#define _HANDLE_PENDING_AND_DEOPT_r30 1015 -#define _IMPORT_FROM_r12 1016 -#define _IMPORT_NAME_r21 1017 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1018 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1019 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1020 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1021 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1022 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1023 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1024 -#define _INSERT_1_LOAD_CONST_INLINE_r02 1025 -#define _INSERT_1_LOAD_CONST_INLINE_r12 1026 -#define _INSERT_1_LOAD_CONST_INLINE_r23 1027 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r02 1028 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r12 1029 -#define _INSERT_1_LOAD_CONST_INLINE_BORROW_r23 1030 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r03 1031 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r13 1032 -#define _INSERT_2_LOAD_CONST_INLINE_BORROW_r23 1033 -#define _INSERT_NULL_r10 1034 -#define _INSTRUMENTED_FOR_ITER_r23 1035 -#define _INSTRUMENTED_INSTRUCTION_r00 1036 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1037 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1038 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1039 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1040 -#define _INSTRUMENTED_LINE_r00 1041 -#define _INSTRUMENTED_NOT_TAKEN_r00 1042 -#define _INSTRUMENTED_NOT_TAKEN_r11 1043 -#define _INSTRUMENTED_NOT_TAKEN_r22 1044 -#define _INSTRUMENTED_NOT_TAKEN_r33 1045 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1046 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1047 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1048 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1049 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1050 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1051 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1052 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1053 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1054 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1055 -#define _IS_NONE_r11 1056 -#define _IS_OP_r03 1057 -#define _IS_OP_r13 1058 -#define _IS_OP_r23 1059 -#define _ITER_CHECK_LIST_r02 1060 -#define _ITER_CHECK_LIST_r12 1061 -#define _ITER_CHECK_LIST_r22 1062 -#define _ITER_CHECK_LIST_r33 1063 -#define _ITER_CHECK_RANGE_r02 1064 -#define _ITER_CHECK_RANGE_r12 1065 -#define _ITER_CHECK_RANGE_r22 1066 -#define _ITER_CHECK_RANGE_r33 1067 -#define _ITER_CHECK_TUPLE_r02 1068 -#define _ITER_CHECK_TUPLE_r12 1069 -#define _ITER_CHECK_TUPLE_r22 1070 -#define _ITER_CHECK_TUPLE_r33 1071 -#define _ITER_JUMP_LIST_r02 1072 -#define _ITER_JUMP_LIST_r12 1073 -#define _ITER_JUMP_LIST_r22 1074 -#define _ITER_JUMP_LIST_r33 1075 -#define _ITER_JUMP_RANGE_r02 1076 -#define _ITER_JUMP_RANGE_r12 1077 -#define _ITER_JUMP_RANGE_r22 1078 -#define _ITER_JUMP_RANGE_r33 1079 -#define _ITER_JUMP_TUPLE_r02 1080 -#define _ITER_JUMP_TUPLE_r12 1081 -#define _ITER_JUMP_TUPLE_r22 1082 -#define _ITER_JUMP_TUPLE_r33 1083 -#define _ITER_NEXT_LIST_r23 1084 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1085 -#define _ITER_NEXT_RANGE_r03 1086 -#define _ITER_NEXT_RANGE_r13 1087 -#define _ITER_NEXT_RANGE_r23 1088 -#define _ITER_NEXT_TUPLE_r03 1089 -#define _ITER_NEXT_TUPLE_r13 1090 -#define _ITER_NEXT_TUPLE_r23 1091 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1092 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1093 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1094 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1095 -#define _JUMP_TO_TOP_r00 1096 -#define _LIST_APPEND_r10 1097 -#define _LIST_EXTEND_r10 1098 -#define _LOAD_ATTR_r10 1099 -#define _LOAD_ATTR_CLASS_r11 1100 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_r11 1101 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1102 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1103 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1104 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1105 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1106 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1107 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1108 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1109 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1110 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1111 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1112 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1113 -#define _LOAD_ATTR_MODULE_r12 1114 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1115 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1116 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1117 -#define _LOAD_ATTR_SLOT_r02 1118 -#define _LOAD_ATTR_SLOT_r12 1119 -#define _LOAD_ATTR_SLOT_r23 1120 -#define _LOAD_ATTR_WITH_HINT_r12 1121 -#define _LOAD_BUILD_CLASS_r01 1122 -#define _LOAD_BYTECODE_r00 1123 -#define _LOAD_COMMON_CONSTANT_r01 1124 -#define _LOAD_COMMON_CONSTANT_r12 1125 -#define _LOAD_COMMON_CONSTANT_r23 1126 -#define _LOAD_CONST_r01 1127 -#define _LOAD_CONST_r12 1128 -#define _LOAD_CONST_r23 1129 -#define _LOAD_CONST_INLINE_r01 1130 -#define _LOAD_CONST_INLINE_r12 1131 -#define _LOAD_CONST_INLINE_r23 1132 -#define _LOAD_CONST_INLINE_BORROW_r01 1133 -#define _LOAD_CONST_INLINE_BORROW_r12 1134 -#define _LOAD_CONST_INLINE_BORROW_r23 1135 -#define _LOAD_CONST_UNDER_INLINE_r02 1136 -#define _LOAD_CONST_UNDER_INLINE_r12 1137 -#define _LOAD_CONST_UNDER_INLINE_r23 1138 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r02 1139 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r12 1140 -#define _LOAD_CONST_UNDER_INLINE_BORROW_r23 1141 -#define _LOAD_DEREF_r01 1142 -#define _LOAD_FAST_r01 1143 -#define _LOAD_FAST_r12 1144 -#define _LOAD_FAST_r23 1145 -#define _LOAD_FAST_0_r01 1146 -#define _LOAD_FAST_0_r12 1147 -#define _LOAD_FAST_0_r23 1148 -#define _LOAD_FAST_1_r01 1149 -#define _LOAD_FAST_1_r12 1150 -#define _LOAD_FAST_1_r23 1151 -#define _LOAD_FAST_2_r01 1152 -#define _LOAD_FAST_2_r12 1153 -#define _LOAD_FAST_2_r23 1154 -#define _LOAD_FAST_3_r01 1155 -#define _LOAD_FAST_3_r12 1156 -#define _LOAD_FAST_3_r23 1157 -#define _LOAD_FAST_4_r01 1158 -#define _LOAD_FAST_4_r12 1159 -#define _LOAD_FAST_4_r23 1160 -#define _LOAD_FAST_5_r01 1161 -#define _LOAD_FAST_5_r12 1162 -#define _LOAD_FAST_5_r23 1163 -#define _LOAD_FAST_6_r01 1164 -#define _LOAD_FAST_6_r12 1165 -#define _LOAD_FAST_6_r23 1166 -#define _LOAD_FAST_7_r01 1167 -#define _LOAD_FAST_7_r12 1168 -#define _LOAD_FAST_7_r23 1169 -#define _LOAD_FAST_AND_CLEAR_r01 1170 -#define _LOAD_FAST_AND_CLEAR_r12 1171 -#define _LOAD_FAST_AND_CLEAR_r23 1172 -#define _LOAD_FAST_BORROW_r01 1173 -#define _LOAD_FAST_BORROW_r12 1174 -#define _LOAD_FAST_BORROW_r23 1175 -#define _LOAD_FAST_BORROW_0_r01 1176 -#define _LOAD_FAST_BORROW_0_r12 1177 -#define _LOAD_FAST_BORROW_0_r23 1178 -#define _LOAD_FAST_BORROW_1_r01 1179 -#define _LOAD_FAST_BORROW_1_r12 1180 -#define _LOAD_FAST_BORROW_1_r23 1181 -#define _LOAD_FAST_BORROW_2_r01 1182 -#define _LOAD_FAST_BORROW_2_r12 1183 -#define _LOAD_FAST_BORROW_2_r23 1184 -#define _LOAD_FAST_BORROW_3_r01 1185 -#define _LOAD_FAST_BORROW_3_r12 1186 -#define _LOAD_FAST_BORROW_3_r23 1187 -#define _LOAD_FAST_BORROW_4_r01 1188 -#define _LOAD_FAST_BORROW_4_r12 1189 -#define _LOAD_FAST_BORROW_4_r23 1190 -#define _LOAD_FAST_BORROW_5_r01 1191 -#define _LOAD_FAST_BORROW_5_r12 1192 -#define _LOAD_FAST_BORROW_5_r23 1193 -#define _LOAD_FAST_BORROW_6_r01 1194 -#define _LOAD_FAST_BORROW_6_r12 1195 -#define _LOAD_FAST_BORROW_6_r23 1196 -#define _LOAD_FAST_BORROW_7_r01 1197 -#define _LOAD_FAST_BORROW_7_r12 1198 -#define _LOAD_FAST_BORROW_7_r23 1199 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1200 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1201 -#define _LOAD_FAST_CHECK_r01 1202 -#define _LOAD_FAST_CHECK_r12 1203 -#define _LOAD_FAST_CHECK_r23 1204 -#define _LOAD_FAST_LOAD_FAST_r02 1205 -#define _LOAD_FAST_LOAD_FAST_r13 1206 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1207 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1208 -#define _LOAD_GLOBAL_r00 1209 -#define _LOAD_GLOBAL_BUILTINS_r01 1210 -#define _LOAD_GLOBAL_MODULE_r01 1211 -#define _LOAD_LOCALS_r01 1212 -#define _LOAD_LOCALS_r12 1213 -#define _LOAD_LOCALS_r23 1214 -#define _LOAD_NAME_r01 1215 -#define _LOAD_SMALL_INT_r01 1216 -#define _LOAD_SMALL_INT_r12 1217 -#define _LOAD_SMALL_INT_r23 1218 -#define _LOAD_SMALL_INT_0_r01 1219 -#define _LOAD_SMALL_INT_0_r12 1220 -#define _LOAD_SMALL_INT_0_r23 1221 -#define _LOAD_SMALL_INT_1_r01 1222 -#define _LOAD_SMALL_INT_1_r12 1223 -#define _LOAD_SMALL_INT_1_r23 1224 -#define _LOAD_SMALL_INT_2_r01 1225 -#define _LOAD_SMALL_INT_2_r12 1226 -#define _LOAD_SMALL_INT_2_r23 1227 -#define _LOAD_SMALL_INT_3_r01 1228 -#define _LOAD_SMALL_INT_3_r12 1229 -#define _LOAD_SMALL_INT_3_r23 1230 -#define _LOAD_SPECIAL_r00 1231 -#define _LOAD_SUPER_ATTR_ATTR_r31 1232 -#define _LOAD_SUPER_ATTR_METHOD_r32 1233 -#define _MAKE_CALLARGS_A_TUPLE_r33 1234 -#define _MAKE_CELL_r00 1235 -#define _MAKE_FUNCTION_r11 1236 -#define _MAKE_WARM_r00 1237 -#define _MAKE_WARM_r11 1238 -#define _MAKE_WARM_r22 1239 -#define _MAKE_WARM_r33 1240 -#define _MAP_ADD_r20 1241 -#define _MATCH_CLASS_r31 1242 -#define _MATCH_KEYS_r23 1243 -#define _MATCH_MAPPING_r02 1244 -#define _MATCH_MAPPING_r12 1245 -#define _MATCH_MAPPING_r23 1246 -#define _MATCH_SEQUENCE_r02 1247 -#define _MATCH_SEQUENCE_r12 1248 -#define _MATCH_SEQUENCE_r23 1249 -#define _MAYBE_EXPAND_METHOD_r00 1250 -#define _MAYBE_EXPAND_METHOD_KW_r11 1251 -#define _MONITOR_CALL_r00 1252 -#define _MONITOR_CALL_KW_r11 1253 -#define _MONITOR_JUMP_BACKWARD_r00 1254 -#define _MONITOR_JUMP_BACKWARD_r11 1255 -#define _MONITOR_JUMP_BACKWARD_r22 1256 -#define _MONITOR_JUMP_BACKWARD_r33 1257 -#define _MONITOR_RESUME_r00 1258 -#define _NOP_r00 1259 -#define _NOP_r11 1260 -#define _NOP_r22 1261 -#define _NOP_r33 1262 -#define _POP_CALL_r20 1263 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1264 -#define _POP_CALL_ONE_r30 1265 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1266 -#define _POP_CALL_TWO_r30 1267 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1268 -#define _POP_EXCEPT_r10 1269 -#define _POP_ITER_r20 1270 -#define _POP_JUMP_IF_FALSE_r00 1271 -#define _POP_JUMP_IF_FALSE_r10 1272 -#define _POP_JUMP_IF_FALSE_r21 1273 -#define _POP_JUMP_IF_FALSE_r32 1274 -#define _POP_JUMP_IF_TRUE_r00 1275 -#define _POP_JUMP_IF_TRUE_r10 1276 -#define _POP_JUMP_IF_TRUE_r21 1277 -#define _POP_JUMP_IF_TRUE_r32 1278 -#define _POP_TOP_r10 1279 -#define _POP_TOP_FLOAT_r00 1280 -#define _POP_TOP_FLOAT_r10 1281 -#define _POP_TOP_FLOAT_r21 1282 -#define _POP_TOP_FLOAT_r32 1283 -#define _POP_TOP_INT_r00 1284 -#define _POP_TOP_INT_r10 1285 -#define _POP_TOP_INT_r21 1286 -#define _POP_TOP_INT_r32 1287 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1288 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1289 -#define _POP_TOP_NOP_r00 1290 -#define _POP_TOP_NOP_r10 1291 -#define _POP_TOP_NOP_r21 1292 -#define _POP_TOP_NOP_r32 1293 -#define _POP_TOP_UNICODE_r00 1294 -#define _POP_TOP_UNICODE_r10 1295 -#define _POP_TOP_UNICODE_r21 1296 -#define _POP_TOP_UNICODE_r32 1297 -#define _POP_TWO_r20 1298 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1299 -#define _PUSH_EXC_INFO_r02 1300 -#define _PUSH_EXC_INFO_r12 1301 -#define _PUSH_EXC_INFO_r23 1302 -#define _PUSH_FRAME_r10 1303 -#define _PUSH_NULL_r01 1304 -#define _PUSH_NULL_r12 1305 -#define _PUSH_NULL_r23 1306 -#define _PUSH_NULL_CONDITIONAL_r00 1307 -#define _PY_FRAME_EX_r31 1308 -#define _PY_FRAME_GENERAL_r01 1309 -#define _PY_FRAME_KW_r11 1310 -#define _QUICKEN_RESUME_r00 1311 -#define _QUICKEN_RESUME_r11 1312 -#define _QUICKEN_RESUME_r22 1313 -#define _QUICKEN_RESUME_r33 1314 -#define _REPLACE_WITH_TRUE_r02 1315 -#define _REPLACE_WITH_TRUE_r12 1316 -#define _REPLACE_WITH_TRUE_r23 1317 -#define _RESUME_CHECK_r00 1318 -#define _RESUME_CHECK_r11 1319 -#define _RESUME_CHECK_r22 1320 -#define _RESUME_CHECK_r33 1321 -#define _RETURN_GENERATOR_r01 1322 -#define _RETURN_VALUE_r11 1323 -#define _SAVE_RETURN_OFFSET_r00 1324 -#define _SAVE_RETURN_OFFSET_r11 1325 -#define _SAVE_RETURN_OFFSET_r22 1326 -#define _SAVE_RETURN_OFFSET_r33 1327 -#define _SEND_r22 1328 -#define _SEND_GEN_FRAME_r22 1329 -#define _SETUP_ANNOTATIONS_r00 1330 -#define _SET_ADD_r10 1331 -#define _SET_FUNCTION_ATTRIBUTE_r01 1332 -#define _SET_FUNCTION_ATTRIBUTE_r11 1333 -#define _SET_FUNCTION_ATTRIBUTE_r21 1334 -#define _SET_FUNCTION_ATTRIBUTE_r32 1335 -#define _SET_IP_r00 1336 -#define _SET_IP_r11 1337 -#define _SET_IP_r22 1338 -#define _SET_IP_r33 1339 -#define _SET_UPDATE_r10 1340 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1341 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1342 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1343 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1344 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1345 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1346 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1347 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1348 -#define _SPILL_OR_RELOAD_r01 1349 -#define _SPILL_OR_RELOAD_r02 1350 -#define _SPILL_OR_RELOAD_r03 1351 -#define _SPILL_OR_RELOAD_r10 1352 -#define _SPILL_OR_RELOAD_r12 1353 -#define _SPILL_OR_RELOAD_r13 1354 -#define _SPILL_OR_RELOAD_r20 1355 -#define _SPILL_OR_RELOAD_r21 1356 -#define _SPILL_OR_RELOAD_r23 1357 -#define _SPILL_OR_RELOAD_r30 1358 -#define _SPILL_OR_RELOAD_r31 1359 -#define _SPILL_OR_RELOAD_r32 1360 -#define _START_EXECUTOR_r00 1361 -#define _STORE_ATTR_r20 1362 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1363 -#define _STORE_ATTR_SLOT_r21 1364 -#define _STORE_ATTR_WITH_HINT_r21 1365 -#define _STORE_DEREF_r10 1366 -#define _STORE_FAST_LOAD_FAST_r11 1367 -#define _STORE_FAST_STORE_FAST_r20 1368 -#define _STORE_GLOBAL_r10 1369 -#define _STORE_NAME_r10 1370 -#define _STORE_SLICE_r30 1371 -#define _STORE_SUBSCR_r30 1372 -#define _STORE_SUBSCR_DICT_r31 1373 -#define _STORE_SUBSCR_LIST_INT_r32 1374 -#define _SWAP_r11 1375 -#define _SWAP_2_r02 1376 -#define _SWAP_2_r12 1377 -#define _SWAP_2_r22 1378 -#define _SWAP_2_r33 1379 -#define _SWAP_3_r03 1380 -#define _SWAP_3_r13 1381 -#define _SWAP_3_r23 1382 -#define _SWAP_3_r33 1383 -#define _SWAP_FAST_r01 1384 -#define _SWAP_FAST_r11 1385 -#define _SWAP_FAST_r22 1386 -#define _SWAP_FAST_r33 1387 -#define _SWAP_FAST_0_r01 1388 -#define _SWAP_FAST_0_r11 1389 -#define _SWAP_FAST_0_r22 1390 -#define _SWAP_FAST_0_r33 1391 -#define _SWAP_FAST_1_r01 1392 -#define _SWAP_FAST_1_r11 1393 -#define _SWAP_FAST_1_r22 1394 -#define _SWAP_FAST_1_r33 1395 -#define _SWAP_FAST_2_r01 1396 -#define _SWAP_FAST_2_r11 1397 -#define _SWAP_FAST_2_r22 1398 -#define _SWAP_FAST_2_r33 1399 -#define _SWAP_FAST_3_r01 1400 -#define _SWAP_FAST_3_r11 1401 -#define _SWAP_FAST_3_r22 1402 -#define _SWAP_FAST_3_r33 1403 -#define _SWAP_FAST_4_r01 1404 -#define _SWAP_FAST_4_r11 1405 -#define _SWAP_FAST_4_r22 1406 -#define _SWAP_FAST_4_r33 1407 -#define _SWAP_FAST_5_r01 1408 -#define _SWAP_FAST_5_r11 1409 -#define _SWAP_FAST_5_r22 1410 -#define _SWAP_FAST_5_r33 1411 -#define _SWAP_FAST_6_r01 1412 -#define _SWAP_FAST_6_r11 1413 -#define _SWAP_FAST_6_r22 1414 -#define _SWAP_FAST_6_r33 1415 -#define _SWAP_FAST_7_r01 1416 -#define _SWAP_FAST_7_r11 1417 -#define _SWAP_FAST_7_r22 1418 -#define _SWAP_FAST_7_r33 1419 -#define _TIER2_RESUME_CHECK_r00 1420 -#define _TIER2_RESUME_CHECK_r11 1421 -#define _TIER2_RESUME_CHECK_r22 1422 -#define _TIER2_RESUME_CHECK_r33 1423 -#define _TO_BOOL_r11 1424 -#define _TO_BOOL_BOOL_r01 1425 -#define _TO_BOOL_BOOL_r11 1426 -#define _TO_BOOL_BOOL_r22 1427 -#define _TO_BOOL_BOOL_r33 1428 -#define _TO_BOOL_INT_r02 1429 -#define _TO_BOOL_INT_r12 1430 -#define _TO_BOOL_INT_r23 1431 -#define _TO_BOOL_LIST_r02 1432 -#define _TO_BOOL_LIST_r12 1433 -#define _TO_BOOL_LIST_r23 1434 -#define _TO_BOOL_NONE_r01 1435 -#define _TO_BOOL_NONE_r11 1436 -#define _TO_BOOL_NONE_r22 1437 -#define _TO_BOOL_NONE_r33 1438 -#define _TO_BOOL_STR_r02 1439 -#define _TO_BOOL_STR_r12 1440 -#define _TO_BOOL_STR_r23 1441 -#define _TRACE_RECORD_r00 1442 -#define _UNARY_INVERT_r12 1443 -#define _UNARY_NEGATIVE_r12 1444 -#define _UNARY_NOT_r01 1445 -#define _UNARY_NOT_r11 1446 -#define _UNARY_NOT_r22 1447 -#define _UNARY_NOT_r33 1448 -#define _UNPACK_EX_r10 1449 -#define _UNPACK_SEQUENCE_r10 1450 -#define _UNPACK_SEQUENCE_LIST_r10 1451 -#define _UNPACK_SEQUENCE_TUPLE_r10 1452 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1453 -#define _WITH_EXCEPT_START_r33 1454 -#define _YIELD_VALUE_r11 1455 -#define MAX_UOP_REGS_ID 1455 +#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 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 33a4d17d766eb2..c08f1e24fd1c12 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -129,6 +129,8 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GUARD_NOS_DICT] = HAS_EXIT_FLAG, [_GUARD_NOS_ANY_DICT] = HAS_EXIT_FLAG, [_GUARD_TOS_ANY_DICT] = HAS_EXIT_FLAG, + [_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_INIT_CALL] = 0, @@ -211,6 +213,8 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_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, [_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, @@ -1245,6 +1249,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TOS_ANY_DICT_r33 }, }, }, + [_GUARD_TOS_DICT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_DICT_r01 }, + { 1, 1, _GUARD_TOS_DICT_r11 }, + { 2, 2, _GUARD_TOS_DICT_r22 }, + { 3, 3, _GUARD_TOS_DICT_r33 }, + }, + }, + [_GUARD_TOS_FROZENDICT] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_FROZENDICT_r01 }, + { 1, 1, _GUARD_TOS_FROZENDICT_r11 }, + { 2, 2, _GUARD_TOS_FROZENDICT_r22 }, + { 3, 3, _GUARD_TOS_FROZENDICT_r33 }, + }, + }, [_BINARY_OP_SUBSCR_DICT] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -1983,6 +2005,24 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_TOS_ANY_SET_r33 }, }, }, + [_GUARD_TOS_SET] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_SET_r01 }, + { 1, 1, _GUARD_TOS_SET_r11 }, + { 2, 2, _GUARD_TOS_SET_r22 }, + { 3, 3, _GUARD_TOS_SET_r33 }, + }, + }, + [_GUARD_TOS_FROZENSET] = { + .best = { 0, 1, 2, 3 }, + .entries = { + { 1, 0, _GUARD_TOS_FROZENSET_r01 }, + { 1, 1, _GUARD_TOS_FROZENSET_r11 }, + { 2, 2, _GUARD_TOS_FROZENSET_r22 }, + { 3, 3, _GUARD_TOS_FROZENSET_r33 }, + }, + }, [_CONTAINS_OP_SET] = { .best = { 2, 2, 2, 2 }, .entries = { @@ -3742,6 +3782,14 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_ANY_DICT_r11] = _GUARD_TOS_ANY_DICT, [_GUARD_TOS_ANY_DICT_r22] = _GUARD_TOS_ANY_DICT, [_GUARD_TOS_ANY_DICT_r33] = _GUARD_TOS_ANY_DICT, + [_GUARD_TOS_DICT_r01] = _GUARD_TOS_DICT, + [_GUARD_TOS_DICT_r11] = _GUARD_TOS_DICT, + [_GUARD_TOS_DICT_r22] = _GUARD_TOS_DICT, + [_GUARD_TOS_DICT_r33] = _GUARD_TOS_DICT, + [_GUARD_TOS_FROZENDICT_r01] = _GUARD_TOS_FROZENDICT, + [_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_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, @@ -3863,6 +3911,14 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_ANY_SET_r11] = _GUARD_TOS_ANY_SET, [_GUARD_TOS_ANY_SET_r22] = _GUARD_TOS_ANY_SET, [_GUARD_TOS_ANY_SET_r33] = _GUARD_TOS_ANY_SET, + [_GUARD_TOS_SET_r01] = _GUARD_TOS_SET, + [_GUARD_TOS_SET_r11] = _GUARD_TOS_SET, + [_GUARD_TOS_SET_r22] = _GUARD_TOS_SET, + [_GUARD_TOS_SET_r33] = _GUARD_TOS_SET, + [_GUARD_TOS_FROZENSET_r01] = _GUARD_TOS_FROZENSET, + [_GUARD_TOS_FROZENSET_r11] = _GUARD_TOS_FROZENSET, + [_GUARD_TOS_FROZENSET_r22] = _GUARD_TOS_FROZENSET, + [_GUARD_TOS_FROZENSET_r33] = _GUARD_TOS_FROZENSET, [_CONTAINS_OP_SET_r23] = _CONTAINS_OP_SET, [_CONTAINS_OP_DICT_r23] = _CONTAINS_OP_DICT, [_CHECK_EG_MATCH_r22] = _CHECK_EG_MATCH, @@ -4816,11 +4872,26 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_ANY_SET_r11] = "_GUARD_TOS_ANY_SET_r11", [_GUARD_TOS_ANY_SET_r22] = "_GUARD_TOS_ANY_SET_r22", [_GUARD_TOS_ANY_SET_r33] = "_GUARD_TOS_ANY_SET_r33", + [_GUARD_TOS_DICT] = "_GUARD_TOS_DICT", + [_GUARD_TOS_DICT_r01] = "_GUARD_TOS_DICT_r01", + [_GUARD_TOS_DICT_r11] = "_GUARD_TOS_DICT_r11", + [_GUARD_TOS_DICT_r22] = "_GUARD_TOS_DICT_r22", + [_GUARD_TOS_DICT_r33] = "_GUARD_TOS_DICT_r33", [_GUARD_TOS_FLOAT] = "_GUARD_TOS_FLOAT", [_GUARD_TOS_FLOAT_r01] = "_GUARD_TOS_FLOAT_r01", [_GUARD_TOS_FLOAT_r11] = "_GUARD_TOS_FLOAT_r11", [_GUARD_TOS_FLOAT_r22] = "_GUARD_TOS_FLOAT_r22", [_GUARD_TOS_FLOAT_r33] = "_GUARD_TOS_FLOAT_r33", + [_GUARD_TOS_FROZENDICT] = "_GUARD_TOS_FROZENDICT", + [_GUARD_TOS_FROZENDICT_r01] = "_GUARD_TOS_FROZENDICT_r01", + [_GUARD_TOS_FROZENDICT_r11] = "_GUARD_TOS_FROZENDICT_r11", + [_GUARD_TOS_FROZENDICT_r22] = "_GUARD_TOS_FROZENDICT_r22", + [_GUARD_TOS_FROZENDICT_r33] = "_GUARD_TOS_FROZENDICT_r33", + [_GUARD_TOS_FROZENSET] = "_GUARD_TOS_FROZENSET", + [_GUARD_TOS_FROZENSET_r01] = "_GUARD_TOS_FROZENSET_r01", + [_GUARD_TOS_FROZENSET_r11] = "_GUARD_TOS_FROZENSET_r11", + [_GUARD_TOS_FROZENSET_r22] = "_GUARD_TOS_FROZENSET_r22", + [_GUARD_TOS_FROZENSET_r33] = "_GUARD_TOS_FROZENSET_r33", [_GUARD_TOS_INT] = "_GUARD_TOS_INT", [_GUARD_TOS_INT_r01] = "_GUARD_TOS_INT_r01", [_GUARD_TOS_INT_r11] = "_GUARD_TOS_INT_r11", @@ -4836,6 +4907,11 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_TOS_OVERFLOWED_r11] = "_GUARD_TOS_OVERFLOWED_r11", [_GUARD_TOS_OVERFLOWED_r22] = "_GUARD_TOS_OVERFLOWED_r22", [_GUARD_TOS_OVERFLOWED_r33] = "_GUARD_TOS_OVERFLOWED_r33", + [_GUARD_TOS_SET] = "_GUARD_TOS_SET", + [_GUARD_TOS_SET_r01] = "_GUARD_TOS_SET_r01", + [_GUARD_TOS_SET_r11] = "_GUARD_TOS_SET_r11", + [_GUARD_TOS_SET_r22] = "_GUARD_TOS_SET_r22", + [_GUARD_TOS_SET_r33] = "_GUARD_TOS_SET_r33", [_GUARD_TOS_SLICE] = "_GUARD_TOS_SLICE", [_GUARD_TOS_SLICE_r01] = "_GUARD_TOS_SLICE_r01", [_GUARD_TOS_SLICE_r11] = "_GUARD_TOS_SLICE_r11", @@ -5607,6 +5683,10 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GUARD_TOS_ANY_DICT: return 0; + case _GUARD_TOS_DICT: + return 0; + case _GUARD_TOS_FROZENDICT: + return 0; case _BINARY_OP_SUBSCR_DICT: return 2; case _BINARY_OP_SUBSCR_CHECK_FUNC: @@ -5771,6 +5851,10 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _GUARD_TOS_ANY_SET: return 0; + case _GUARD_TOS_SET: + return 0; + case _GUARD_TOS_FROZENSET: + return 0; case _CONTAINS_OP_SET: return 2; case _CONTAINS_OP_DICT: diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 8caad077ec07ec..8a748fec9e4201 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1082,6 +1082,16 @@ dummy_func( EXIT_IF(!PyAnyDict_CheckExact(o)); } + op(_GUARD_TOS_DICT, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + EXIT_IF(!PyDict_CheckExact(o)); + } + + op(_GUARD_TOS_FROZENDICT, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + EXIT_IF(!PyFrozenDict_CheckExact(o)); + } + macro(BINARY_OP_SUBSCR_DICT) = _GUARD_NOS_ANY_DICT + unused/5 + _BINARY_OP_SUBSCR_DICT + POP_TOP + POP_TOP; @@ -2931,6 +2941,16 @@ dummy_func( DEOPT_IF(!PyAnySet_CheckExact(o)); } + op(_GUARD_TOS_SET, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + DEOPT_IF(!PySet_CheckExact(o)); + } + + op(_GUARD_TOS_FROZENSET, (tos -- tos)) { + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + DEOPT_IF(!PyFrozenSet_CheckExact(o)); + } + macro(CONTAINS_OP_SET) = _GUARD_TOS_ANY_SET + unused/1 + _CONTAINS_OP_SET + POP_TOP + POP_TOP; op(_CONTAINS_OP_SET, (left, right -- b, l, r)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 6708a9282077c4..09004545267026 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -6221,6 +6221,176 @@ break; } + case _GUARD_TOS_DICT_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_DICT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_DICT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_DICT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENDICT_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENDICT_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENDICT_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENDICT_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenDict_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _BINARY_OP_SUBSCR_DICT_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -10470,6 +10640,176 @@ break; } + case _GUARD_TOS_SET_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_SET_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_SET_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_SET_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PySet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + tos = stack_pointer[-1]; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r11: { + CHECK_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + tos = _stack_item_0; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache0 = tos; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + tos = _stack_item_1; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache1 = tos; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _GUARD_TOS_FROZENSET_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef tos; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + tos = _stack_item_2; + PyObject *o = PyStackRef_AsPyObjectBorrow(tos); + if (!PyFrozenSet_CheckExact(o)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + _tos_cache2 = tos; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _CONTAINS_OP_SET_r23: { CHECK_CURRENT_CACHED_VALUES(2); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 45dd42c96064bc..a5ed5953ec082c 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -262,6 +262,7 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_new_null _Py_uop_sym_new_null #define sym_has_type _Py_uop_sym_has_type #define sym_get_type _Py_uop_sym_get_type +#define sym_get_probable_type _Py_uop_sym_get_probable_type #define sym_matches_type _Py_uop_sym_matches_type #define sym_matches_type_version _Py_uop_sym_matches_type_version #define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 3dd5d65702b47f..2f52837f058113 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -46,6 +46,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; #define sym_set_recorded_gen_func(SYM, VAL) _Py_uop_sym_set_recorded_gen_func(ctx, SYM, VAL) #define sym_get_probable_func_code _Py_uop_sym_get_probable_func_code #define sym_get_probable_value _Py_uop_sym_get_probable_value +#define sym_get_probable_type _Py_uop_sym_get_probable_type #define sym_set_stack_depth(DEPTH, SP) _Py_uop_sym_set_stack_depth(ctx, DEPTH, SP) extern int @@ -1324,28 +1325,36 @@ dummy_func(void) { if (sym_matches_type(tos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyList_Type); + else { + sym_set_type(tos, &PyList_Type); + } } op(_GUARD_NOS_LIST, (nos, unused -- nos, unused)) { if (sym_matches_type(nos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyList_Type); + else { + sym_set_type(nos, &PyList_Type); + } } op(_GUARD_TOS_TUPLE, (tos -- tos)) { if (sym_matches_type(tos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyTuple_Type); + else { + sym_set_type(tos, &PyTuple_Type); + } } op(_GUARD_NOS_TUPLE, (nos, unused -- nos, unused)) { if (sym_matches_type(nos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyTuple_Type); + else { + sym_set_type(nos, &PyTuple_Type); + } } op(_GUARD_NOS_DICT, (nos, unused -- nos, unused)) { @@ -1359,7 +1368,6 @@ dummy_func(void) { PyTypeObject *tp = sym_get_type(nos); if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { ADD_OP(_NOP, 0, 0); - sym_set_type(nos, tp); } } @@ -1367,65 +1375,133 @@ dummy_func(void) { PyTypeObject *tp = sym_get_type(tos); if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { ADD_OP(_NOP, 0, 0); - sym_set_type(tos, tp); + } + else { + // Narrowing the guard based on the probable type. + tp = sym_get_probable_type(tos); + if (tp == &PyDict_Type) { + ADD_OP(_GUARD_TOS_DICT, 0, 0); + } + else if (tp == &PyFrozenDict_Type) { + ADD_OP(_GUARD_TOS_FROZENDICT, 0, 0); + } + } + } + + op(_GUARD_TOS_DICT, (tos -- tos)) { + if (sym_matches_type(tos, &PyDict_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyDict_Type); + } + } + + op(_GUARD_TOS_FROZENDICT, (tos -- tos)) { + if (sym_matches_type(tos, &PyFrozenDict_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyFrozenDict_Type); } } op(_GUARD_TOS_ANY_SET, (tos -- tos)) { - if (sym_matches_type(tos, &PySet_Type) || - sym_matches_type(tos, &PyFrozenSet_Type)) - { + PyTypeObject *tp = sym_get_type(tos); + if (tp == &PySet_Type || tp == &PyFrozenSet_Type) { + ADD_OP(_NOP, 0, 0); + } + else { + // Narrowing the guard based on the probable type. + tp = sym_get_probable_type(tos); + if (tp == &PySet_Type) { + ADD_OP(_GUARD_TOS_SET, 0, 0); + } + else if (tp == &PyFrozenSet_Type) { + ADD_OP(_GUARD_TOS_FROZENSET, 0, 0); + } + } + } + + op(_GUARD_TOS_SET, (tos -- tos)) { + if (sym_matches_type(tos, &PySet_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PySet_Type); + } + } + + op(_GUARD_TOS_FROZENSET, (tos -- tos)) { + if (sym_matches_type(tos, &PyFrozenSet_Type)) { ADD_OP(_NOP, 0, 0); } + else { + sym_set_type(tos, &PyFrozenSet_Type); + } } op(_GUARD_TOS_SLICE, (tos -- tos)) { if (sym_matches_type(tos, &PySlice_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PySlice_Type); + else { + sym_set_type(tos, &PySlice_Type); + } } op(_GUARD_NOS_NULL, (null, unused -- null, unused)) { if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } } op(_GUARD_NOS_NOT_NULL, (nos, unused -- nos, unused)) { if (sym_is_not_null(nos)) { ADD_OP(_NOP, 0, 0); } - sym_set_non_null(nos); + else { + sym_set_non_null(nos); + } } op(_GUARD_THIRD_NULL, (null, unused, unused -- null, unused, unused)) { if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } } op(_GUARD_CALLABLE_TYPE_1, (callable, unused, unused -- callable, unused, unused)) { if (sym_get_const(ctx, callable) == (PyObject *)&PyType_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyType_Type); + else { + sym_set_const(callable, (PyObject *)&PyType_Type); + } } op(_GUARD_CALLABLE_TUPLE_1, (callable, unused, unused -- callable, unused, unused)) { if (sym_get_const(ctx, callable) == (PyObject *)&PyTuple_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyTuple_Type); + else { + sym_set_const(callable, (PyObject *)&PyTuple_Type); + } } op(_GUARD_CALLABLE_STR_1, (callable, unused, unused -- callable, unused, unused)) { if (sym_get_const(ctx, callable) == (PyObject *)&PyUnicode_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyUnicode_Type); + else { + sym_set_const(callable, (PyObject *)&PyUnicode_Type); + } } op(_CALL_LEN, (callable, null, arg -- res, a, c)) { @@ -1484,7 +1560,9 @@ dummy_func(void) { if (sym_get_const(ctx, callable) == len) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, len); + else { + sym_set_const(callable, len); + } } op(_GUARD_CALLABLE_ISINSTANCE, (callable, unused, unused, unused -- callable, unused, unused, unused)) { @@ -1492,7 +1570,9 @@ dummy_func(void) { if (sym_get_const(ctx, callable) == isinstance) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, isinstance); + else { + sym_set_const(callable, isinstance); + } } op(_GUARD_CALLABLE_LIST_APPEND, (callable, unused, unused -- callable, unused, unused)) { @@ -1500,7 +1580,9 @@ dummy_func(void) { if (sym_get_const(ctx, callable) == list_append) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, list_append); + else { + sym_set_const(callable, list_append); + } } op(_BINARY_SLICE, (container, start, stop -- res)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index f2616eddbb758a..c35c77ed442d7a 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -355,7 +355,9 @@ if (sym_matches_type(nos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyList_Type); + else { + sym_set_type(nos, &PyList_Type); + } break; } @@ -365,7 +367,9 @@ if (sym_matches_type(tos, &PyList_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyList_Type); + else { + sym_set_type(tos, &PyList_Type); + } break; } @@ -375,7 +379,9 @@ if (sym_matches_type(tos, &PySlice_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PySlice_Type); + else { + sym_set_type(tos, &PySlice_Type); + } break; } @@ -1023,7 +1029,9 @@ if (sym_matches_type(nos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(nos, &PyTuple_Type); + else { + sym_set_type(nos, &PyTuple_Type); + } break; } @@ -1033,7 +1041,9 @@ if (sym_matches_type(tos, &PyTuple_Type)) { ADD_OP(_NOP, 0, 0); } - sym_set_type(tos, &PyTuple_Type); + else { + sym_set_type(tos, &PyTuple_Type); + } break; } @@ -1107,7 +1117,6 @@ PyTypeObject *tp = sym_get_type(nos); if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { ADD_OP(_NOP, 0, 0); - sym_set_type(nos, tp); } break; } @@ -1118,7 +1127,39 @@ PyTypeObject *tp = sym_get_type(tos); if (tp == &PyDict_Type || tp == &PyFrozenDict_Type) { ADD_OP(_NOP, 0, 0); - sym_set_type(tos, tp); + } + else { + tp = sym_get_probable_type(tos); + if (tp == &PyDict_Type) { + ADD_OP(_GUARD_TOS_DICT, 0, 0); + } + else if (tp == &PyFrozenDict_Type) { + ADD_OP(_GUARD_TOS_FROZENDICT, 0, 0); + } + } + break; + } + + case _GUARD_TOS_DICT: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PyDict_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyDict_Type); + } + break; + } + + case _GUARD_TOS_FROZENDICT: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PyFrozenDict_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyFrozenDict_Type); } break; } @@ -2430,11 +2471,43 @@ case _GUARD_TOS_ANY_SET: { JitOptRef tos; tos = stack_pointer[-1]; - if (sym_matches_type(tos, &PySet_Type) || - sym_matches_type(tos, &PyFrozenSet_Type)) - { + PyTypeObject *tp = sym_get_type(tos); + if (tp == &PySet_Type || tp == &PyFrozenSet_Type) { + ADD_OP(_NOP, 0, 0); + } + else { + tp = sym_get_probable_type(tos); + if (tp == &PySet_Type) { + ADD_OP(_GUARD_TOS_SET, 0, 0); + } + else if (tp == &PyFrozenSet_Type) { + ADD_OP(_GUARD_TOS_FROZENSET, 0, 0); + } + } + break; + } + + case _GUARD_TOS_SET: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PySet_Type)) { ADD_OP(_NOP, 0, 0); } + else { + sym_set_type(tos, &PySet_Type); + } + break; + } + + case _GUARD_TOS_FROZENSET: { + JitOptRef tos; + tos = stack_pointer[-1]; + if (sym_matches_type(tos, &PyFrozenSet_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(tos, &PyFrozenSet_Type); + } break; } @@ -3071,7 +3144,9 @@ if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } break; } @@ -3081,7 +3156,9 @@ if (sym_is_not_null(nos)) { ADD_OP(_NOP, 0, 0); } - sym_set_non_null(nos); + else { + sym_set_non_null(nos); + } break; } @@ -3091,7 +3168,9 @@ if (sym_is_null(null)) { ADD_OP(_NOP, 0, 0); } - sym_set_null(null); + else { + sym_set_null(null); + } break; } @@ -3101,7 +3180,9 @@ if (sym_get_const(ctx, callable) == (PyObject *)&PyType_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyType_Type); + else { + sym_set_const(callable, (PyObject *)&PyType_Type); + } break; } @@ -3134,7 +3215,9 @@ if (sym_get_const(ctx, callable) == (PyObject *)&PyUnicode_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyUnicode_Type); + else { + sym_set_const(callable, (PyObject *)&PyUnicode_Type); + } break; } @@ -3164,7 +3247,9 @@ if (sym_get_const(ctx, callable) == (PyObject *)&PyTuple_Type) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, (PyObject *)&PyTuple_Type); + else { + sym_set_const(callable, (PyObject *)&PyTuple_Type); + } break; } @@ -3307,7 +3392,9 @@ if (sym_get_const(ctx, callable) == len) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, len); + else { + sym_set_const(callable, len); + } break; } @@ -3368,7 +3455,9 @@ if (sym_get_const(ctx, callable) == isinstance) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, isinstance); + else { + sym_set_const(callable, isinstance); + } break; } @@ -3403,7 +3492,9 @@ if (sym_get_const(ctx, callable) == list_append) { ADD_OP(_NOP, 0, 0); } - sym_set_const(callable, list_append); + else { + sym_set_const(callable, list_append); + } break; } diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index dcbe093fd6d74c..fd784aa11e4b89 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -688,6 +688,34 @@ _Py_uop_sym_get_type(JitOptRef ref) Py_UNREACHABLE(); } +PyTypeObject * +_Py_uop_sym_get_probable_type(JitOptRef ref) +{ + JitOptSymbol *sym = PyJitRef_Unwrap(ref); + JitSymType tag = sym->tag; + switch(tag) { + case JIT_SYM_NULL_TAG: + case JIT_SYM_BOTTOM_TAG: + case JIT_SYM_NON_NULL_TAG: + case JIT_SYM_UNKNOWN_TAG: + case JIT_SYM_TYPE_VERSION_TAG: + case JIT_SYM_TUPLE_TAG: + case JIT_SYM_PREDICATE_TAG: + case JIT_SYM_TRUTHINESS_TAG: + case JIT_SYM_COMPACT_INT: + case JIT_SYM_KNOWN_CLASS_TAG: + case JIT_SYM_KNOWN_VALUE_TAG: + return _Py_uop_sym_get_type(ref); + case JIT_SYM_RECORDED_GEN_FUNC_TAG: + return NULL; + case JIT_SYM_RECORDED_VALUE_TAG: + return Py_TYPE(sym->recorded_value.value); + case JIT_SYM_RECORDED_TYPE_TAG: + return sym->recorded_type.type; + } + Py_UNREACHABLE(); +} + unsigned int _Py_uop_sym_get_type_version(JitOptRef ref) { From f1de65b3669226d563802a32b78a2294e971151a Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 3 Mar 2026 11:47:02 +0100 Subject: [PATCH 020/196] gh-145455: Show output of blurb & sphinx-build version commands (GH-145457) In gh-145455, an outdated dependency caused an import error that was not printed out (`2>&1`); the message instead said that the tools are missing. Don't redirect stderr, to show warnings and failures. Also, switch `blurb` to output a version on a single line (`--version` rather than `help`), and, and don't redirect stdout either. This results in two version info lines being printed out. These get drowned in typical Sphinx output, and can be helpful when debugging. --- Doc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Makefile b/Doc/Makefile index d39c2fe3c3f22a..5b7fdf8ec08ed4 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -58,7 +58,7 @@ build: @if [ -f ../Misc/NEWS ] ; then \ echo "Using existing Misc/NEWS file"; \ cp ../Misc/NEWS build/NEWS; \ - elif $(BLURB) help >/dev/null 2>&1 && $(SPHINXBUILD) --version >/dev/null 2>&1; then \ + elif $(BLURB) --version && $(SPHINXBUILD) --version ; then \ if [ -d ../Misc/NEWS.d ]; then \ echo "Building NEWS from Misc/NEWS.d with blurb"; \ $(BLURB) merge -f build/NEWS; \ From c9d123482acebcf725c847bd6f8354bdd9314189 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 3 Mar 2026 12:15:32 +0100 Subject: [PATCH 021/196] gh-144995: Optimize memoryview == memoryview (#144996) Optimize memoryview comparison: a memoryview is equal to itself, there is no need to compare values, except if it uses float format. Benchmark comparing 1 MiB: from timeit import timeit with open("/dev/random", 'br') as fp: data = fp.read(2**20) view = memoryview(data) LOOPS = 1_000 b = timeit('x == x', number=LOOPS, globals={'x': data}) m = timeit('x == x', number=LOOPS, globals={'x': view}) print("bytes %f seconds" % b) print("mview %f seconds" % m) print("=> %f time slower" % (m / b)) Result before the change: bytes 0.000026 seconds mview 1.445791 seconds => 55660.873940 time slower Result after the change: bytes 0.000026 seconds mview 0.000028 seconds => 1.104382 time slower This missed optimization was discovered by Pierre-Yves David while working on Mercurial. Co-authored-by: Pieter Eendebak --- Lib/test/test_memoryview.py | 61 +++++++++++++++++++ ...-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst | 2 + Objects/memoryobject.c | 24 ++++++++ 3 files changed, 87 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py index 656318668e6d6e..0f7dc15b8c6f2c 100644 --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -575,6 +575,67 @@ def test_array_assign(self): m[:] = new_a self.assertEqual(a, new_a) + def test_compare_equal(self): + # A memoryview is equal to itself: there is no need to compare + # individual values. This is not true for float values since they can + # be NaN, and NaN is not equal to itself. + + def check_equal(view, is_equal): + self.assertEqual(view == view, is_equal) + self.assertEqual(view != view, not is_equal) + + # Comparison with a different memoryview doesn't use + # the optimization and should give the same result. + view2 = memoryview(view) + self.assertEqual(view2 == view, is_equal) + self.assertEqual(view2 != view2, not is_equal) + + # Test integer formats + for int_format in 'bBhHiIlLqQ': + with self.subTest(format=int_format): + a = array.array(int_format, [1, 2, 3]) + m = memoryview(a) + check_equal(m, True) + + if int_format in 'bB': + m2 = m.cast('@' + m.format) + check_equal(m2, True) + + # Test 'c' format + a = array.array('B', [1, 2, 3]) + m = memoryview(a.tobytes()).cast('c') + check_equal(m, True) + + # Test 'n' and 'N' formats + if struct.calcsize('L') == struct.calcsize('N'): + int_format = 'L' + elif struct.calcsize('Q') == struct.calcsize('N'): + int_format = 'Q' + else: + int_format = None + if int_format: + a = array.array(int_format, [1, 2, 3]) + m = memoryview(a.tobytes()).cast('N') + check_equal(m, True) + m = memoryview(a.tobytes()).cast('n') + check_equal(m, True) + + # Test '?' format + m = memoryview(b'\0\1\2').cast('?') + check_equal(m, True) + + # Test float formats + for float_format in 'fd': + with self.subTest(format=float_format): + a = array.array(float_format, [1.0, 2.0, float('nan')]) + m = memoryview(a) + # nan is not equal to nan + check_equal(m, False) + + a = array.array(float_format, [1.0, 2.0, 3.0]) + m = memoryview(a) + check_equal(m, True) + class BytesMemorySliceTest(unittest.TestCase, BaseMemorySliceTests, BaseBytesMemoryTests): 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 new file mode 100644 index 00000000000000..83d84b9505c5a5 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst @@ -0,0 +1,2 @@ +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/Objects/memoryobject.c b/Objects/memoryobject.c index f3b7e4a396b4a1..0ad4f02d80bf50 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -3122,6 +3122,30 @@ memory_richcompare(PyObject *v, PyObject *w, int op) } vv = VIEW_ADDR(v); + // For formats supported by the struct module a memoryview is equal to + // itself: there is no need to compare individual values. + // This is not true for float values since they can be NaN, and NaN + // is not equal to itself. So only use this optimization on format known to + // not use floats. + if (v == w) { + const char *format = vv->format; + if (format != NULL) { + if (*format == '@') { + format++; + } + // Include only formats known by struct, exclude float formats + // "d" (double), "f" (float) and "e" (16-bit float). + // Do not optimize "P" format. + if (format[0] != 0 + && strchr("bBchHiIlLnNqQ?", format[0]) != NULL + && format[1] == 0) + { + equal = 1; + goto result; + } + } + } + if (PyMemoryView_Check(w)) { if (BASE_INACCESSIBLE(w)) { equal = (v == w); From a929e80b9e5aa5aa23bd3fb3397dfc0ac605c067 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Tue, 3 Mar 2026 12:10:34 +0000 Subject: [PATCH 022/196] Add `PyExc_OverflowError` to the list of possible exceptions in `fuzz_ast_literal_eval` fuzzer (GH-145429) --- Modules/_xxtestfuzz/fuzzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index 0cbe10c79ab4a6..14da472c1bb110 100644 --- a/Modules/_xxtestfuzz/fuzzer.c +++ b/Modules/_xxtestfuzz/fuzzer.c @@ -428,6 +428,7 @@ static int fuzz_ast_literal_eval(const char* data, size_t size) { PyErr_ExceptionMatches(PyExc_TypeError) || PyErr_ExceptionMatches(PyExc_SyntaxError) || PyErr_ExceptionMatches(PyExc_MemoryError) || + PyErr_ExceptionMatches(PyExc_OverflowError) || PyErr_ExceptionMatches(PyExc_RecursionError)) ) { PyErr_Clear(); From db41717cd50af6db7d496b0aa282b1f3370327c6 Mon Sep 17 00:00:00 2001 From: "Michiel W. Beijen" Date: Tue, 3 Mar 2026 13:44:56 +0100 Subject: [PATCH 023/196] GH-145450: Document missing `wave.Wave_write` getter methods (GH-145451) --- Doc/library/wave.rst | 37 +++++++++++++++++++ ...-03-03-08-18-00.gh-issue-145450.VI7GXj.rst | 1 + 2 files changed, 38 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2026-03-03-08-18-00.gh-issue-145450.VI7GXj.rst diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 6e61a1a44ad232..ff020b52da3f23 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -181,11 +181,21 @@ Wave_write Objects Set the number of channels. + .. method:: getnchannels() + + Return the number of channels. + + .. method:: setsampwidth(n) Set the sample width to *n* bytes. + .. method:: getsampwidth() + + Return the sample width in bytes. + + .. method:: setframerate(n) Set the frame rate to *n*. @@ -195,6 +205,11 @@ Wave_write Objects integer. + .. method:: getframerate() + + Return the frame rate. + + .. method:: setnframes(n) Set the number of frames to *n*. This will be changed later if the number @@ -202,12 +217,27 @@ Wave_write Objects raise an error if the output stream is not seekable). + .. method:: getnframes() + + Return the number of audio frames written so far. + + .. method:: setcomptype(type, name) Set the compression type and description. At the moment, only compression type ``NONE`` is supported, meaning no compression. + .. method:: getcomptype() + + Return the compression type (``'NONE'``). + + + .. method:: getcompname() + + Return the human-readable compression type name. + + .. method:: setparams(tuple) The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype, @@ -215,6 +245,13 @@ Wave_write Objects parameters. + .. method:: getparams() + + Return a :func:`~collections.namedtuple` + ``(nchannels, sampwidth, framerate, nframes, comptype, compname)`` + containing the current output parameters. + + .. method:: tell() Return current position in the file, with the same disclaimer for the 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 new file mode 100644 index 00000000000000..681c932b34a05d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-03-03-08-18-00.gh-issue-145450.VI7GXj.rst @@ -0,0 +1 @@ +Document missing public :class:`wave.Wave_write` getter methods. From 52c8efa87d028e57895d6a44f22caeb99a589711 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 3 Mar 2026 13:57:08 +0100 Subject: [PATCH 024/196] gh-145335: Fix os functions when passing fd -1 as path (#145439) 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. --- Doc/library/os.rst | 12 ++++ Lib/test/test_os/test_os.py | 51 ++++++++++++++ ...-03-02-20-08-09.gh-issue-145335.lVTBvd.rst | 5 ++ Modules/posixmodule.c | 67 ++++++++++--------- 4 files changed, 103 insertions(+), 32 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-03-02-20-08-09.gh-issue-145335.lVTBvd.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 7418f3a8bacb0f..a22afdec516bb4 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2409,6 +2409,10 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: next + ``os.listdir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing the current directory. + .. function:: listdrives() @@ -2939,6 +2943,10 @@ features: .. versionchanged:: 3.7 Added support for :ref:`file descriptors ` on Unix. + .. versionchanged:: next + ``os.scandir(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing the current directory. + .. class:: DirEntry @@ -4574,6 +4582,10 @@ These functions are all available on Linux only. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: next + ``os.listxattr(-1)`` now fails with ``OSError(errno.EBADF)`` rather than + listing extended attributes of the current directory. + .. function:: removexattr(path, attribute, *, follow_symlinks=True) diff --git a/Lib/test/test_os/test_os.py b/Lib/test/test_os/test_os.py index 1f241609da80cd..3cab8ff9536d23 100644 --- a/Lib/test/test_os/test_os.py +++ b/Lib/test/test_os/test_os.py @@ -2784,10 +2784,61 @@ def test_fpathconf_bad_fd(self): 'musl fpathconf ignores the file descriptor and returns a constant', ) def test_pathconf_negative_fd_uses_fd_semantics(self): + if os.pathconf not in os.supports_fd: + self.skipTest('needs fpathconf()') + with self.assertRaises(OSError) as ctx: os.pathconf(-1, 1) self.assertEqual(ctx.exception.errno, errno.EBADF) + @support.subTests("fd", [-1, -5]) + def test_negative_fd_ebadf(self, fd): + tests = [(os.stat, fd)] + if hasattr(os, "statx"): + tests.append((os.statx, fd, 0)) + if os.chdir in os.supports_fd: + tests.append((os.chdir, fd)) + if os.chmod in os.supports_fd: + tests.append((os.chmod, fd, 0o777)) + if hasattr(os, "chown") and os.chown in os.supports_fd: + tests.append((os.chown, fd, 0, 0)) + if os.listdir in os.supports_fd: + tests.append((os.listdir, fd)) + if os.utime in os.supports_fd: + tests.append((os.utime, fd, (0, 0))) + if hasattr(os, "truncate") and os.truncate in os.supports_fd: + tests.append((os.truncate, fd, 0)) + if hasattr(os, 'statvfs') and os.statvfs in os.supports_fd: + tests.append((os.statvfs, fd)) + if hasattr(os, "setxattr"): + tests.append((os.getxattr, fd, b"user.test")) + tests.append((os.setxattr, fd, b"user.test", b"1")) + tests.append((os.removexattr, fd, b"user.test")) + tests.append((os.listxattr, fd)) + if os.scandir in os.supports_fd: + tests.append((os.scandir, fd)) + + for func, *args in tests: + with self.subTest(func=func, args=args): + with self.assertRaises(OSError) as ctx: + func(*args) + self.assertEqual(ctx.exception.errno, errno.EBADF) + + if hasattr(os, "execve") and os.execve in os.supports_fd: + # glibc fails with EINVAL, musl fails with EBADF + with self.assertRaises(OSError) as ctx: + os.execve(fd, [sys.executable, "-c", "pass"], os.environ) + self.assertIn(ctx.exception.errno, (errno.EBADF, errno.EINVAL)) + + if support.MS_WINDOWS: + import nt + self.assertFalse(nt._path_exists(fd)) + self.assertFalse(nt._path_lexists(fd)) + self.assertFalse(nt._path_isdir(fd)) + self.assertFalse(nt._path_isfile(fd)) + self.assertFalse(nt._path_islink(fd)) + self.assertFalse(nt._path_isjunction(fd)) + @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()') def test_ftruncate(self): self.check(os.truncate, 0) 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 new file mode 100644 index 00000000000000..53033b06c2fae0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-02-20-08-09.gh-issue-145335.lVTBvd.rst @@ -0,0 +1,5 @@ +``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/Modules/posixmodule.c b/Modules/posixmodule.c index b82f08e7dc4291..aa3d682a19bc9c 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1638,10 +1638,10 @@ dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) } static int -fd_and_follow_symlinks_invalid(const char *function_name, int fd, +fd_and_follow_symlinks_invalid(const char *function_name, int is_fd, int follow_symlinks) { - if ((fd >= 0) && (!follow_symlinks)) { + if (is_fd && (!follow_symlinks)) { PyErr_Format(PyExc_ValueError, "%s: cannot use fd and follow_symlinks together", function_name); @@ -2880,12 +2880,13 @@ posix_do_stat(PyObject *module, const char *function_name, path_t *path, if (path_and_dir_fd_invalid("stat", path, dir_fd) || dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks)) return NULL; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) + if (path->is_fd) { result = FSTAT(path->fd, &st); + } #ifdef MS_WINDOWS else if (follow_symlinks) result = win32_stat(path->wide, &st); @@ -3647,7 +3648,7 @@ os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags, { if (path_and_dir_fd_invalid("statx", path, dir_fd) || dir_fd_and_fd_invalid("statx", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("statx", path->fd, follow_symlinks)) { + fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) { return NULL; } @@ -3677,7 +3678,7 @@ os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags, int result; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx); } else { @@ -3934,7 +3935,7 @@ os_chdir_impl(PyObject *module, path_t *path) result = !win32_wchdir(path->wide); #else #ifdef HAVE_FCHDIR - if (path->fd != -1) + if (path->is_fd) result = fchdir(path->fd); else #endif @@ -4090,7 +4091,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, #ifdef MS_WINDOWS result = 0; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = win32_fchmod(path->fd, mode); } else if (follow_symlinks) { @@ -4113,8 +4114,9 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHMOD - if (path->fd != -1) + if (path->is_fd) { result = fchmod(path->fd, mode); + } else #endif /* HAVE_CHMOD */ #ifdef HAVE_LCHMOD @@ -4511,7 +4513,7 @@ os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, return NULL; #endif if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, @@ -4521,7 +4523,7 @@ os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHOWN - if (path->fd != -1) + if (path->is_fd) result = fchown(path->fd, uid, gid); else #endif @@ -4999,7 +5001,7 @@ _posix_listdir(path_t *path, PyObject *list) errno = 0; #ifdef HAVE_FDOPENDIR - if (path->fd != -1) { + if (path->is_fd) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ fd = _Py_dup(path->fd); @@ -5898,7 +5900,7 @@ _testFileExists(path_t *path, BOOL followLinks) } Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) { @@ -5924,7 +5926,7 @@ _testFileType(path_t *path, int testedType) } Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { result = _testFileTypeByHandle(hfile, testedType, TRUE); @@ -7141,7 +7143,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, if (path_and_dir_fd_invalid("utime", path, dir_fd) || dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) + fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks)) return NULL; #if !defined(HAVE_UTIMENSAT) @@ -7200,7 +7202,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #endif #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) - if (path->fd != -1) + if (path->is_fd) result = utime_fd(&utime, path->fd); else #endif @@ -7569,7 +7571,7 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_FEXECVE - if (path->fd > -1) + if (path->is_fd) fexecve(path->fd, argvlist, envlist); else #endif @@ -13355,7 +13357,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) int fd; #endif - if (path->fd != -1) + if (path->is_fd) return os_ftruncate_impl(module, path->fd, length); if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { @@ -14052,7 +14054,7 @@ os_statvfs_impl(PyObject *module, path_t *path) struct statfs st; Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) { + if (path->is_fd) { result = fstatfs(path->fd, &st); } else @@ -14070,7 +14072,7 @@ os_statvfs_impl(PyObject *module, path_t *path) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FSTATVFS - if (path->fd != -1) { + if (path->is_fd) { result = fstatvfs(path->fd, &st); } else @@ -15410,7 +15412,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks) /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ { - if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { @@ -15432,7 +15434,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, void *ptr = PyBytesWriter_GetData(writer); Py_BEGIN_ALLOW_THREADS; - if (path->fd >= 0) + if (path->is_fd) result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); else if (follow_symlinks) result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); @@ -15481,7 +15483,7 @@ os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, { ssize_t result; - if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, @@ -15490,7 +15492,7 @@ os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) result = fsetxattr(path->fd, attribute->narrow, value->buf, value->len, flags); else if (follow_symlinks) @@ -15534,7 +15536,7 @@ os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, { ssize_t result; - if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks)) return NULL; if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { @@ -15542,7 +15544,7 @@ os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) result = fremovexattr(path->fd, attribute->narrow); else if (follow_symlinks) result = removexattr(path->narrow, attribute->narrow); @@ -15584,7 +15586,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) const char *name; char *buffer = NULL; - if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) + if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks)) goto exit; if (PySys_Audit("os.listxattr", "(O)", @@ -15611,7 +15613,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) } Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) + if (path->is_fd) length = flistxattr(path->fd, buffer, buffer_size); else if (follow_symlinks) length = listxattr(name, buffer, buffer_size); @@ -16664,7 +16666,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, entry->stat = NULL; entry->lstat = NULL; - if (path->fd != -1) { + if (path->is_fd) { entry->dir_fd = path->fd; joined_path = NULL; } @@ -16689,7 +16691,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, if (!entry->name) goto error; - if (path->fd != -1) { + if (path->is_fd) { entry->path = Py_NewRef(entry->name); } else if (!entry->path) @@ -16813,8 +16815,9 @@ ScandirIterator_closedir(ScandirIterator *iterator) iterator->dirp = NULL; Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) + if (iterator->path.is_fd) { rewinddir(dirp); + } #endif closedir(dirp); Py_END_ALLOW_THREADS @@ -17034,7 +17037,7 @@ os_scandir_impl(PyObject *module, path_t *path) #else /* POSIX */ errno = 0; #ifdef HAVE_FDOPENDIR - if (iterator->path.fd != -1) { + if (iterator->path.is_fd) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ fd = _Py_dup(iterator->path.fd); From 671a953dd65292a5b69ba7393666ddcac93dbc44 Mon Sep 17 00:00:00 2001 From: bkap123 <97006829+bkap123@users.noreply.github.com> Date: Tue, 3 Mar 2026 08:46:02 -0500 Subject: [PATCH 025/196] gh-144475: Fix reference management in partial_repr (GH-145362) --- Lib/test/test_functools.py | 52 ++++++++++++++++++ ...-02-07-16-37-42.gh-issue-144475.8tFEXw.rst | 3 + Modules/_functoolsmodule.c | 55 +++++++++++-------- 3 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-07-16-37-42.gh-issue-144475.8tFEXw.rst diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 86652b7fa4d6df..dda42cb33072c3 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -514,6 +514,58 @@ def test_partial_genericalias(self): self.assertEqual(alias.__args__, (int,)) self.assertEqual(alias.__parameters__, ()) + # GH-144475: Tests that the partial object does not change until repr finishes + def test_repr_safety_against_reentrant_mutation(self): + g_partial = None + + class Function: + def __init__(self, name): + self.name = name + + def __call__(self): + return None + + def __repr__(self): + return f"Function({self.name})" + + class EvilObject: + def __init__(self): + self.triggered = False + + def __repr__(self): + if not self.triggered and g_partial is not None: + self.triggered = True + new_args_tuple = (None,) + new_keywords_dict = {"keyword": None} + new_tuple_state = (Function("new_function"), new_args_tuple, new_keywords_dict, None) + g_partial.__setstate__(new_tuple_state) + gc.collect() + return f"EvilObject" + + trigger = EvilObject() + func = Function("old_function") + + g_partial = functools.partial(func, None, trigger=trigger) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), None, trigger=EvilObject)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, arg=None)") + + + trigger.triggered = False + g_partial = functools.partial(func, trigger, None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, None)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger=trigger, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), trigger=EvilObject, arg=None)") + + trigger.triggered = False + g_partial = functools.partial(func, trigger, None, None, None, None, arg=None) + self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, None, None, None, None, arg=None)") + + @unittest.skipUnless(c_functools, 'requires the C _functools module') class TestPartialC(TestPartial, unittest.TestCase): 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 new file mode 100644 index 00000000000000..b458399bb40640 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-07-16-37-42.gh-issue-144475.8tFEXw.rst @@ -0,0 +1,3 @@ +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/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 5773083ff68b46..5286be0b715fff 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -688,65 +688,72 @@ partial_repr(PyObject *self) { partialobject *pto = partialobject_CAST(self); PyObject *result = NULL; - PyObject *arglist; - PyObject *mod; - PyObject *name; + PyObject *arglist = NULL; + PyObject *mod = NULL; + PyObject *name = NULL; Py_ssize_t i, n; PyObject *key, *value; int status; status = Py_ReprEnter(self); if (status != 0) { - if (status < 0) + if (status < 0) { return NULL; + } return PyUnicode_FromString("..."); } + /* Reference arguments in case they change */ + PyObject *fn = Py_NewRef(pto->fn); + PyObject *args = Py_NewRef(pto->args); + PyObject *kw = Py_NewRef(pto->kw); + assert(PyTuple_Check(args)); + assert(PyDict_Check(kw)); arglist = Py_GetConstant(Py_CONSTANT_EMPTY_STR); - if (arglist == NULL) + if (arglist == NULL) { goto done; + } /* Pack positional arguments */ - assert(PyTuple_Check(pto->args)); - n = PyTuple_GET_SIZE(pto->args); + n = PyTuple_GET_SIZE(args); for (i = 0; i < n; i++) { Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist, - PyTuple_GET_ITEM(pto->args, i))); - if (arglist == NULL) + PyTuple_GET_ITEM(args, i))); + if (arglist == NULL) { goto done; + } } /* Pack keyword arguments */ - assert (PyDict_Check(pto->kw)); - for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) { + for (i = 0; PyDict_Next(kw, &i, &key, &value);) { /* Prevent key.__str__ from deleting the value. */ Py_INCREF(value); Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist, key, value)); Py_DECREF(value); - if (arglist == NULL) + if (arglist == NULL) { goto done; + } } mod = PyType_GetModuleName(Py_TYPE(pto)); if (mod == NULL) { - goto error; + goto done; } + name = PyType_GetQualName(Py_TYPE(pto)); if (name == NULL) { - Py_DECREF(mod); - goto error; + goto done; } - result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, pto->fn, arglist); - Py_DECREF(mod); - Py_DECREF(name); - Py_DECREF(arglist); - done: + result = PyUnicode_FromFormat("%S.%S(%R%U)", mod, name, fn, arglist); +done: + Py_XDECREF(name); + Py_XDECREF(mod); + Py_XDECREF(arglist); + Py_DECREF(fn); + Py_DECREF(args); + Py_DECREF(kw); Py_ReprLeave(self); return result; - error: - Py_DECREF(arglist); - Py_ReprLeave(self); - return NULL; } /* Pickle strategy: From 246227392cacf4f31f933a671264f55897d93a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Tue, 3 Mar 2026 14:35:48 +0000 Subject: [PATCH 026/196] Add myself to initialization and import machinery codeowners (#145473) --- .github/CODEOWNERS | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 19cc7050a43f04..5bf60348f68250 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -260,33 +260,33 @@ Include/pyhash.h @gpshead @picnixz Python/pyhash.c @gpshead @picnixz # The import system (including importlib) -**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw -Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @kumaraditya303 +**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00 +Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00 @kumaraditya303 **/*freeze* @ericsnowcurrently **/*frozen* @ericsnowcurrently **/*modsupport* @ericsnowcurrently -**/*modulefinder* @ericsnowcurrently +**/*modulefinder* @ericsnowcurrently @FFY00 **/*moduleobject* @ericsnowcurrently **/*multiphase* @ericsnowcurrently -**/*pkgutil* @ericsnowcurrently +**/*pkgutil* @ericsnowcurrently @FFY00 **/*pythonrun* @ericsnowcurrently -**/*runpy* @ericsnowcurrently +**/*runpy* @ericsnowcurrently @FFY00 **/*singlephase* @ericsnowcurrently Doc/c-api/module.rst @ericsnowcurrently Lib/test/test_module/ @ericsnowcurrently -Python/dynload_*.c @ericsnowcurrently +Python/dynload_*.c @ericsnowcurrently @FFY00 # Initialisation -**/*initconfig* @ericsnowcurrently -**/*pathconfig* @ericsnowcurrently -**/*preconfig* @ericsnowcurrently +**/*initconfig* @ericsnowcurrently @FFY00 +**/*pathconfig* @ericsnowcurrently @FFY00 +**/*preconfig* @ericsnowcurrently @FFY00 Doc/library/sys_path_init.rst @FFY00 Doc/c-api/init_config.rst @FFY00 # Interpreter main program -Modules/main.c @ericsnowcurrently -Programs/_bootstrap_python.c @ericsnowcurrently -Programs/python.c @ericsnowcurrently +Modules/main.c @ericsnowcurrently @FFY00 +Programs/_bootstrap_python.c @ericsnowcurrently @FFY00 +Programs/python.c @ericsnowcurrently @FFY00 # JIT .github/workflows/jit.yml @savannahostrowski @@ -316,8 +316,8 @@ Tools/peg_generator/ @pablogsal @lysnikolaou # Runtime state/lifecycle **/*gil* @ericsnowcurrently -**/*pylifecycle* @ericsnowcurrently @ZeroIntensity -**/*pystate* @ericsnowcurrently @ZeroIntensity +**/*pylifecycle* @ericsnowcurrently @ZeroIntensity @FFY00 +**/*pystate* @ericsnowcurrently @ZeroIntensity @FFY00 Include/internal/pycore_*_init.h @ericsnowcurrently Include/internal/pycore_*_state.h @ericsnowcurrently Include/internal/pycore_atexit.h @ericsnowcurrently @@ -505,13 +505,13 @@ Lib/idlelib/ @terryjreedy Lib/turtledemo/ @terryjreedy # importlib.metadata -Doc/library/importlib.metadata.rst @jaraco @warsaw -Lib/importlib/metadata/ @jaraco @warsaw -Lib/test/test_importlib/metadata/ @jaraco @warsaw +Doc/library/importlib.metadata.rst @jaraco @warsaw @FFY00 +Lib/importlib/metadata/ @jaraco @warsaw @FFY00 +Lib/test/test_importlib/metadata/ @jaraco @warsaw @FFY00 # importlib.resources -Doc/library/importlib.resources.abc.rst @jaraco @warsaw -Doc/library/importlib.resources.rst @jaraco @warsaw +Doc/library/importlib.resources.abc.rst @jaraco @warsaw @FFY00 +Doc/library/importlib.resources.rst @jaraco @warsaw @FFY00 Lib/importlib/resources/ @jaraco @warsaw @FFY00 Lib/test/test_importlib/resources/ @jaraco @warsaw @FFY00 From bd13cc09faaef01635aea85130f33aa8cbb8b177 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 3 Mar 2026 07:23:30 -0800 Subject: [PATCH 027/196] gh-145376: Fix various reference leaks (GH-145377) --- .../2026-02-28-16-46-17.gh-issue-145376.lG5u1a.rst | 1 + Modules/main.c | 1 + Python/crossinterp.c | 1 + Python/import.c | 1 + Python/pythonrun.c | 1 + Python/sysmodule.c | 2 +- 6 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-16-46-17.gh-issue-145376.lG5u1a.rst 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 new file mode 100644 index 00000000000000..a5a6908757e458 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-16-46-17.gh-issue-145376.lG5u1a.rst @@ -0,0 +1 @@ +Fix reference leaks in various unusual error scenarios. diff --git a/Modules/main.c b/Modules/main.c index 74e48c94732565..95ba541d98c2e8 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -506,6 +506,7 @@ pymain_run_interactive_hook(int *exitcode) } if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) { + Py_DECREF(hook); goto error; } diff --git a/Python/crossinterp.c b/Python/crossinterp.c index 6365b995a0d3f7..c8a80e7a986008 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -609,6 +609,7 @@ check_missing___main___attr(PyObject *exc) // Get the error message. PyObject *args = PyException_GetArgs(exc); if (args == NULL || args == Py_None || PyObject_Size(args) < 1) { + Py_XDECREF(args); assert(!PyErr_Occurred()); return 0; } diff --git a/Python/import.c b/Python/import.c index dfc4d5707bfdba..3ed808f67f4149 100644 --- a/Python/import.c +++ b/Python/import.c @@ -5642,6 +5642,7 @@ _imp__set_lazy_attributes_impl(PyObject *module, PyObject *modobj, module_dict = get_mod_dict(modobj); if (module_dict == NULL || !PyDict_CheckExact(module_dict)) { + Py_DECREF(lazy_submodules); goto done; } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index ec8c2d12ab27fc..043bdf3433ab57 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1145,6 +1145,7 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) "traceback", "_print_exception_bltin"); if (print_exception_fn == NULL || !PyCallable_Check(print_exception_fn)) { + Py_XDECREF(print_exception_fn); goto fallback; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 28b2108940c853..55b4072213d3c2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1762,7 +1762,7 @@ sys_getwindowsversion_impl(PyObject *module) PyObject *realVersion = _sys_getwindowsversion_from_kernel32(); if (!realVersion) { if (!PyErr_ExceptionMatches(PyExc_WindowsError)) { - return NULL; + goto error; } PyErr_Clear(); From 34df70c83c0055b204fcb10f7e63dbab6d7ecdbb Mon Sep 17 00:00:00 2001 From: Victorien <65306057+Viicos@users.noreply.github.com> Date: Tue, 3 Mar 2026 16:05:14 +0000 Subject: [PATCH 028/196] Reference `memoryview.tolist` as a method (#145412) --- 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 4451d485884987..76a4367dd2dcd5 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4536,7 +4536,7 @@ copying. types such as :class:`bytes` and :class:`bytearray`, an element is a single byte, but other types such as :class:`array.array` may have bigger elements. - ``len(view)`` is equal to the length of :class:`~memoryview.tolist`, which + ``len(view)`` is equal to the length of :meth:`~memoryview.tolist`, which is the nested list representation of the view. If ``view.ndim = 1``, this is equal to the number of elements in the view. From e6c3c04fab43057baf70b4f24b57a4679d646d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Tue, 3 Mar 2026 17:14:12 +0100 Subject: [PATCH 029/196] gh-145452: Initialize `PyLazyImport_Type` during interpreter startup (#145453) Co-authored-by: Victor Stinner --- Lib/test/test_lazy_import/__init__.py | 11 +++++++++++ Objects/object.c | 2 ++ 2 files changed, 13 insertions(+) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 5d30ec2299789b..a4180f05dbbafc 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -12,6 +12,7 @@ import os from test import support +from test.support.script_helper import assert_python_ok try: import _testcapi @@ -219,6 +220,16 @@ def test_lazy_import_type_cant_construct(self): """LazyImportType should not be directly constructible.""" self.assertRaises(TypeError, types.LazyImportType, {}, "module") + @support.requires_subprocess() + def test_lazy_import_type_attributes_accessible(self): + """Check that static PyLazyImport_Type is initialized at startup.""" + code = textwrap.dedent(""" + lazy import json + print(globals()["json"].resolve) + """) + proc = assert_python_ok("-c", code) + self.assertIn(b" Date: Wed, 4 Mar 2026 02:48:03 +0800 Subject: [PATCH 030/196] gh-135883: Fix sqlite3 CLI history scrolling with colored prompts (#135884) --- Lib/sqlite3/__main__.py | 7 +++++-- Lib/test/test_sqlite3/test_cli.py | 12 ++++++++---- .../2025-06-24-19-07-18.gh-issue-135883.38cePA.rst | 2 ++ 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-06-24-19-07-18.gh-issue-135883.38cePA.rst diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index b3746ed757332f..8805442b69e080 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -133,8 +133,11 @@ def main(*args): theme = get_theme() s = theme.syntax - sys.ps1 = f"{s.prompt}sqlite> {s.reset}" - sys.ps2 = f"{s.prompt} ... {s.reset}" + # Use RL_PROMPT_START_IGNORE (\001) and RL_PROMPT_END_IGNORE (\002) to + # bracket non-printing characters. This tells readline to ignore them + # when calculating screen space for redisplay during history scrolling. + sys.ps1 = f"\001{s.prompt}\002sqlite> \001{s.reset}\002" + sys.ps2 = f"\001{s.prompt}\002 ... \001{s.reset}\002" con = sqlite3.connect(args.filename, isolation_level=None) try: diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 98aadaa829a969..1fc0236780fa8b 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -80,8 +80,8 @@ def test_cli_on_disk_db(self): @force_not_colorized_test_class class InteractiveSession(unittest.TestCase): MEMORY_DB_MSG = "Connected to a transient in-memory database" - PS1 = "sqlite> " - PS2 = "... " + PS1 = "\001\002sqlite> \001\002" + PS2 = "\001\002 ... \001\002" def run_cli(self, *args, commands=()): with ( @@ -202,8 +202,8 @@ def test_interact_on_disk_file(self): def test_color(self): with unittest.mock.patch("_colorize.can_colorize", return_value=True): out, err = self.run_cli(commands="TEXT\n") - self.assertIn("\x1b[1;35msqlite> \x1b[0m", out) - self.assertIn("\x1b[1;35m ... \x1b[0m\x1b", out) + self.assertIn("\x01\x1b[1;35m\x02sqlite> \x01\x1b[0m\x02", out) + self.assertIn("\x01\x1b[1;35m\x02 ... \x01\x1b[0m\x02\x01\x1b", out) out, err = self.run_cli(commands=("sel;",)) self.assertIn('\x1b[1;35mOperationalError (SQLITE_ERROR)\x1b[0m: ' '\x1b[35mnear "sel": syntax error\x1b[0m', err) @@ -212,6 +212,10 @@ def test_color(self): @requires_subprocess() @force_not_colorized_test_class class Completion(unittest.TestCase): + # run_pty() creates a real terminal environment, where sqlite3 CLI + # SqliteInteractiveConsole invokes GNU Readline for input. Readline's + # _rl_strip_prompt() strips \001 and \002 from the output, so test + # assertions use the plain prompt. PS1 = "sqlite> " @classmethod 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 new file mode 100644 index 00000000000000..8f3efceaae1d91 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-06-24-19-07-18.gh-issue-135883.38cePA.rst @@ -0,0 +1,2 @@ +Fix :mod:`sqlite3`'s :ref:`interactive shell ` keeping part of +previous commands when scrolling history. From 15f6479c415cc6cd219cd25c1d94bab17d720cbc Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Tue, 3 Mar 2026 15:48:43 -0500 Subject: [PATCH 031/196] Docs: use a Sphinx extension to eliminate excessive links (#145130) --- Doc/conf.py | 1 + Doc/requirements.txt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Doc/conf.py b/Doc/conf.py index d7effe2572ec44..545049bb460419 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -43,6 +43,7 @@ # Skip if downstream redistributors haven't installed them _OPTIONAL_EXTENSIONS = ( + 'linklint.ext', 'notfound.extension', 'sphinxext.opengraph', ) diff --git a/Doc/requirements.txt b/Doc/requirements.txt index d0107744ecbe85..536ae57e4efc29 100644 --- a/Doc/requirements.txt +++ b/Doc/requirements.txt @@ -18,4 +18,6 @@ sphinx-notfound-page~=1.0.0 # to install that as well. python-docs-theme>=2023.3.1,!=2023.7 +linklint + -c constraints.txt From dc12d1999b88e84d5a6b8e491be468b73379e54b Mon Sep 17 00:00:00 2001 From: Justin Kunimune Date: Tue, 3 Mar 2026 16:41:26 -0500 Subject: [PATCH 032/196] Fix incorrect statement about argparse.ArgumentParser.add_argument() (#145479) Co-authored-by: Savannah Ostrowski --- Doc/library/argparse.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index ca4f439c345f32..8f31e815e0eb4b 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -739,9 +739,9 @@ By default, :mod:`!argparse` automatically handles the internal naming and display names of arguments, simplifying the process without requiring additional configuration. As such, you do not need to specify the dest_ and metavar_ parameters. -The dest_ parameter defaults to the argument name with underscores ``_`` -replacing hyphens ``-`` . The metavar_ parameter defaults to the -upper-cased name. For example:: +For optional arguments, the dest_ parameter defaults to the argument name, with +underscores ``_`` replacing hyphens ``-``. The metavar_ parameter defaults to +the upper-cased name. For example:: >>> parser = argparse.ArgumentParser(prog='PROG') >>> parser.add_argument('--foo-bar') From 31343cf2bc5f7209fa965558265555973323c2f9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 4 Mar 2026 11:00:08 +0100 Subject: [PATCH 033/196] gh-142417: Restore private _Py_InitializeMain() function (#145472) This reverts commit 07c3518ffb27875b14a0f1637aa85f773ff2f9ff. Co-authored-by: Petr Viktorin --- Doc/c-api/init_config.rst | 94 +++++++++++++++++-- Doc/whatsnew/3.15.rst | 4 + Include/cpython/pylifecycle.h | 3 + Lib/test/test_embed.py | 18 ++++ ...-03-03-14-59-57.gh-issue-142417.HiNP5j.rst | 2 + Programs/_testembed.c | 28 ++++++ Python/pylifecycle.c | 12 +++ 7 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-03-03-14-59-57.gh-issue-142417.HiNP5j.rst diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index a143274bfe69e2..f6dc604a609cb1 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -2299,13 +2299,91 @@ Py_GetArgcArgv() See also :c:member:`PyConfig.orig_argv` member. -Delaying main module execution -============================== -In some embedding use cases, it may be desirable to separate interpreter initialization -from the execution of the main module. +Multi-Phase Initialization Private Provisional API +================================================== -This separation can be achieved by setting ``PyConfig.run_command`` to the empty -string during initialization (to prevent the interpreter from dropping into the -interactive prompt), and then subsequently executing the desired main module -code using ``__main__.__dict__`` as the global namespace. +This section is a private provisional API introducing multi-phase +initialization, the core feature of :pep:`432`: + +* "Core" initialization phase, "bare minimum Python": + + * Builtin types; + * Builtin exceptions; + * Builtin and frozen modules; + * The :mod:`sys` module is only partially initialized + (ex: :data:`sys.path` doesn't exist yet). + +* "Main" initialization phase, Python is fully initialized: + + * Install and configure :mod:`importlib`; + * Apply the :ref:`Path Configuration `; + * Install signal handlers; + * Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout` + and :data:`sys.path`); + * Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`; + * Import the :mod:`site` module; + * etc. + +Private provisional API: + +.. c:member:: int PyConfig._init_main + + If set to ``0``, :c:func:`Py_InitializeFromConfig` stops at the "Core" + initialization phase. + +.. c:function:: PyStatus _Py_InitializeMain(void) + + Move to the "Main" initialization phase, finish the Python initialization. + +No module is imported during the "Core" phase and the ``importlib`` module is +not configured: the :ref:`Path Configuration ` is only +applied during the "Main" phase. It may allow to customize Python in Python to +override or tune the :ref:`Path Configuration `, maybe +install a custom :data:`sys.meta_path` importer or an import hook, etc. + +It may become possible to calculate the :ref:`Path Configuration +` in Python, after the Core phase and before the Main phase, +which is one of the :pep:`432` motivation. + +The "Core" phase is not properly defined: what should be and what should +not be available at this phase is not specified yet. The API is marked +as private and provisional: the API can be modified or even be removed +anytime until a proper public API is designed. + +Example running Python code between "Core" and "Main" initialization +phases:: + + void init_python(void) + { + PyStatus status; + + PyConfig config; + PyConfig_InitPythonConfig(&config); + config._init_main = 0; + + /* ... customize 'config' configuration ... */ + + status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + + /* Use sys.stderr because sys.stdout is only created + by _Py_InitializeMain() */ + int res = PyRun_SimpleString( + "import sys; " + "print('Run Python code before _Py_InitializeMain', " + "file=sys.stderr)"); + if (res < 0) { + exit(1); + } + + /* ... put more configuration code here ... */ + + status = _Py_InitializeMain(); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + } diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 63ef5f84301794..fff2168be72604 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1664,6 +1664,10 @@ New features * Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as :term:`immortal`. (Contributed by Kumar Aditya in :gh:`143300`.) +* Restore private provisional ``_Py_InitializeMain()`` function removed in + Python 3.14. + (Contributed by Victor Stinner in :gh:`142417`.) + Changed C APIs -------------- diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index 86ce6e6f79824a..e46dfe59ec4630 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -25,6 +25,9 @@ PyAPI_FUNC(PyStatus) Py_PreInitializeFromArgs( PyAPI_FUNC(PyStatus) Py_InitializeFromConfig( const PyConfig *config); +// Python 3.8 provisional API (PEP 587) +PyAPI_FUNC(PyStatus) _Py_InitializeMain(void); + PyAPI_FUNC(int) Py_RunMain(void); diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index b3f0cb5d35de5d..45d0d8308dbdea 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1319,6 +1319,24 @@ def test_init_run_main(self): } self.check_all_configs("test_init_run_main", config, api=API_PYTHON) + def test_init_main(self): + code = ('import _testinternalcapi, json; ' + 'print(json.dumps(_testinternalcapi.get_configs()))') + config = { + 'argv': ['-c', 'arg2'], + 'orig_argv': ['python3', + '-c', code, + 'arg2'], + 'program_name': './python3', + 'run_command': code + '\n', + 'parse_argv': True, + '_init_main': False, + 'sys_path_0': '', + } + self.check_all_configs("test_init_main", config, + api=API_PYTHON, + stderr="Run Python code before _Py_InitializeMain") + def test_init_parse_argv(self): config = { 'parse_argv': True, 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 new file mode 100644 index 00000000000000..943be5b4533d9e --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-03-03-14-59-57.gh-issue-142417.HiNP5j.rst @@ -0,0 +1,2 @@ +Restore private provisional ``_Py_InitializeMain()`` function removed in +Python 3.14. Patch by Victor Stinner. diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 38f546b976cac3..d4d2a7131ccb1f 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1991,6 +1991,33 @@ static int test_init_run_main(void) } +static int test_init_main(void) +{ + PyConfig config; + PyConfig_InitPythonConfig(&config); + + configure_init_main(&config); + config._init_main = 0; + init_from_config_clear(&config); + + /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */ + int res = PyRun_SimpleString( + "import sys; " + "print('Run Python code before _Py_InitializeMain', " + "file=sys.stderr)"); + if (res < 0) { + exit(1); + } + + PyStatus status = _Py_InitializeMain(); + if (PyStatus_Exception(status)) { + Py_ExitStatusException(status); + } + + return Py_RunMain(); +} + + static int test_run_main(void) { PyConfig config; @@ -2649,6 +2676,7 @@ static struct TestCase TestCases[] = { {"test_preinit_parse_argv", test_preinit_parse_argv}, {"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv}, {"test_init_run_main", test_init_run_main}, + {"test_init_main", test_init_main}, {"test_init_sys_add", test_init_sys_add}, {"test_init_setpath", test_init_setpath}, {"test_init_setpath_config", test_init_setpath_config}, diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 7dfeb5b847b254..711e7bc89b71c0 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1530,6 +1530,18 @@ Py_Initialize(void) } +PyStatus +_Py_InitializeMain(void) +{ + PyStatus status = _PyRuntime_Initialize(); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + PyThreadState *tstate = _PyThreadState_GET(); + return pyinit_main(tstate); +} + + static void finalize_modules_delete_special(PyThreadState *tstate, int verbose) { From 45e9343d7eed1d9e784e731cc9af853fa8649e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 4 Mar 2026 13:59:50 +0100 Subject: [PATCH 034/196] GH-144739: Skip test_pyexpat.MemoryProtectionTest based on expat compile-time version, not runtime (#144740) --- Lib/test/test_pyexpat.py | 4 +++- .../next/Tests/2026-02-12-12-12-00.gh-issue-144739.-fx1tN.rst | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Tests/2026-02-12-12-12-00.gh-issue-144739.-fx1tN.rst diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 74a75458289b4d..31bcee293b2b69 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -1069,7 +1069,9 @@ def test_set_maximum_amplification__amplification_not_exceeded(self): self.assertIsNotNone(parser.Parse(payload, True)) -@unittest.skipIf(expat.version_info < (2, 7, 2), "requires Expat >= 2.7.2") +@unittest.skipIf(not hasattr(expat.XMLParserType, + "SetAllocTrackerMaximumAmplification"), + "requires Python compiled with Expat >= 2.7.2") class MemoryProtectionTest(AttackProtectionTestBase, unittest.TestCase): # NOTE: with the default Expat configuration, the billion laughs protection 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 new file mode 100644 index 00000000000000..8c46ff133f9433 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2026-02-12-12-12-00.gh-issue-144739.-fx1tN.rst @@ -0,0 +1,3 @@ +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`. From 3fe7849d9a50075901195602bb7143b93537289a Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 4 Mar 2026 14:21:10 +0100 Subject: [PATCH 035/196] gh-145376: Fix refleak in error path of time_tzset (GH-145477) --- Modules/timemodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 3946d18479e253..a3260e0f15ab99 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1170,7 +1170,8 @@ time_tzset(PyObject *self, PyObject *unused) /* Reset timezone, altzone, daylight and tzname */ if (init_timezone(m) < 0) { - return NULL; + Py_DECREF(m); + return NULL; } Py_DECREF(m); if (PyErr_Occurred()) From f9dac4e2ebbb913479bf882f0ac582040ba54ea3 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 4 Mar 2026 14:32:14 +0100 Subject: [PATCH 036/196] gh-145376: Avoid reference leaks in failure path of _functoolsmodule.c method partial_new (GH-145423) --- Modules/_functoolsmodule.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 5286be0b715fff..336a2e57ec0179 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -252,6 +252,11 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) } PyObject *item; PyObject *tot_args = PyTuple_New(tot_nargs); + if (tot_args == NULL) { + Py_DECREF(new_args); + Py_DECREF(pto); + return NULL; + } for (Py_ssize_t i = 0, j = 0; i < tot_nargs; i++) { if (i < npargs) { item = PyTuple_GET_ITEM(pto_args, i); From 18aec59fe5bbae9225951ca4d69bfca17eba82d8 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 4 Mar 2026 14:34:24 +0100 Subject: [PATCH 037/196] gh-145376: Fix refleak in unusual error path in BaseExceptionGroup_new (GH-145474) --- Objects/exceptions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 499fb2b34b34a8..f5edc286243ee1 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -912,7 +912,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) exceptions = PySequence_Tuple(exceptions); if (!exceptions) { - return NULL; + goto error; } /* We are now holding a ref to the exceptions tuple */ From a00392349c8cccdf2fe720fe46e504699f584f02 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 4 Mar 2026 18:29:02 +0100 Subject: [PATCH 038/196] gh-144741: Fix test_frame_pointer_unwind for libpython (#145499) Fix test_frame_pointer_unwind when Python is built with --enable-shared. Classify also libpython frames as "python". --- .../next/Tests/2026-03-04-17-39-15.gh-issue-144741.0RHhBF.rst | 3 +++ Modules/_testinternalcapi.c | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Tests/2026-03-04-17-39-15.gh-issue-144741.0RHhBF.rst 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 new file mode 100644 index 00000000000000..be3092f1c2592a --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2026-03-04-17-39-15.gh-issue-144741.0RHhBF.rst @@ -0,0 +1,3 @@ +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/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 22cfa3f58a9d83..998bf5e592e8ee 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -196,6 +196,10 @@ classify_address(uintptr_t addr, int jit_enabled, PyInterpreterState *interp) if (strncmp(base, "python", 6) == 0) { return "python"; } + // Match "libpython3.15.so.1.0" + if (strncmp(base, "libpython", 9) == 0) { + return "python"; + } return "other"; } #ifdef _Py_JIT From 6cdbd7bc5d4ee63459d03a944477ea8671a05198 Mon Sep 17 00:00:00 2001 From: Itamar Oren Date: Wed, 4 Mar 2026 10:06:49 -0800 Subject: [PATCH 039/196] gh-122941: Fix test_launcher sporadic failures via py.ini isolation (GH-145090) Adds _PYLAUNCHER_INIDIR as a private variable since the launcher is deprecated and not getting new features. --- Lib/test/test_launcher.py | 17 ++++++++++++----- PC/launcher2.c | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index caa1603c78eb01..c522bc1c2c093c 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -227,6 +227,8 @@ def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=Non "PYLAUNCHER_LIMIT_TO_COMPANY": "", **{k.upper(): v for k, v in (env or {}).items()}, } + if ini_dir := getattr(self, '_ini_dir', None): + env.setdefault("_PYLAUNCHER_INIDIR", ini_dir) if not argv: argv = [self.py_exe, *args] with subprocess.Popen( @@ -262,11 +264,14 @@ def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=Non return data def py_ini(self, content): - local_appdata = os.environ.get("LOCALAPPDATA") - if not local_appdata: - raise unittest.SkipTest("LOCALAPPDATA environment variable is " - "missing or empty") - return PreservePyIni(Path(local_appdata) / "py.ini", content) + ini_dir = getattr(self, '_ini_dir', None) + if not ini_dir: + local_appdata = os.environ.get("LOCALAPPDATA") + if not local_appdata: + raise unittest.SkipTest("LOCALAPPDATA environment variable is " + "missing or empty") + ini_dir = local_appdata + return PreservePyIni(Path(ini_dir) / "py.ini", content) @contextlib.contextmanager def script(self, content, encoding="utf-8"): @@ -302,6 +307,8 @@ def setUpClass(cls): p = subprocess.check_output("reg query HKCU\\Software\\Python /s") #print(p.decode('mbcs')) + cls._ini_dir = tempfile.mkdtemp() + cls.addClassCleanup(shutil.rmtree, cls._ini_dir, ignore_errors=True) @classmethod def tearDownClass(cls): diff --git a/PC/launcher2.c b/PC/launcher2.c index 832935c5cc6c1c..4dd18c8eb5462e 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -922,6 +922,20 @@ _readIni(const wchar_t *section, const wchar_t *settingName, wchar_t *buffer, in { wchar_t iniPath[MAXLEN]; int n; + // Check for _PYLAUNCHER_INIDIR override (used for test isolation) + DWORD len = GetEnvironmentVariableW(L"_PYLAUNCHER_INIDIR", iniPath, MAXLEN); + if (len && len < MAXLEN) { + if (join(iniPath, MAXLEN, L"py.ini")) { + debug(L"# Reading from %s for %s/%s\n", iniPath, section, settingName); + n = GetPrivateProfileStringW(section, settingName, NULL, buffer, bufferLength, iniPath); + if (n) { + debug(L"# Found %s in %s\n", settingName, iniPath); + return n; + } + } + // When _PYLAUNCHER_INIDIR is set, skip the default locations + return 0; + } if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, iniPath)) && join(iniPath, MAXLEN, L"py.ini")) { debug(L"# Reading from %s for %s/%s\n", iniPath, section, settingName); From 8a7eb8b2ab2d9bf20f2fdc77177f735331fa9a72 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Wed, 4 Mar 2026 13:32:43 -0500 Subject: [PATCH 040/196] gh-145500: Delete _PyType_GetMRO (gh-145501) --- Include/internal/pycore_typeobject.h | 1 - Objects/typeobject.c | 22 ---------------------- 2 files changed, 23 deletions(-) diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index 8af317d54c0bda..9c8b00550e3980 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -96,7 +96,6 @@ PyAPI_FUNC(PyObject *) _PyType_LookupSubclasses(PyTypeObject *); PyAPI_FUNC(PyObject *) _PyType_InitSubclasses(PyTypeObject *); extern PyObject * _PyType_GetBases(PyTypeObject *type); -extern PyObject * _PyType_GetMRO(PyTypeObject *type); extern PyObject* _PyType_GetSubclasses(PyTypeObject *); extern int _PyType_HasSubclasses(PyTypeObject *); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index d77d981085f4da..c5e94a8668fef2 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -651,28 +651,6 @@ lookup_tp_mro(PyTypeObject *self) return self->tp_mro; } -PyObject * -_PyType_GetMRO(PyTypeObject *self) -{ -#ifdef Py_GIL_DISABLED - PyObject *mro = _Py_atomic_load_ptr_relaxed(&self->tp_mro); - if (mro == NULL) { - return NULL; - } - if (_Py_TryIncrefCompare(&self->tp_mro, mro)) { - return mro; - } - - BEGIN_TYPE_LOCK(); - mro = lookup_tp_mro(self); - Py_XINCREF(mro); - END_TYPE_LOCK(); - return mro; -#else - return Py_XNewRef(lookup_tp_mro(self)); -#endif -} - static inline void set_tp_mro(PyTypeObject *self, PyObject *mro, int initial) { From 95f56b120623f17990be81379661de270e95e3c5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 4 Mar 2026 20:11:00 +0100 Subject: [PATCH 041/196] gh-141510: Return frozendict unmodified in PyDict_Copy() (#145505) Add also the internal _PyDict_CopyAsDict() function. --- Include/internal/pycore_dict.h | 2 ++ Lib/test/test_capi/test_dict.py | 16 +++++++---- Objects/dictobject.c | 50 +++++++++++++++++++++++---------- Objects/typeobject.c | 18 ++---------- 4 files changed, 50 insertions(+), 36 deletions(-) diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 59e88be6aeec12..1aeec32f55a7f3 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -160,6 +160,8 @@ extern void _PyDict_Clear_LockHeld(PyObject *op); PyAPI_FUNC(void) _PyDict_EnsureSharedOnRead(PyDictObject *mp); #endif +extern PyObject* _PyDict_CopyAsDict(PyObject *op); + #define DKIX_EMPTY (-1) #define DKIX_DUMMY (-2) /* Used internally */ #define DKIX_ERROR (-3) diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py index d9de9bb4c8125d..561e1ea4d52846 100644 --- a/Lib/test/test_capi/test_dict.py +++ b/Lib/test/test_capi/test_dict.py @@ -98,14 +98,18 @@ def test_dict_copy(self): # Test PyDict_Copy() copy = _testlimitedcapi.dict_copy for dict_type in ANYDICT_TYPES: - if issubclass(dict_type, frozendict): - expected_type = frozendict - else: - expected_type = dict dct = dict_type({1: 2}) dct_copy = copy(dct) - self.assertIs(type(dct_copy), expected_type) - self.assertEqual(dct_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) for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES: self.assertRaises(SystemError, copy, test_type()) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 5894fdb614ebdc..0f123c3c2bb994 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4235,9 +4235,6 @@ static PyObject * dict_copy_impl(PyDictObject *self) /*[clinic end generated code: output=ffb782cf970a5c39 input=73935f042b639de4]*/ { - if (PyFrozenDict_CheckExact(self)) { - return Py_NewRef(self); - } return PyDict_Copy((PyObject *)self); } @@ -4263,18 +4260,17 @@ copy_values(PyDictValues *values) } static PyObject * -copy_lock_held(PyObject *o) +copy_lock_held(PyObject *o, int as_frozendict) { PyObject *copy; PyDictObject *mp; - int frozendict = PyFrozenDict_Check(o); ASSERT_DICT_LOCKED(o); mp = (PyDictObject *)o; if (mp->ma_used == 0) { /* The dict is empty; just return a new dict. */ - if (frozendict) { + if (as_frozendict) { return PyFrozenDict_New(NULL); } else { @@ -4288,7 +4284,7 @@ copy_lock_held(PyObject *o) if (newvalues == NULL) { return PyErr_NoMemory(); } - if (frozendict) { + if (as_frozendict) { split_copy = (PyDictObject *)PyObject_GC_New(PyFrozenDictObject, &PyFrozenDict_Type); } @@ -4307,7 +4303,7 @@ copy_lock_held(PyObject *o) split_copy->ma_used = mp->ma_used; split_copy->_ma_watcher_tag = 0; dictkeys_incref(mp->ma_keys); - if (frozendict) { + if (as_frozendict) { PyFrozenDictObject *frozen = (PyFrozenDictObject *)split_copy; frozen->ma_hash = -1; } @@ -4318,7 +4314,7 @@ copy_lock_held(PyObject *o) if (Py_TYPE(mp)->tp_iter == dict_iter && mp->ma_values == NULL && (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3) && - !frozendict) + !as_frozendict) { /* Use fast-copy if: @@ -4350,7 +4346,7 @@ copy_lock_held(PyObject *o) return (PyObject *)new; } - if (frozendict) { + if (as_frozendict) { copy = PyFrozenDict_New(NULL); } else { @@ -4364,6 +4360,19 @@ copy_lock_held(PyObject *o) return NULL; } +// Similar to PyDict_Copy(), but copy also frozendict. +static PyObject * +_PyDict_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(); + return res; +} + PyObject * PyDict_Copy(PyObject *o) { @@ -4372,11 +4381,22 @@ PyDict_Copy(PyObject *o) return NULL; } - PyObject *res; - Py_BEGIN_CRITICAL_SECTION(o); + if (PyFrozenDict_CheckExact(o)) { + return Py_NewRef(o); + } + + return _PyDict_Copy(o); +} - res = copy_lock_held(o); +// Similar to PyDict_Copy(), but return a dict if the argument is a frozendict. +PyObject* +_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(); return res; } @@ -4925,7 +4945,7 @@ dict_or(PyObject *self, PyObject *other) if (!PyAnyDict_Check(self) || !PyAnyDict_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } - PyObject *new = PyDict_Copy(self); + PyObject *new = _PyDict_Copy(self); if (new == NULL) { return NULL; } @@ -6479,7 +6499,7 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2) ASSERT_DICT_LOCKED(d1); ASSERT_DICT_LOCKED(d2); - PyObject *temp_dict = copy_lock_held(d1); + PyObject *temp_dict = copy_lock_held(d1, PyFrozenDict_Check(d1)); if (temp_dict == NULL) { return NULL; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c5e94a8668fef2..1fdd3cbdaaa639 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4850,21 +4850,9 @@ type_new_get_slots(type_new_ctx *ctx, PyObject *dict) static PyTypeObject* type_new_init(type_new_ctx *ctx) { - PyObject *dict; - if (PyFrozenDict_Check(ctx->orig_dict)) { - dict = PyDict_New(); - if (dict == NULL) { - goto error; - } - if (PyDict_Merge(dict, ctx->orig_dict, 1) < 0) { - goto error; - } - } - else { - dict = PyDict_Copy(ctx->orig_dict); - if (dict == NULL) { - goto error; - } + PyObject *dict = _PyDict_CopyAsDict(ctx->orig_dict); + if (dict == NULL) { + goto error; } if (type_new_get_slots(ctx, dict) < 0) { From 0a51113a4901502e1e14c892e4c31768a14faa60 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 4 Mar 2026 20:49:20 +0100 Subject: [PATCH 042/196] gh-141510: Optimize PyDict_Copy() for frozendict (#145509) Implement fast-path for frozendict in PyDict_Copy(). --- Objects/dictobject.c | 58 +++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 0f123c3c2bb994..2552216152f98d 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -896,24 +896,20 @@ free_values(PyDictValues *values, bool use_qsbr) PyMem_Free(values); } -/* Consumes a reference to the keys object */ -static PyObject * -new_dict(PyDictKeysObject *keys, PyDictValues *values, - Py_ssize_t used, int free_values_on_failure) +static inline PyObject * +new_dict_impl(PyDictObject *mp, PyDictKeysObject *keys, + PyDictValues *values, Py_ssize_t used, + int free_values_on_failure) { assert(keys != NULL); - PyDictObject *mp = _Py_FREELIST_POP(PyDictObject, dicts); if (mp == NULL) { - mp = PyObject_GC_New(PyDictObject, &PyDict_Type); - if (mp == NULL) { - dictkeys_decref(keys, false); - if (free_values_on_failure) { - free_values(values, false); - } - return NULL; + dictkeys_decref(keys, false); + if (free_values_on_failure) { + free_values(values, false); } + return NULL; } - assert(Py_IS_TYPE(mp, &PyDict_Type)); + mp->ma_keys = keys; mp->ma_values = values; mp->ma_used = used; @@ -923,6 +919,29 @@ new_dict(PyDictKeysObject *keys, PyDictValues *values, return (PyObject *)mp; } +/* Consumes a reference to the keys object */ +static PyObject * +new_dict(PyDictKeysObject *keys, PyDictValues *values, + Py_ssize_t used, int free_values_on_failure) +{ + PyDictObject *mp = _Py_FREELIST_POP(PyDictObject, dicts); + if (mp == NULL) { + mp = PyObject_GC_New(PyDictObject, &PyDict_Type); + } + assert(mp == NULL || Py_IS_TYPE(mp, &PyDict_Type)); + + return new_dict_impl(mp, keys, values, used, free_values_on_failure); +} + +/* Consumes a reference to the keys object */ +static PyObject * +new_frozendict(PyDictKeysObject *keys, PyDictValues *values, + Py_ssize_t used, int free_values_on_failure) +{ + PyDictObject *mp = PyObject_GC_New(PyDictObject, &PyFrozenDict_Type); + return new_dict_impl(mp, keys, values, used, free_values_on_failure); +} + static PyObject * new_dict_with_shared_keys(PyDictKeysObject *keys) { @@ -4313,8 +4332,7 @@ copy_lock_held(PyObject *o, int as_frozendict) if (Py_TYPE(mp)->tp_iter == dict_iter && mp->ma_values == NULL && - (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3) && - !as_frozendict) + (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3)) { /* Use fast-copy if: @@ -4334,9 +4352,15 @@ copy_lock_held(PyObject *o, int as_frozendict) if (keys == NULL) { return NULL; } - PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0); + PyDictObject *new; + if (as_frozendict) { + new = (PyDictObject *)new_frozendict(keys, NULL, 0, 0); + } + else { + new = (PyDictObject *)new_dict(keys, NULL, 0, 0); + } if (new == NULL) { - /* In case of an error, `new_dict()` takes care of + /* In case of an error, new_dict()/new_frozendict() takes care of cleaning up `keys`. */ return NULL; } From a51b1b512de1d56b3714b65628a2eae2b07e535e Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 4 Mar 2026 19:55:52 +0000 Subject: [PATCH 043/196] gh-145506: Fixes CVE-2026-2297 by ensuring SourcelessFileLoader uses io.open_code (GH-145507) --- Lib/importlib/_bootstrap_external.py | 2 +- .../Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 213190d2098e75..a1cb729efb7fef 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -918,7 +918,7 @@ def get_filename(self, fullname): def get_data(self, path): """Return the data from path as raw bytes.""" - if isinstance(self, (SourceLoader, ExtensionFileLoader)): + if isinstance(self, (SourceLoader, SourcelessFileLoader, ExtensionFileLoader)): with _io.open_code(str(path)) as file: return file.read() else: 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 new file mode 100644 index 00000000000000..dcdb44d4fae4e5 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst @@ -0,0 +1,2 @@ +Fixes :cve:`2026-2297` by ensuring that ``SourcelessFileLoader`` uses +:func:`io.open_code` when opening ``.pyc`` files. From ae208d5665453aca414d87fb1894bf0bbb677003 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Wed, 4 Mar 2026 20:43:44 +0000 Subject: [PATCH 044/196] Fix bugs in `compute-changes.py` logic for CIFuzz (#145232) --- Lib/test/test_tools/test_compute_changes.py | 24 +++++++++++---------- Tools/build/compute-changes.py | 8 ++++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_tools/test_compute_changes.py b/Lib/test/test_tools/test_compute_changes.py index b20ff975fc2834..c4e3ffdb4de6cf 100644 --- a/Lib/test/test_tools/test_compute_changes.py +++ b/Lib/test/test_tools/test_compute_changes.py @@ -6,7 +6,8 @@ from pathlib import Path from unittest.mock import patch -from test.test_tools import skip_if_missing, imports_under_tool +from test.support import os_helper +from test.test_tools import basepath, skip_if_missing, imports_under_tool skip_if_missing("build") @@ -15,6 +16,7 @@ compute_changes = importlib.import_module("compute-changes") process_changed_files = compute_changes.process_changed_files +is_fuzzable_library_file = compute_changes.is_fuzzable_library_file Outputs = compute_changes.Outputs ANDROID_DIRS = compute_changes.ANDROID_DIRS IOS_DIRS = compute_changes.IOS_DIRS @@ -45,16 +47,16 @@ def test_docs(self): self.assertFalse(result.run_tests) def test_ci_fuzz_stdlib(self): - for p in LIBRARY_FUZZER_PATHS: - with self.subTest(p=p): - if p.is_dir(): - f = p / "file" - elif p.is_file(): - f = p - else: - continue - result = process_changed_files({f}) - self.assertTrue(result.run_ci_fuzz_stdlib) + with os_helper.change_cwd(basepath): + for p in LIBRARY_FUZZER_PATHS: + with self.subTest(p=p): + if p.is_dir(): + f = p / "file" + elif p.is_file(): + f = p + result = process_changed_files({f}) + self.assertTrue(result.run_ci_fuzz_stdlib) + self.assertTrue(is_fuzzable_library_file(f)) def test_android(self): for d in ANDROID_DIRS: diff --git a/Tools/build/compute-changes.py b/Tools/build/compute-changes.py index 67d2b060969660..981e00e28b42a7 100644 --- a/Tools/build/compute-changes.py +++ b/Tools/build/compute-changes.py @@ -68,7 +68,8 @@ Path("Lib/encodings/"), Path("Modules/_codecsmodule.c"), Path("Modules/cjkcodecs/"), - Path("Modules/unicodedata*"), + Path("Modules/unicodedata.c"), + Path("Modules/unicodedata_db.h"), # difflib Path("Lib/difflib.py"), # email @@ -116,10 +117,10 @@ class Outputs: def compute_changes() -> None: - target_branch, head_ref = git_refs() + target_ref, head_ref = git_refs() if os.environ.get("GITHUB_EVENT_NAME", "") == "pull_request": # Getting changed files only makes sense on a pull request - files = get_changed_files(target_branch, head_ref) + files = get_changed_files(target_ref, head_ref) outputs = process_changed_files(files) else: # Otherwise, just run the tests @@ -132,6 +133,7 @@ def compute_changes() -> None: run_wasi=True, run_windows_tests=True, ) + target_branch = target_ref.removeprefix("origin/") outputs = process_target_branch(outputs, target_branch) if outputs.run_tests: From b63dc8abdf7b985bb23d212862baf29736888394 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 4 Mar 2026 13:27:23 -0800 Subject: [PATCH 045/196] Refactor `Platforms/WASI/__main__.py` for lazy importing and future new subcommands (#145404) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- .pre-commit-config.yaml | 8 + Platforms/WASI/.ruff.toml | 2 + Platforms/WASI/__main__.py | 463 ++++--------------------------------- Platforms/WASI/_build.py | 413 +++++++++++++++++++++++++++++++++ 4 files changed, 462 insertions(+), 424 deletions(-) create mode 100644 Platforms/WASI/_build.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1dcb50e31d9a68..4893ec28f23e5a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,10 @@ repos: name: Run Ruff (lint) on Lib/test/ args: [--exit-non-zero-on-fix] files: ^Lib/test/ + - id: ruff-check + name: Run Ruff (lint) on Platforms/WASI/ + args: [--exit-non-zero-on-fix, --config=Platforms/WASI/.ruff.toml] + files: ^Platforms/WASI/ - id: ruff-check name: Run Ruff (lint) on Tools/build/ args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml] @@ -42,6 +46,10 @@ repos: name: Run Ruff (format) on Doc/ args: [--exit-non-zero-on-fix] files: ^Doc/ + - id: ruff-format + name: Run Ruff (format) on Platforms/WASI/ + args: [--exit-non-zero-on-fix, --config=Platforms/WASI/.ruff.toml] + files: ^Platforms/WASI/ - id: ruff-format name: Run Ruff (format) on Tools/build/check_warnings.py args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml] diff --git a/Platforms/WASI/.ruff.toml b/Platforms/WASI/.ruff.toml index 3d8e59fa3f22c4..492713c1520000 100644 --- a/Platforms/WASI/.ruff.toml +++ b/Platforms/WASI/.ruff.toml @@ -1,5 +1,7 @@ extend = "../../.ruff.toml" # Inherit the project-wide settings +target-version = "py314" + [format] preview = true docstring-code-format = true diff --git a/Platforms/WASI/__main__.py b/Platforms/WASI/__main__.py index 471ac3297b2702..b8513a004f18e5 100644 --- a/Platforms/WASI/__main__.py +++ b/Platforms/WASI/__main__.py @@ -1,417 +1,23 @@ #!/usr/bin/env python3 +__lazy_modules__ = ["_build"] + import argparse -import contextlib -import functools import os - -import tomllib - -try: - from os import process_cpu_count as cpu_count -except ImportError: - from os import cpu_count import pathlib -import shutil -import subprocess -import sys -import sysconfig -import tempfile - -CHECKOUT = HERE = pathlib.Path(__file__).parent - -while CHECKOUT != CHECKOUT.parent: - if (CHECKOUT / "configure").is_file(): - break - CHECKOUT = CHECKOUT.parent -else: - raise FileNotFoundError( - "Unable to find the root of the CPython checkout by looking for 'configure'" - ) - -CROSS_BUILD_DIR = CHECKOUT / "cross-build" -# Build platform can also be found via `config.guess`. -BUILD_DIR = CROSS_BUILD_DIR / sysconfig.get_config_var("BUILD_GNU_TYPE") - -LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local" -LOCAL_SETUP_MARKER = ( - b"# Generated by Platforms/WASI .\n" - b"# Required to statically build extension modules." -) - -WASI_SDK_VERSION = 29 - -WASMTIME_VAR_NAME = "WASMTIME" -WASMTIME_HOST_RUNNER_VAR = f"{{{WASMTIME_VAR_NAME}}}" - - -def separator(): - """Print a separator line across the terminal width.""" - try: - tput_output = subprocess.check_output( - ["tput", "cols"], encoding="utf-8" - ) - except subprocess.CalledProcessError: - terminal_width = 80 - else: - terminal_width = int(tput_output.strip()) - print("⎯" * terminal_width) - - -def log(emoji, message, *, spacing=None): - """Print a notification with an emoji. - - If 'spacing' is None, calculate the spacing based on the number of code points - in the emoji as terminals "eat" a space when the emoji has multiple code points. - """ - if spacing is None: - spacing = " " if len(emoji) == 1 else " " - print("".join([emoji, spacing, message])) - - -def updated_env(updates={}): - """Create a new dict representing the environment to use. - - The changes made to the execution environment are printed out. - """ - env_defaults = {} - # https://reproducible-builds.org/docs/source-date-epoch/ - git_epoch_cmd = ["git", "log", "-1", "--pretty=%ct"] - try: - epoch = subprocess.check_output( - git_epoch_cmd, encoding="utf-8" - ).strip() - env_defaults["SOURCE_DATE_EPOCH"] = epoch - 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 - - env_diff = {} - for key, value in environment.items(): - if os.environ.get(key) != value: - env_diff[key] = value - - env_vars = ( - f"\n {key}={item}" for key, item in sorted(env_diff.items()) - ) - log("🌎", f"Environment changes:{''.join(env_vars)}") - - return environment - - -def subdir(working_dir, *, clean_ok=False): - """Decorator to change to a working directory.""" - - def decorator(func): - @functools.wraps(func) - def wrapper(context): - nonlocal working_dir - - if callable(working_dir): - working_dir = working_dir(context) - separator() - log("📁", os.fsdecode(working_dir)) - if ( - clean_ok - and getattr(context, "clean", False) - and working_dir.exists() - ): - log("🚮", "Deleting directory (--clean)...") - shutil.rmtree(working_dir) - - working_dir.mkdir(parents=True, exist_ok=True) - - with contextlib.chdir(working_dir): - return func(context, working_dir) - - return wrapper - - return decorator - - -def call(command, *, context=None, quiet=False, logdir=None, **kwargs): - """Execute a command. - - If 'quiet' is true, then redirect stdout and stderr to a temporary file. - """ - if context is not None: - quiet = context.quiet - logdir = context.logdir - elif quiet and logdir is None: - raise ValueError("When quiet is True, logdir must be specified") - - log("❯", " ".join(map(str, command)), spacing=" ") - if not quiet: - stdout = None - stderr = None - else: - stdout = tempfile.NamedTemporaryFile( - "w", - encoding="utf-8", - delete=False, - dir=logdir, - prefix="cpython-wasi-", - suffix=".log", - ) - stderr = subprocess.STDOUT - log("📝", f"Logging output to {stdout.name} (--quiet)...") - - subprocess.check_call(command, **kwargs, stdout=stdout, stderr=stderr) - - -def build_python_path(): - """The path to the build Python binary.""" - binary = 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 {BUILD_DIR}" - ) - - return binary - - -def build_python_is_pydebug(): - """Find out if the build Python is a pydebug build.""" - test = "import sys, test.support; sys.exit(test.support.Py_DEBUG)" - result = subprocess.run( - [build_python_path(), "-c", test], - capture_output=True, - ) - return bool(result.returncode) +import _build -@subdir(BUILD_DIR, clean_ok=True) -def configure_build_python(context, working_dir): - """Configure the build/host Python.""" - if LOCAL_SETUP.exists(): - if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: - log("👍", f"{LOCAL_SETUP} exists ...") - else: - log("⚠️", f"{LOCAL_SETUP} exists, but has unexpected contents") - else: - log("📝", f"Creating {LOCAL_SETUP} ...") - LOCAL_SETUP.write_bytes(LOCAL_SETUP_MARKER) - - configure = [os.path.relpath(CHECKOUT / "configure", working_dir)] - if context.args: - configure.extend(context.args) - - call(configure, context=context) - - -@subdir(BUILD_DIR) -def make_build_python(context, working_dir): - """Make/build the build Python.""" - call(["make", "--jobs", str(cpu_count()), "all"], context=context) - - binary = build_python_path() - cmd = [ - binary, - "-c", - "import sys; " - "print(f'{sys.version_info.major}.{sys.version_info.minor}')", - ] - version = subprocess.check_output(cmd, encoding="utf-8").strip() - - log("🎉", f"{binary} {version}") - - -def find_wasi_sdk(config): - """Find the path to the WASI SDK.""" - wasi_sdk_path = None - wasi_sdk_version = config["targets"]["wasi-sdk"] - - if wasi_sdk_path_env_var := os.environ.get("WASI_SDK_PATH"): - wasi_sdk_path = pathlib.Path(wasi_sdk_path_env_var) - else: - opt_path = pathlib.Path("/opt") - # WASI SDK versions have a ``.0`` suffix, but it's a constant; the WASI SDK team - # has said they don't plan to ever do a point release and all of their Git tags - # lack the ``.0`` suffix. - # Starting with WASI SDK 23, the tarballs went from containing a directory named - # ``wasi-sdk-{WASI_SDK_VERSION}.0`` to e.g. - # ``wasi-sdk-{WASI_SDK_VERSION}.0-x86_64-linux``. - potential_sdks = [ - path - for path in opt_path.glob(f"wasi-sdk-{wasi_sdk_version}.0*") - if path.is_dir() - ] - if len(potential_sdks) == 1: - wasi_sdk_path = potential_sdks[0] - elif (default_path := opt_path / "wasi-sdk").is_dir(): - wasi_sdk_path = default_path - - # Starting with WASI SDK 25, a VERSION file is included in the root - # of the SDK directory that we can read to warn folks when they are using - # an unsupported version. - if wasi_sdk_path and (version_file := wasi_sdk_path / "VERSION").is_file(): - version_details = version_file.read_text(encoding="utf-8") - found_version = version_details.splitlines()[0] - # Make sure there's a trailing dot to avoid false positives if somehow the - # supported version is a prefix of the found version (e.g. `25` and `2567`). - if not found_version.startswith(f"{wasi_sdk_version}."): - major_version = found_version.partition(".")[0] - log( - "⚠️", - f" Found WASI SDK {major_version}, " - f"but WASI SDK {wasi_sdk_version} is the supported version", - ) - - return wasi_sdk_path - - -def wasi_sdk_env(context): - """Calculate environment variables for building with wasi-sdk.""" - wasi_sdk_path = context.wasi_sdk_path - sysroot = wasi_sdk_path / "share" / "wasi-sysroot" - env = { - "CC": "clang", - "CPP": "clang-cpp", - "CXX": "clang++", - "AR": "llvm-ar", - "RANLIB": "ranlib", - } - - for env_var, binary_name in list(env.items()): - env[env_var] = os.fsdecode(wasi_sdk_path / "bin" / binary_name) - - if not wasi_sdk_path.name.startswith("wasi-sdk"): - for compiler in ["CC", "CPP", "CXX"]: - env[compiler] += f" --sysroot={sysroot}" - - env["PKG_CONFIG_PATH"] = "" - env["PKG_CONFIG_LIBDIR"] = os.pathsep.join( - map( - os.fsdecode, - [sysroot / "lib" / "pkgconfig", sysroot / "share" / "pkgconfig"], - ) - ) - env["PKG_CONFIG_SYSROOT_DIR"] = os.fsdecode(sysroot) - - env["WASI_SDK_PATH"] = os.fsdecode(wasi_sdk_path) - env["WASI_SYSROOT"] = os.fsdecode(sysroot) - - env["PATH"] = os.pathsep.join([ - os.fsdecode(wasi_sdk_path / "bin"), - os.environ["PATH"], - ]) - - return env - - -@subdir(lambda context: CROSS_BUILD_DIR / context.host_triple, clean_ok=True) -def configure_wasi_python(context, working_dir): - """Configure the WASI/host build.""" - if not context.wasi_sdk_path or not context.wasi_sdk_path.exists(): - raise ValueError( - "WASI-SDK not found; " - "download from " - "https://github.com/WebAssembly/wasi-sdk and/or " - "specify via $WASI_SDK_PATH or --wasi-sdk" - ) - - config_site = os.fsdecode(HERE / "config.site-wasm32-wasi") - - wasi_build_dir = working_dir.relative_to(CHECKOUT) - - args = { - "ARGV0": f"/{wasi_build_dir}/python.wasm", - "PYTHON_WASM": working_dir / "python.wasm", - } - # Check dynamically for wasmtime in case it was specified manually via - # `--host-runner`. - if WASMTIME_HOST_RUNNER_VAR in context.host_runner: - if wasmtime := shutil.which("wasmtime"): - args[WASMTIME_VAR_NAME] = wasmtime - else: - raise FileNotFoundError( - "wasmtime not found; download from " - "https://github.com/bytecodealliance/wasmtime" - ) - host_runner = context.host_runner.format_map(args) - env_additions = {"CONFIG_SITE": config_site, "HOSTRUNNER": host_runner} - build_python = os.fsdecode(build_python_path()) - # The path to `configure` MUST be relative, else `python.wasm` is unable - # to find the stdlib due to Python not recognizing that it's being - # executed from within a checkout. - configure = [ - os.path.relpath(CHECKOUT / "configure", working_dir), - f"--host={context.host_triple}", - f"--build={BUILD_DIR.name}", - f"--with-build-python={build_python}", - ] - if build_python_is_pydebug(): - configure.append("--with-pydebug") - if context.args: - configure.extend(context.args) - call( - configure, - env=updated_env(env_additions | wasi_sdk_env(context)), - context=context, - ) - - python_wasm = working_dir / "python.wasm" - exec_script = working_dir / "python.sh" - with exec_script.open("w", encoding="utf-8") as file: - file.write(f'#!/bin/sh\nexec {host_runner} {python_wasm} "$@"\n') - exec_script.chmod(0o755) - log("🏃", f"Created {exec_script} (--host-runner)... ") - sys.stdout.flush() - - -@subdir(lambda context: CROSS_BUILD_DIR / context.host_triple) -def make_wasi_python(context, working_dir): - """Run `make` for the WASI/host build.""" - call( - ["make", "--jobs", str(cpu_count()), "all"], - env=updated_env(), - context=context, - ) - - exec_script = working_dir / "python.sh" - call([exec_script, "--version"], quiet=False) - log( - "🎉", - f"Use `{exec_script.relative_to(context.init_dir)}` " - "to run CPython w/ the WASI host specified by --host-runner", - ) - - -def clean_contents(context): - """Delete all files created by this script.""" - if CROSS_BUILD_DIR.exists(): - log("🧹", f"Deleting {CROSS_BUILD_DIR} ...") - shutil.rmtree(CROSS_BUILD_DIR) - - if LOCAL_SETUP.exists(): - if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: - log("🧹", f"Deleting generated {LOCAL_SETUP} ...") - - -def build_steps(*steps): - """Construct a command from other steps.""" - - def builder(context): - for step in steps: - step(context) - - return builder +HERE = pathlib.Path(__file__).parent def main(): - with (HERE / "config.toml").open("rb") as file: - config = tomllib.load(file) - default_wasi_sdk = find_wasi_sdk(config) - default_host_triple = config["targets"]["host-triple"] default_host_runner = ( - f"{WASMTIME_HOST_RUNNER_VAR} run " - # Set argv0 so that getpath.py can auto-discover the sysconfig data directory + "{WASMTIME} run " + # Set argv0 so that getpath.py can auto-discover the sysconfig data directory. "--argv0 {ARGV0} " # Map the checkout to / to load the stdlib from /Lib. - f"--dir {os.fsdecode(CHECKOUT)}::/ " + "--dir {CHECKOUT}::/ " # Flags involving --optimize, --codegen, --debug, --wasm, and --wasi can be kept # in a config file. # We are using such a file to act as defaults in case a user wants to override @@ -419,9 +25,8 @@ def main(): # post-build so that they immediately apply to the Makefile instead of having to # regenerate it, and allow for easy copying of the settings for anyone else who # may want to use them. - f"--config {os.fsdecode(HERE / 'wasmtime.toml')}" + "--config {WASMTIME_CONFIG_PATH}" ) - default_logdir = pathlib.Path(tempfile.gettempdir()) parser = argparse.ArgumentParser() subcommands = parser.add_subparsers(dest="subcommand") @@ -470,8 +75,8 @@ def main(): subcommand.add_argument( "--logdir", type=pathlib.Path, - default=default_logdir, - help=f"Directory to store log files; defaults to {default_logdir}", + default=None, + help="Directory to store log files", ) for subcommand in ( configure_build, @@ -501,8 +106,9 @@ def main(): "--wasi-sdk", type=pathlib.Path, dest="wasi_sdk_path", - default=default_wasi_sdk, - help=f"Path to the WASI SDK; defaults to {default_wasi_sdk}", + default=None, + help="Path to the WASI SDK; defaults to WASI_SDK_PATH environment variable " + "or the appropriate version found in /opt", ) subcommand.add_argument( "--host-runner", @@ -516,28 +122,37 @@ def main(): subcommand.add_argument( "--host-triple", action="store", - default=default_host_triple, + default=None, help="The target triple for the WASI host build; " - f"defaults to {default_host_triple}", + f"defaults to the value found in {os.fsdecode(HERE / 'config.toml')}", ) context = parser.parse_args() - context.init_dir = pathlib.Path().absolute() - - build_build_python = build_steps(configure_build_python, make_build_python) - build_wasi_python = build_steps(configure_wasi_python, make_wasi_python) - dispatch = { - "configure-build-python": configure_build_python, - "make-build-python": make_build_python, - "build-python": build_build_python, - "configure-host": configure_wasi_python, - "make-host": make_wasi_python, - "build-host": build_wasi_python, - "build": build_steps(build_build_python, build_wasi_python), - "clean": clean_contents, - } - dispatch[context.subcommand](context) + match context.subcommand: + case "configure-build-python": + _build.configure_build_python(context) + case "make-build-python": + _build.make_build_python(context) + case "build-python": + _build.configure_build_python(context) + _build.make_build_python(context) + case "configure-host": + _build.configure_wasi_python(context) + case "make-host": + _build.make_wasi_python(context) + case "build-host": + _build.configure_wasi_python(context) + _build.make_wasi_python(context) + case "build": + _build.configure_build_python(context) + _build.make_build_python(context) + _build.configure_wasi_python(context) + _build.make_wasi_python(context) + case "clean": + _build.clean_contents(context) + case _: + raise ValueError(f"Unknown subcommand {context.subcommand!r}") if __name__ == "__main__": diff --git a/Platforms/WASI/_build.py b/Platforms/WASI/_build.py new file mode 100644 index 00000000000000..76d2853163baa9 --- /dev/null +++ b/Platforms/WASI/_build.py @@ -0,0 +1,413 @@ +#!/usr/bin/env python3 + +__lazy_modules__ = ["shutil", "sys", "tempfile", "tomllib"] + +import contextlib +import functools +import os +import pathlib +import shutil +import subprocess +import sys +import sysconfig +import tempfile +import tomllib + +try: + from os import process_cpu_count as cpu_count +except ImportError: + from os import cpu_count + + +CHECKOUT = HERE = pathlib.Path(__file__).parent + +while CHECKOUT != CHECKOUT.parent: + if (CHECKOUT / "configure").is_file(): + break + CHECKOUT = CHECKOUT.parent +else: + raise FileNotFoundError( + "Unable to find the root of the CPython checkout by looking for 'configure'" + ) + +CROSS_BUILD_DIR = CHECKOUT / "cross-build" +# Build platform can also be found via `config.guess`. +BUILD_DIR = CROSS_BUILD_DIR / sysconfig.get_config_var("BUILD_GNU_TYPE") + +LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local" +LOCAL_SETUP_MARKER = ( + b"# Generated by Platforms/WASI .\n" + b"# Required to statically build extension modules." +) + +WASMTIME_VAR_NAME = "WASMTIME" +WASMTIME_HOST_RUNNER_VAR = f"{{{WASMTIME_VAR_NAME}}}" + + +def separator(): + """Print a separator line across the terminal width.""" + try: + tput_output = subprocess.check_output( + ["tput", "cols"], encoding="utf-8" + ) + except subprocess.CalledProcessError: + terminal_width = 80 + else: + terminal_width = int(tput_output.strip()) + print("⎯" * terminal_width) + + +def log(emoji, message, *, spacing=None): + """Print a notification with an emoji. + + If 'spacing' is None, calculate the spacing based on the number of code points + in the emoji as terminals "eat" a space when the emoji has multiple code points. + """ + if spacing is None: + spacing = " " if len(emoji) == 1 else " " + print("".join([emoji, spacing, message])) + + +def updated_env(updates={}): + """Create a new dict representing the environment to use. + + The changes made to the execution environment are printed out. + """ + env_defaults = {} + # https://reproducible-builds.org/docs/source-date-epoch/ + git_epoch_cmd = ["git", "log", "-1", "--pretty=%ct"] + try: + epoch = subprocess.check_output( + git_epoch_cmd, encoding="utf-8" + ).strip() + env_defaults["SOURCE_DATE_EPOCH"] = epoch + 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 + + env_diff = {} + for key, value in environment.items(): + if os.environ.get(key) != value: + env_diff[key] = value + + env_vars = [ + f"\n {key}={item}" for key, item in sorted(env_diff.items()) + ] + log("🌎", f"Environment changes:{''.join(env_vars)}") + + return environment + + +def subdir(working_dir, *, clean_ok=False): + """Decorator to change to a working directory.""" + + def decorator(func): + @functools.wraps(func) + def wrapper(context): + nonlocal working_dir + + if callable(working_dir): + working_dir = working_dir(context) + separator() + log("📁", os.fsdecode(working_dir)) + if ( + clean_ok + and getattr(context, "clean", False) + and working_dir.exists() + ): + log("🚮", "Deleting directory (--clean)...") + shutil.rmtree(working_dir) + + working_dir.mkdir(parents=True, exist_ok=True) + + with contextlib.chdir(working_dir): + return func(context, working_dir) + + return wrapper + + return decorator + + +def call(command, *, context=None, quiet=False, **kwargs): + """Execute a command. + + If 'quiet' is true, then redirect stdout and stderr to a temporary file. + """ + if context is not None: + quiet = context.quiet + + log("❯", " ".join(map(str, command)), spacing=" ") + if not quiet: + stdout = None + stderr = None + else: + if (logdir := getattr(context, "logdir", None)) is None: + logdir = pathlib.Path(tempfile.gettempdir()) + stdout = tempfile.NamedTemporaryFile( + "w", + encoding="utf-8", + delete=False, + dir=logdir, + prefix="cpython-wasi-", + suffix=".log", + ) + stderr = subprocess.STDOUT + log("📝", f"Logging output to {stdout.name} (--quiet)...") + + subprocess.check_call(command, **kwargs, stdout=stdout, stderr=stderr) + + +def build_python_path(): + """The path to the build Python binary.""" + binary = 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 {BUILD_DIR}" + ) + + return binary + + +def build_python_is_pydebug(): + """Find out if the build Python is a pydebug build.""" + test = "import sys, test.support; sys.exit(test.support.Py_DEBUG)" + result = subprocess.run( + [build_python_path(), "-c", test], + capture_output=True, + ) + return bool(result.returncode) + + +@subdir(BUILD_DIR, clean_ok=True) +def configure_build_python(context, working_dir): + """Configure the build/host Python.""" + if LOCAL_SETUP.exists(): + if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: + log("👍", f"{LOCAL_SETUP} exists ...") + else: + log("⚠️", f"{LOCAL_SETUP} exists, but has unexpected contents") + else: + log("📝", f"Creating {LOCAL_SETUP} ...") + LOCAL_SETUP.write_bytes(LOCAL_SETUP_MARKER) + + configure = [os.path.relpath(CHECKOUT / "configure", working_dir)] + if context.args: + configure.extend(context.args) + + call(configure, context=context) + + +@subdir(BUILD_DIR) +def make_build_python(context, working_dir): + """Make/build the build Python.""" + call(["make", "--jobs", str(cpu_count()), "all"], context=context) + + binary = build_python_path() + cmd = [ + binary, + "-c", + "import sys; " + "print(f'{sys.version_info.major}.{sys.version_info.minor}')", + ] + version = subprocess.check_output(cmd, encoding="utf-8").strip() + + log("🎉", f"{binary} {version}") + + +def wasi_sdk(context): + """Find the path to the WASI SDK.""" + if wasi_sdk_path := context.wasi_sdk_path: + if not wasi_sdk_path.exists(): + raise ValueError( + "WASI SDK not found; " + "download from " + "https://github.com/WebAssembly/wasi-sdk and/or " + "specify via $WASI_SDK_PATH or --wasi-sdk" + ) + return wasi_sdk_path + + with (HERE / "config.toml").open("rb") as file: + config = tomllib.load(file) + wasi_sdk_version = config["targets"]["wasi-sdk"] + + if wasi_sdk_path_env_var := os.environ.get("WASI_SDK_PATH"): + wasi_sdk_path = pathlib.Path(wasi_sdk_path_env_var) + if not wasi_sdk_path.exists(): + raise ValueError( + f"WASI SDK not found at $WASI_SDK_PATH ({wasi_sdk_path})" + ) + else: + opt_path = pathlib.Path("/opt") + # WASI SDK versions have a ``.0`` suffix, but it's a constant; the WASI SDK team + # has said they don't plan to ever do a point release and all of their Git tags + # lack the ``.0`` suffix. + # Starting with WASI SDK 23, the tarballs went from containing a directory named + # ``wasi-sdk-{WASI_SDK_VERSION}.0`` to e.g. + # ``wasi-sdk-{WASI_SDK_VERSION}.0-x86_64-linux``. + potential_sdks = [ + path + for path in opt_path.glob(f"wasi-sdk-{wasi_sdk_version}.0*") + if path.is_dir() + ] + if len(potential_sdks) == 1: + wasi_sdk_path = potential_sdks[0] + elif (default_path := opt_path / "wasi-sdk").is_dir(): + wasi_sdk_path = default_path + + # Starting with WASI SDK 25, a VERSION file is included in the root + # of the SDK directory that we can read to warn folks when they are using + # an unsupported version. + if wasi_sdk_path and (version_file := wasi_sdk_path / "VERSION").is_file(): + version_details = version_file.read_text(encoding="utf-8") + found_version = version_details.splitlines()[0] + # Make sure there's a trailing dot to avoid false positives if somehow the + # supported version is a prefix of the found version (e.g. `25` and `2567`). + if not found_version.startswith(f"{wasi_sdk_version}."): + major_version = found_version.partition(".")[0] + log( + "⚠️", + f" Found WASI SDK {major_version}, " + f"but WASI SDK {wasi_sdk_version} is the supported version", + ) + + # Cache the result. + context.wasi_sdk_path = wasi_sdk_path + return wasi_sdk_path + + +def wasi_sdk_env(context): + """Calculate environment variables for building with wasi-sdk.""" + wasi_sdk_path = wasi_sdk(context) + sysroot = wasi_sdk_path / "share" / "wasi-sysroot" + env = { + "CC": "clang", + "CPP": "clang-cpp", + "CXX": "clang++", + "AR": "llvm-ar", + "RANLIB": "ranlib", + } + + for env_var, binary_name in list(env.items()): + env[env_var] = os.fsdecode(wasi_sdk_path / "bin" / binary_name) + + if not wasi_sdk_path.name.startswith("wasi-sdk"): + for compiler in ["CC", "CPP", "CXX"]: + env[compiler] += f" --sysroot={sysroot}" + + env["PKG_CONFIG_PATH"] = "" + env["PKG_CONFIG_LIBDIR"] = os.pathsep.join( + map( + os.fsdecode, + [sysroot / "lib" / "pkgconfig", sysroot / "share" / "pkgconfig"], + ) + ) + env["PKG_CONFIG_SYSROOT_DIR"] = os.fsdecode(sysroot) + + env["WASI_SDK_PATH"] = os.fsdecode(wasi_sdk_path) + env["WASI_SYSROOT"] = os.fsdecode(sysroot) + + env["PATH"] = os.pathsep.join([ + os.fsdecode(wasi_sdk_path / "bin"), + os.environ["PATH"], + ]) + + return env + + +def host_triple(context): + """Determine the target triple for the WASI host build.""" + if context.host_triple: + return context.host_triple + + with (HERE / "config.toml").open("rb") as file: + config = tomllib.load(file) + + # Cache the result. + context.host_triple = config["targets"]["host-triple"] + return context.host_triple + + +@subdir(lambda context: CROSS_BUILD_DIR / host_triple(context), clean_ok=True) +def configure_wasi_python(context, working_dir): + """Configure the WASI/host build.""" + config_site = os.fsdecode(HERE / "config.site-wasm32-wasi") + + wasi_build_dir = working_dir.relative_to(CHECKOUT) + + args = { + "WASMTIME": "wasmtime", + "ARGV0": f"/{wasi_build_dir}/python.wasm", + "CHECKOUT": os.fsdecode(CHECKOUT), + "WASMTIME_CONFIG_PATH": os.fsdecode(HERE / "wasmtime.toml"), + } + # Check dynamically for wasmtime in case it was specified manually via + # `--host-runner`. + if "{WASMTIME}" in context.host_runner: + if wasmtime := shutil.which("wasmtime"): + args["WASMTIME"] = wasmtime + else: + raise FileNotFoundError( + "wasmtime not found; download from " + "https://github.com/bytecodealliance/wasmtime" + ) + host_runner = context.host_runner.format_map(args) + env_additions = {"CONFIG_SITE": config_site, "HOSTRUNNER": host_runner} + build_python = os.fsdecode(build_python_path()) + # The path to `configure` MUST be relative, else `python.wasm` is unable + # to find the stdlib due to Python not recognizing that it's being + # executed from within a checkout. + configure = [ + os.path.relpath(CHECKOUT / "configure", working_dir), + f"--host={host_triple(context)}", + f"--build={BUILD_DIR.name}", + f"--with-build-python={build_python}", + ] + if build_python_is_pydebug(): + configure.append("--with-pydebug") + if context.args: + configure.extend(context.args) + call( + configure, + env=updated_env(env_additions | wasi_sdk_env(context)), + context=context, + ) + + python_wasm = working_dir / "python.wasm" + exec_script = working_dir / "python.sh" + with exec_script.open("w", encoding="utf-8") as file: + file.write(f'#!/bin/sh\nexec {host_runner} {python_wasm} "$@"\n') + exec_script.chmod(0o755) + log("🏃", f"Created {exec_script} (--host-runner)... ") + sys.stdout.flush() + + +@subdir(lambda context: CROSS_BUILD_DIR / host_triple(context)) +def make_wasi_python(context, working_dir): + """Run `make` for the WASI/host build.""" + call( + ["make", "--jobs", str(cpu_count()), "all"], + env=updated_env(), + context=context, + ) + + exec_script = working_dir / "python.sh" + call([exec_script, "--version"], quiet=False) + log( + "🎉", + f"Use `{exec_script.relative_to(pathlib.Path().absolute())}` " + "to run CPython w/ the WASI host specified by --host-runner", + ) + + +def clean_contents(context): + """Delete all files created by this script.""" + if CROSS_BUILD_DIR.exists(): + log("🧹", f"Deleting {CROSS_BUILD_DIR} ...") + shutil.rmtree(CROSS_BUILD_DIR) + + if LOCAL_SETUP.exists(): + if LOCAL_SETUP.read_bytes() == LOCAL_SETUP_MARKER: + log("🧹", f"Deleting generated {LOCAL_SETUP} ...") From 4ebaf3f4596adfb4d508e2278cb9a08b39480d50 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 4 Mar 2026 13:27:47 -0800 Subject: [PATCH 046/196] Use bytecodealliance/setup-wasi-sdk-action to install the WASI SDK (#145445) --- .github/workflows/reusable-wasi.yml | 31 +++++++++++++++++------------ 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml index fb62f0d5164e07..8d76679a400c7f 100644 --- a/.github/workflows/reusable-wasi.yml +++ b/.github/workflows/reusable-wasi.yml @@ -13,8 +13,6 @@ jobs: timeout-minutes: 60 env: WASMTIME_VERSION: 38.0.3 - WASI_SDK_VERSION: 30 - WASI_SDK_PATH: /opt/wasi-sdk CROSS_BUILD_PYTHON: cross-build/build CROSS_BUILD_WASI: cross-build/wasm32-wasip1 steps: @@ -26,18 +24,23 @@ jobs: uses: bytecodealliance/actions/wasmtime/setup@v1 with: version: ${{ env.WASMTIME_VERSION }} - - name: "Restore WASI SDK" - id: cache-wasi-sdk - uses: actions/cache@v5 - with: - path: ${{ env.WASI_SDK_PATH }} - key: ${{ runner.os }}-wasi-sdk-${{ env.WASI_SDK_VERSION }} - - name: "Install WASI SDK" # Hard-coded to x64. - if: steps.cache-wasi-sdk.outputs.cache-hit != 'true' + - name: "Read WASI SDK version" + id: wasi-sdk-version run: | - mkdir "${WASI_SDK_PATH}" && \ - curl -s -S --location "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-arm64-linux.tar.gz" | \ - tar --strip-components 1 --directory "${WASI_SDK_PATH}" --extract --gunzip + import tomllib + from pathlib import Path + import os + config = tomllib.loads(Path("Platforms/WASI/config.toml").read_text()) + version = config["targets"]["wasi-sdk"] + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"version={version}\n") + shell: python + - name: "Install WASI SDK" + id: install-wasi-sdk + uses: bytecodealliance/setup-wasi-sdk-action@b2de090b44eb70013ee96b393727d473b35e1728 + with: + version: ${{ steps.wasi-sdk-version.outputs.version }} + add-to-path: false - name: "Install Python" uses: actions/setup-python@v6 with: @@ -51,6 +54,8 @@ jobs: - name: "Configure host" # `--with-pydebug` inferred from configure-build-python run: python3 Platforms/WASI configure-host -- --config-cache + env: + WASI_SDK_PATH: ${{ steps.install-wasi-sdk.outputs.wasi-sdk-path }} - name: "Make host" run: python3 Platforms/WASI make-host - name: "Display build info" From 1aa1d76b7f2b5d4f767029d6d531f126e2857187 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 4 Mar 2026 23:45:43 +0100 Subject: [PATCH 047/196] gh-145376: Fix reference leaks in deque (#145421) Fix a reference leak if newblock() fails in _collections.deque. --- Modules/_collectionsmodule.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 72865f87fc484f..c3d63c8aab4b47 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -342,8 +342,10 @@ deque_append_lock_held(dequeobject *deque, PyObject *item, Py_ssize_t maxlen) { if (deque->rightindex == BLOCKLEN - 1) { block *b = newblock(deque); - if (b == NULL) + if (b == NULL) { + Py_DECREF(item); return -1; + } b->leftlink = deque->rightblock; CHECK_END(deque->rightblock->rightlink); deque->rightblock->rightlink = b; @@ -389,8 +391,10 @@ deque_appendleft_lock_held(dequeobject *deque, PyObject *item, { if (deque->leftindex == 0) { block *b = newblock(deque); - if (b == NULL) + if (b == NULL) { + Py_DECREF(item); return -1; + } b->rightlink = deque->leftblock; CHECK_END(deque->leftblock->leftlink); deque->leftblock->leftlink = b; @@ -564,7 +568,6 @@ deque_extendleft_impl(dequeobject *deque, PyObject *iterable) iternext = *Py_TYPE(it)->tp_iternext; while ((item = iternext(it)) != NULL) { if (deque_appendleft_lock_held(deque, item, maxlen) == -1) { - Py_DECREF(item); Py_DECREF(it); return NULL; } From 72b3e374a32989a07bbab057695942b2cc23a294 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 00:57:54 +0100 Subject: [PATCH 048/196] gh-141510: Add frozendict support to python-gdb.py (#145511) --- Lib/test/test_gdb/test_pretty_print.py | 9 ++++++++- Tools/gdb/libpython.py | 13 ++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_gdb/test_pretty_print.py b/Lib/test/test_gdb/test_pretty_print.py index dfc77d65ab16a4..db3064e3df54c2 100644 --- a/Lib/test/test_gdb/test_pretty_print.py +++ b/Lib/test/test_gdb/test_pretty_print.py @@ -82,7 +82,14 @@ def test_dicts(self): self.assertGdbRepr({}) self.assertGdbRepr({'foo': 'bar'}, "{'foo': 'bar'}") # Python preserves insertion order since 3.6 - self.assertGdbRepr({'foo': 'bar', 'douglas': 42}, "{'foo': 'bar', 'douglas': 42}") + self.assertGdbRepr({'foo': 'bar', 'douglas': 42}, + "{'foo': 'bar', 'douglas': 42}") + + # frozendict + self.assertGdbRepr(frozendict(), + "frozendict({})") + self.assertGdbRepr(frozendict({'foo': 'bar', 'douglas': 42}), + "frozendict({'foo': 'bar', 'douglas': 42})") def test_lists(self): 'Verify the pretty-printing of lists' diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index a85195dcd1016a..ba52ea2a30e0be 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -352,6 +352,7 @@ def subclass_from_type(cls, t): 'frame': PyFrameObjectPtr, 'set' : PySetObjectPtr, 'frozenset' : PySetObjectPtr, + 'frozendict' : PyDictObjectPtr, 'builtin_function_or_method' : PyCFunctionObjectPtr, 'method-wrapper': wrapperobject, } @@ -815,12 +816,20 @@ def proxyval(self, visited): return result def write_repr(self, out, visited): + tp_name = self.safe_tp_name() + is_frozendict = (tp_name == "frozendict") + # Guard against infinite loops: if self.as_address() in visited: - out.write('{...}') + if is_frozendict: + out.write(tp_name + '({...})') + else: + out.write('{...}') return visited.add(self.as_address()) + if is_frozendict: + out.write(tp_name + '(') out.write('{') first = True for pyop_key, pyop_value in self.iteritems(): @@ -831,6 +840,8 @@ def write_repr(self, out, visited): out.write(': ') pyop_value.write_repr(out, visited) out.write('}') + if is_frozendict: + out.write(')') @staticmethod def _get_entries(keys): From 8b5431367042672d5c6f83e8329e199b79aa02f9 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Thu, 5 Mar 2026 09:07:47 +0900 Subject: [PATCH 049/196] gh-144991: Use runtime JIT threshold in _testinternalcapi (gh-145496) --- Include/internal/pycore_interp_structs.h | 2 +- Modules/_testinternalcapi.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 1e69c64bcd1fc0..776fb9575c2365 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -496,7 +496,7 @@ struct _py_func_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 201 +#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 202 #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/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 998bf5e592e8ee..b6ed0b8902354e 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -2970,6 +2970,8 @@ static PyMethodDef module_functions[] = { static int module_exec(PyObject *module) { + PyInterpreterState *interp = PyInterpreterState_Get(); + if (_PyTestInternalCapi_Init_Lock(module) < 0) { return 1; } @@ -3011,9 +3013,10 @@ module_exec(PyObject *module) return 1; } + // + 1 more due to one loop spent on tracing. + unsigned long threshold = interp->opt_config.jump_backward_initial_value + 2; if (PyModule_Add(module, "TIER2_THRESHOLD", - // + 1 more due to one loop spent on tracing. - PyLong_FromLong(JUMP_BACKWARD_INITIAL_VALUE + 2)) < 0) { + PyLong_FromUnsignedLong(threshold)) < 0) { return 1; } From 6acaf659ef0fdee131bc02f0b58685da039b5855 Mon Sep 17 00:00:00 2001 From: krylosov-aa Date: Thu, 5 Mar 2026 06:48:25 +0300 Subject: [PATCH 050/196] 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 00000000000000..7aeb6a1145ab4c --- /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 00000000000000..436ff316b2c327 --- /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 77832a768e0cbc..e19eb1abcf2c4d 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 f074f24807703c..7a040103bcb234 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 051/196] 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 8f64e572bd6086..6b23a5c637a308 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 052/196] 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 3cab8ff9536d23..06f69caad12bc8 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 053/196] 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 bef72032513da5..67595e3550b0ff 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 2552216152f98d..e0127f04249f6b 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 054/196] 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 3e799219478424..eb42fe9919eaeb 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 055/196] 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 8f14d81a43ee75..6e37288c32dd9a 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 3ec06faf338488..6df72de44e78cb 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 056/196] 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 65b8ffdb23111d..d9a2eff667ebe1 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 1aeec32f55a7f3..a2c5ee41c37784 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 eabfdcd447f2bb..844656eb0e2c2e 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 00000000000000..c9daaa27717ed0 --- /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 520190824fbf1a..d26516f7c2ff66 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 e0127f04249f6b..14019e4f1d926f 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 efe27a2b70c4de..fc32826fb3a861 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 d44d414bc93a04..0ea785772f03b9 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 301125051f3b0e..fc69f6372028a6 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 3ad46cf1ec85ff..1e5142f4b456a1 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 3ed808f67f4149..34224f4c6d6514 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 043bdf3433ab57..a21f494dc69d82 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 057/196] 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 e021a81d2a2b87..45abf5b1e736b3 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 a2c5ee41c37784..6d7d68eda84c5a 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 93162f52ba0344..5b06e422672b1d 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 e3d81a2c4560d9..57c5b64ea3ba70 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 f60a4c295e6495..e0bc69c5fe22f8 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 058/196] 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 675712d65d4c95..eacfff24889021 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 fab3abcb355dfe..8b7b4de0fc8f31 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 4893ec28f23e5a..dfd18182105e11 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 059/196] 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 162b0b38f8555d..45448d1264a53e 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 14019e4f1d926f..d86ab2634a9b13 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 060/196] 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 68bcf535eada10..78461abcd69f33 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 19eddde700bcf9..21f82125f5a7c4 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 00000000000000..17d62df72ce1ae --- /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 061/196] 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 | 64 ++++++++++++++++++++++----------- 4 files changed, 66 insertions(+), 38 deletions(-) diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 734462bc0051af..371761573e97de 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 561e1ea4d52846..5bdf74ef73ab54 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 abf6b38449fcb0..15b8705d9c78e3 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 d86ab2634a9b13..61fde37f8d4fff 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,35 +4385,37 @@ copy_lock_held(PyObject *o, int as_frozendict) return NULL; } -// Similar to PyDict_Copy(), but copy also frozendict. -static PyObject * -_PyDict_Copy(PyObject *o) +PyObject * +PyDict_Copy(PyObject *o) { - assert(PyAnyDict_Check(o)); + if (o == NULL || !PyDict_Check(o)) { + PyErr_BadInternalCall(); + return NULL; + } PyObject *res; Py_BEGIN_CRITICAL_SECTION(o); - res = copy_lock_held(o, PyFrozenDict_Check(o)); + res = copy_lock_held(o, 0); Py_END_CRITICAL_SECTION(); return res; } -PyObject * -PyDict_Copy(PyObject *o) +// Similar to PyDict_Copy(), but return a frozendict if the argument +// is a frozendict. +static PyObject * +anydict_copy(PyObject *o) { - if (o == NULL || !PyAnyDict_Check(o)) { - PyErr_BadInternalCall(); - return NULL; - } - - if (PyFrozenDict_CheckExact(o)) { - return Py_NewRef(o); - } + assert(PyAnyDict_Check(o)); - return _PyDict_Copy(o); + PyObject *res; + Py_BEGIN_CRITICAL_SECTION(o); + res = copy_lock_held(o, PyFrozenDict_Check(o)); + Py_END_CRITICAL_SECTION(); + return res; } -// 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 062/196] 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 d9a2eff667ebe1..af53b57dc9d2a7 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 76a4367dd2dcd5..c930b876b3ccbf 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 fff2168be72604..0b5902bb013436 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 063/196] 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 b7225ff1c2cbfc..454e2f4930e724 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 064/196] 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 890aa584cd192c..ec7192b1b89184 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 065/196] 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 c88e9edba6d230..856a7f8252bb7c 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 00000000000000..4c05e4ef57dbf8 --- /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 066/196] 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 ed182ea24e8f3c..25902622b8730b 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 6c1f7f96b6a2e8..159459fcaec3d9 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 28f24d0fc59cb0..78db4219e2997c 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 00000000000000..280a7b3632ddae --- /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 a5809b37b6b493..27a60171f3eca8 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 a71909f103ebfc..59db6456552c35 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 067/196] 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 9bc2ee7e8c894c..cd374631f16792 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 6c11ab2b1eb570..2f77f0e849e9ae 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 92ad6352557640..4cd6f8367a1349 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 050c2fe2161e3e..e0b944b197d38b 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 f016b8dc4a50b2..165f42baed94e3 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 5ff7f74754f9c1..de1082442ef7f2 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 3a71b669985f13..9d7aa5c66a91cb 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 cae38672f641b7..3c6a6b7bdc44d2 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 612b32cd0765ec..896db17baeb3db 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 45610fd5612995..c7152a70f5aa0b 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 75984bf8b262b9..7abda3653e764b 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 068/196] 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 1fa6e615e46a76..762b1b62fc871d 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 + +ZERO = dt.timedelta(0) +HOUR = dt.timedelta(hours=1) +SECOND = dt.timedelta(seconds=1) -STDOFFSET = timedelta(seconds = -_time.timezone) -if _time.daylight: - DSTOFFSET = timedelta(seconds = -_time.altzone) +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 ebe3c3576c0979..73217136f14472 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 069/196] 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 a7a5c5ba33d493..3379df37d38ca8 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 9353fb678625b3..b82862deea7d74 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 e38bda37bfa92d..88c0a68f1e6c87 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 00000000000000..2d13a0611322c5 --- /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 070/196] 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 6df59946574a17..219fbb4bb1bbe2 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 9ad5b29ea58ecb..9e03069494345b 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 071/196] 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 8f31e815e0eb4b..5a463ee9821d61 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 072/196] 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 00000000000000..723b81ddc5f897 --- /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 1fdd3cbdaaa639..27ec8bb40a929f 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 073/196] 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 00000000000000..b6dbda0427181d --- /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 7a040103bcb234..1a212fa3d37e18 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 56e9faf4c62002..e598b1fe67240d 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 074/196] 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 fd6be6a9b67a03..4a3a6347239c4f 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 0b5902bb013436..42b6171c1a83a2 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 6134442106474f..b9f253e06b31c9 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 1520489f843826..29bebf847aaba2 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 00000000000000..da1e489bb3d2e5 --- /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 6746eb9eb1e94a..151e4aa19afe11 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 c119ca5c35398b..31cd4ad3f652d9 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 075/196] 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 00000000000000..212fd7b02902e9 --- /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 db640800ad780f..98c5bf6a2fb146 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 @@ mmap_mmap_madvise(PyObject *self, PyObject *const *args, Py_ssize_t nargs) #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 16e3c0ecefd05d..61d8a043a04ce2 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 076/196] 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 a45959346bc1f2..f2246dd36cf110 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 077/196] 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 aa793a2c223de9..4cbfd7ad8b1e48 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 00000000000000..77b43e79e35860 --- /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 ae8a8ffb3c005a..dcc3c7ec63e9e0 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 078/196] 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 b25750f0897de2..9ee38a4fd1cefc 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 079/196] 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 deabac5253051c..7778e37a9adaa9 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 080/196] 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 e234d86e8d5532..f9d2cdfc32b383 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 856a7f8252bb7c..14d32279a8c4fa 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 081/196] 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 c4e3ffdb4de6cf..351fb06a885006 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 981e00e28b42a7..4d92b083026b27 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 082/196] 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 025a3fac46e59b..a2d1aefb1611b3 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 083/196] 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 61464348d6fab8..dd96f9aa62b85b 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 e6cd64338064b3..3f3695d50f2754 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 119dd4b5c2dd00..7aef56cf4e93b8 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 b537c0d104e58c..e405963614689f 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 7a159338b9ba8a..b8bb041f0cff21 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 2ec546aff52c0a..0a260f4c10278c 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 7aa85a942e449e..7756f1a8482477 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 084/196] 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 ff0e2fd2b3569d..bc25bf6bfc1bd2 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); + + // 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; - stepped_up = PyNumber_Add(long_cnt, lz->long_step); - if (stepped_up == NULL) + 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 814ce4f919514b..70e7cce6aba008 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 3921b7cd7b69bc..7fc21907fefd31 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 085/196] 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 120a6add38507f..4c2426ed283d43 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 00000000000000..6b6a9eb9813663 --- /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 cb806459596084..40946cafd16b75 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 6dcf0e8712903a..a0e36a4c526ede 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 15d256b6743e0a..72a291d0d43f1d 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 3c43f7e3bbe8ca..0d1f5968d2a9e9 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 086/196] 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 8cadf26cee3027..c9bb5c3f09ac18 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 64399f6ab1ff26..01b064f3e617ff 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 087/196] 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 dd96f9aa62b85b..fe9d6fe2763f36 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 088/196] 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 c23e81e29df0f5..fcbe2122d9f1a7 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:: + + >>> 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:: _handle + + The system handle used to access the library. - `Microsoft DUMPBIN tool `_ - -- A tool to find DLL dependents. + .. attribute:: _name + The name of the library passed in the constructor. -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) +.. class:: OleDLL - Instances of this class represent loaded shared libraries, - functions in these libraries use the ``stdcall`` calling convention, and are + 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 -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) + See :py:class:`~ctypes.CDLL`, the superclass, for common information. - 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 089/196] 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 321a4e5d5d18fb..224b1883808a41 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 bf301740741ae7..c08eb7cf261568 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 00000000000000..15b70d734ca3b9 --- /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 090/196] 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 5bdf74ef73ab54..cd46fea5476ca6 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 45448d1264a53e..b2f4363b23e748 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 61fde37f8d4fff..b5f2a682c54982 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)) - { - self = frozendict_new(_PyType_CAST(type), NULL, NULL); + PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL); + if (self == NULL) { + return NULL; } - else { - self = dict_new(_PyType_CAST(type), NULL, 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)) + { + // 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 091/196] 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 f485c27bca2a4f..4387bcb0d67832 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 092/196] 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 5b7fdf8ec08ed4..7bdabd8bf168fe 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 545049bb460419..26497083d28e47 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 078062c08c6020..d2b7d9669ab07e 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 093/196] 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 3ea24ea77004ad..a32c3828313454 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 094/196] 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 00000000000000..2183eef618daae --- /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 d92dc768e5ec28..5fbfb82baa0204 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 ff7444cce10923..ded59f8eb1ccaa 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 9b092b9b734d4c..9dad69c995e7a0 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 b59ebdfbda3897..983bdddbf026a8 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 095/196] 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 26497083d28e47..6f66ed68c52e83 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 0c3b1d3a9108a3..916bb25d74dee9 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 71f1e616116d81..faa3a2bfe121dc 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 35e4652a87b423..dcaad49ffab5d2 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 00000000000000..9b55459bffdea8 --- /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 c25699978cf651..6050c351cff68f 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 096/196] 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 4c2426ed283d43..120a6add38507f 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 6b6a9eb9813663..00000000000000 --- 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 40946cafd16b75..cb806459596084 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 a0e36a4c526ede..6dcf0e8712903a 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 72a291d0d43f1d..15d256b6743e0a 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 0d1f5968d2a9e9..3c43f7e3bbe8ca 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 097/196] 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 7a6f88d90a9ea5..8bd2bc99d74b83 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 098/196] 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 2f4d635a29585c..4dceb5cdc8dfcf 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 099/196] 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 3a485a43a5a751..412005f3ec82f4 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 100/196] 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 70148dc30fc957..cee528722b85aa 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 00000000000000..23796082fb616f --- /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 beb6df88d097e3..4b695e4b2588d8 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 101/196] 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 27ec8bb40a929f..81abb0990eebe9 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 102/196] Vary compiler flags in `fuzz_pycompile` (#145236) * Vary compiler flags in fuzz_pycompile * Drop `PyCF_SOURCE_IS_UTF8` --- Modules/_xxtestfuzz/fuzzer.c | 48 +++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/Modules/_xxtestfuzz/fuzzer.c b/Modules/_xxtestfuzz/fuzzer.c index 14da472c1bb110..f3a22f3f6a87cb 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'; - - // 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); + pycompile_scratch[size - 3] = '\0'; + + 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 103/196] 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 90e2ed20d1f6b3..8fa4f02afb5b45 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 00000000000000..c8ca7a7fa194ee --- /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 4387bcb0d67832..7315bb6b9f603d 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 104/196] 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 00000000000000..676a68e5a912f5 --- /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 2b1488911ef97b..399ff59ad01ab6 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 105/196] 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 84b8575284b793..cc3d2f154ed754 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 d4517183d697f1..772334f40a56fb 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 af6cb84e9ff905..74d84052a2bb2b 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 045c47ce5addc4..cb86c95a672ed7 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 7756f1a8482477..a65c43874e876c 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 106/196] 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 3b7897b8a88a45..d8e3b671ec229f 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 107/196] 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 1e5142f4b456a1..950050a6027116 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 c8a80e7a986008..f92927da475321 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 55b4072213d3c2..893a116565e37e 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 108/196] 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 00562bef769920..b3fa28f5bf21d5 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 d6669d7802c5b8..0c27e81168ff77 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 39be41d9d2a426..0d520684c795d6 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 b6ed0b8902354e..aa5911ef2fb449 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 03557d5bf5957f..81f536c3babb18 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 00000000000000..c12ee32deb9164 --- /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 3c68955495d566..01afa53e15cd5d 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 3818e6d3f7bbd2..f3e423fa04668e 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 012d709bd1ce5d..7ab242c2c230b6 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 109/196] 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 42b6171c1a83a2..ead4e7cbf2871e 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 110/196] 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 1a51802ffefac7..a2b21da2970064 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 195a555d68e98b..07b15a5a2b48c7 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 53928b7b20fb11..2da1103b82a52a 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 84b13ca0a9682b..fb761335876b0f 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 00000000000000..da8b5851c85f62 --- /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 b6d9ff79e8ceec..ea1beec70d39f8 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 5a3497a5408414..931bc2c487b55b 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 111/196] 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 34fd49bf56fbb6..64a01a0b713c61 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 112/196] 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 | 410 +++--- 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, 1513 insertions(+), 454 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 4a3a6347239c4f..58456a36b96c15 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 371761573e97de..d63c26865899cc 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 aef191d3a29ac6..8ecd7c62517104 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 04b5adb9a8f43d..367490732b994f 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 f71bfebdb2a19a..15a4b55eab82f0 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 447f05e67d8418..fd8e0c0bea1cb1 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 8dfcd492f0a763..c6924a0ac29c97 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 33f37bdf1fc1cd..3db3c7a13503f4 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 af53b57dc9d2a7..1d83cb6f2bb688 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 d5036a0fe7510b..785f6c614b4391 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 b9a55a03dc8ae7..5b9741bdbcad19 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 25902622b8730b..4fe34f0a3a3f91 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 a22afdec516bb4..940d04ccc925cd 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 7edb85ca507722..43fb7295876fe1 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 0666fcfde61e61..d289ba58c24065 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 c930b876b3ccbf..e16954b12a6c2b 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 4c76feafc9b492..b1461b0cbaf528 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 01f4df3c89091f..74898baa521bd6 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 d5f0405efbecc6..f5c11fd849f58b 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 45abf5b1e736b3..919d4c595bf793 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 5c931683db100a..ae541680c534d6 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 9ada6f047843b4..9b84c2e9ac7017 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 cc3d2f154ed754..5c3d44395c0039 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 50d5ac4a73c1d8..3cc12a2b2d3888 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 76a2c18bdb2f0e..314bef547f3052 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 dc09c5fd47affe..7dd9cfe2ff5821 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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): '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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): >>> t"Hello" t"{name}!" Template(strings=('Hello', '!'), interpolations=(...)) + +Formally: + + strings: (STRING | fstring)+ | tstring+ ''', 'attribute-access': r'''Customizing attribute access **************************** @@ -1007,7 +1062,7 @@ class and instance attributes applies as for regular assignments. 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 @@ def foo(): 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 @@ def foo(): 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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): 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 @@ async def func(param1, param2): 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 @@ def f() -> annotation: ... * 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 @@ def f() -> annotation: ... 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: - -* If both arguments are complex numbers, no conversion is performed; +means that the operator implementation for built-in numeric types +works as described in the Numeric Types section of the standard +library documentation. -* 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 @@ def __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 @@ def inner(x): 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 @@ def whats_on_the_telly(penguin=None): * "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 @@ def whats_on_the_telly(penguin=None): 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 @@ def whats_on_the_telly(penguin=None): '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 @@ def whats_on_the_telly(penguin=None): "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 @@ class C: pass # a class with no methods (yet) 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 @@ def __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 @@ class is used in a class pattern with positional arguments, each "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 @@ class is used in a class pattern with positional arguments, each 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 @@ class is used in a class pattern with positional arguments, each 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 @@ class is used in a class pattern with positional arguments, each '00042' >>> "-42".zfill(5) '-0042' + + See also "rjust()". ''', 'strings': '''String and Bytes literals ************************* @@ -13338,13 +13452,13 @@ class instance has a namespace implemented as a dictionary which is 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 @@ class dict(iterable, /, **kwargs) 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*: - - 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. +See also: + + For detailed information on thread-safety guarantees for "list" + objects, see Thread safety for list objects. Tuples @@ -14615,9 +14710,9 @@ class range(start, stop, step=1, /) 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 @@ class range(start, stop, step=1, /) 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 00000000000000..7d9681cbcbef00 --- /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 30addc4bf64d4b..00000000000000 --- 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 1018ed95a2af77..00000000000000 --- 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 ebcfda54da39a7..00000000000000 --- 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 035d0c141d36ed..00000000000000 --- 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 d6e0201b90c550..00000000000000 --- 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 da1e489bb3d2e5..00000000000000 --- 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 cf84f8b1b0d36b..00000000000000 --- 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 57a25fe045f04c..00000000000000 --- 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 d86886ab09704a..00000000000000 --- 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 bda7003be94e54..00000000000000 --- 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 943be5b4533d9e..00000000000000 --- 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 db87a5ed9c7fc2..00000000000000 --- 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 9b9a282b5ab414..00000000000000 --- 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 f5d312a289fe21..00000000000000 --- 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 3f7ce7326187d4..00000000000000 --- 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 73cc167fd04013..00000000000000 --- 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 3e33e461ae8b5a..00000000000000 --- 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 bdd0d6c2f7b944..00000000000000 --- 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 01d2b6570ded96..00000000000000 --- 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 85c75a224e42fc..00000000000000 --- 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 c8ca7a7fa194ee..00000000000000 --- 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 4596e273fc6118..00000000000000 --- 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 46786d0672b0a8..00000000000000 --- 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 d9613c95af1915..00000000000000 --- 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 c06bf01baee6fd..00000000000000 --- 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 f13b8541a0ebe2..00000000000000 --- 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 3cfc3e930d1e9d..00000000000000 --- 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 b031fb3c75dea7..00000000000000 --- 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 87d6a2a6df96a1..00000000000000 --- 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 83d84b9505c5a5..00000000000000 --- 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 05eb296f96ec6d..00000000000000 --- 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 c9daaa27717ed0..00000000000000 --- 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 1f298e164f4488..00000000000000 --- 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 24507d4a411f85..00000000000000 --- 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 122315e031bc87..00000000000000 --- 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 fccc3bc2a1804e..00000000000000 --- 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 5f6043cc3d9660..00000000000000 --- 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 08c6b44164ebc3..00000000000000 --- 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 6d6afe5abfea9c..00000000000000 --- 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 5a2106480fb843..00000000000000 --- 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 a3253132a577ba..00000000000000 --- 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 8d9e4a872d0d7a..00000000000000 --- 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 1723a7c8c10717..00000000000000 --- 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 caeffff0be8a85..00000000000000 --- 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 a5a6908757e458..00000000000000 --- 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 42ed85c7da31ac..00000000000000 --- 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 9b55459bffdea8..00000000000000 --- 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 723b81ddc5f897..00000000000000 --- 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 212fd7b02902e9..00000000000000 --- 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 2183eef618daae..00000000000000 --- 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 23796082fb616f..00000000000000 --- 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 5f83785df13209..00000000000000 --- 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 d29bde5ca690c6..00000000000000 --- 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 681c932b34a05d..00000000000000 --- 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 b22289835620df..00000000000000 --- 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 bf97bf0231fc0a..00000000000000 --- 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 2e9c3d81180e6a..00000000000000 --- 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 1f48525cdbecd0..00000000000000 --- 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 a3e0a3e14af1fa..00000000000000 --- 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 f82f1eeb0589c6..00000000000000 --- 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 5067db357fc577..00000000000000 --- 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 8f3efceaae1d91..00000000000000 --- 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 2311ace10e411d..00000000000000 --- 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 fe5e7d17ab6c8c..00000000000000 --- 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 13e38b118175b4..00000000000000 --- 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 e928bd2cac72a8..00000000000000 --- 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 772e05766c5c69..00000000000000 --- 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 826b2e9a126d36..00000000000000 --- 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 3993c7a91da138..00000000000000 --- 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 efa7c8a1f62692..00000000000000 --- 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 05dc4941c98a83..00000000000000 --- 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 5f95b0de7d8895..00000000000000 --- 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 bed126f02f8714..00000000000000 --- 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 cbb21194d5b387..00000000000000 --- 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 b9d0749f56ba6a..00000000000000 --- 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 e1119a85e9c1f3..00000000000000 --- 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 b458399bb40640..00000000000000 --- 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 45561898e2e1e9..00000000000000 --- 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 1db257ae312e84..00000000000000 --- 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 276711e6ba3900..00000000000000 --- 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 68e59a6276c092..00000000000000 --- 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 f45f6682869eb1..00000000000000 --- 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 29fa908d739fc3..00000000000000 --- 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 14eb4f49c8ad3c..00000000000000 --- 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 871005fd7d986c..00000000000000 --- 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 f7782f2fa4f23b..00000000000000 --- 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 6d5b18f59ee7ea..00000000000000 --- 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 9d603b51c48a93..00000000000000 --- 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 59a8b4165cdd15..00000000000000 --- 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 5b604124c6d7cc..00000000000000 --- 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 62c20b7fa06d94..00000000000000 --- 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 fd720bfd3f3da6..00000000000000 --- 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 841c3758ec4df1..00000000000000 --- 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 15cf25052bbb46..00000000000000 --- 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 4654dd060a6b78..00000000000000 --- 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 cf22e82b8415b8..00000000000000 --- 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 69052c7ca92c8a..00000000000000 --- 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 ae46ff0cbdd8b1..00000000000000 --- 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 6f496bb30e1686..00000000000000 --- 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 68a25262c7d7f7..00000000000000 --- 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 1babcbfd8e678a..00000000000000 --- 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 60a5e4ad1f0ca4..00000000000000 --- 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 4bb230dcb8473f..00000000000000 --- 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 7aeb6a1145ab4c..00000000000000 --- 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 436ff316b2c327..00000000000000 --- 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 b6dbda0427181d..00000000000000 --- 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 53033b06c2fae0..00000000000000 --- 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 17d62df72ce1ae..00000000000000 --- 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 280a7b3632ddae..00000000000000 --- 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 15b70d734ca3b9..00000000000000 --- 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 77b43e79e35860..00000000000000 --- 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 2d13a0611322c5..00000000000000 --- 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 dcdb44d4fae4e5..00000000000000 --- 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 8c46ff133f9433..00000000000000 --- 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 be3092f1c2592a..00000000000000 --- 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 810985a352baeb..00000000000000 --- 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 6f039197962e10..00000000000000 --- 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 676a68e5a912f5..00000000000000 --- 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 68e114e66abe43..1d2874e9ca4fdc 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 113/196] 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 fbd7354a915a0a..732e9a876ca8ad 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 00000000000000..297ee4099f12c5 --- /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 c3d63c8aab4b47..15c9aa41911822 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 114/196] 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 | 49 +++++++++++++------ 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, 121 insertions(+), 35 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 81b36efc6c285f..84551e3546eb6e 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 44667efc522556..0bf3bdded40200 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 b5d8f827827415..7b08d2bb70183d 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 69c83e085113c9..a1a6aad434ddf4 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) - -# 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 +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 + + # --------------------------------------------------------- old names + getpager = get_pager + pipepager = pipe_pager + plainpager = plain_pager + tempfilepager = tempfile_pager + ttypager = tty_pager + +except ModuleNotFoundError: + # Minimal alternatives for cases where _pyrepl is absent. + + 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 5f09a7dd8c91c0..30015b3f26b4b3 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 d4d3c7f1aefa66..3da662b0c4d50a 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 79ef178f3807f4..b5ec41b17f793b 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 2f37bff6df8b4a..1534d63352cc55 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 40965835bcec00..27cd125078ea69 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 00000000000000..b20da3b54c0415 --- /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 95ba541d98c2e8..7731fa0c7c6717 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 115/196] 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 c930b876b3ccbf..bfa49b62ec5778 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 116/196] 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 3cc12a2b2d3888..7cffd74125f1b4 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 117/196] 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 | 210 +++++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 85 deletions(-) diff --git a/Doc/c-api/threads.rst b/Doc/c-api/threads.rst index 41c7fbda2302cf..3b761d0c657cbd 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. + +.. 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``. -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``. +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. - -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. +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. + +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,73 +178,84 @@ 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`. - PyGILState_STATE gstate; - gstate = PyGILState_Ensure(); +.. 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 */ - /* Release the thread. No Python API allowed beyond this point. */ - PyGILState_Release(gstate); + /* Destroy the thread state. No Python API allowed beyond this point. */ + PyThreadState_Clear(tstate); + PyThreadState_DeleteCurrent(); -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. +.. warning:: -Supporting subinterpreters in non-Python threads ------------------------------------------------- + If the interpreter finalized before ``PyThreadState_Swap`` was called, then + ``interp`` will be a dangling pointer! -If you would like to support subinterpreters with non-Python created threads, you -must use the ``PyThreadState_*`` API instead of the traditional ``PyGILState_*`` -API. +.. _gilstate: -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:: +Legacy API +---------- - /* 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); +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`. - /* GIL of the subinterpreter is now held. - Perform Python actions here. */ +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(); + + /* 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(); + /* Release the thread. No Python API allowed beyond this point. */ + PyGILState_Release(gstate); .. _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 118/196] 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 ead4e7cbf2871e..e749ef2a455ea2 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 fc916c470a0110..ee66160be63b6f 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 fe7584f1f9d3b3..2d618081521e10 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 00000000000000..c3a476df75f136 --- /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 119/196] 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 cf5a0e71a104eb..062d301f6286f7 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 120/196] 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 00000000000000..538995538d7da8 --- /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 aa3d682a19bc9c..8c360ce3b79b8a 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 eca5f03cdcfb2d..95bb6ba4e84ccf 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 c21024a1e77433..e049f568417335 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 121/196] 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 70c4de543b7d00..c0d2663adefc6b 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 83eba8cfea3969..2f089a3d89680a 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 122/196] 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 4cbfd7ad8b1e48..6904572d095d31 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 dcc3c7ec63e9e0..c2f7b1fe0e800a 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 123/196] 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 27ddc9c2d26dfb..0ede4df103f728 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 00000000000000..2a565c1d02bc2e --- /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 7fc21907fefd31..62d04ab150a77a 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 124/196] 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 62d04ab150a77a..1fcedd3a28c91b 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 125/196] 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 0c7e7341f13d4e..bee2aceb187027 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 126/196] 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 81abb0990eebe9..5dc96bf251b384 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 127/196] 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 ad452be8405671..3fb28035a50547 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 1fd01702f64029..5b4c97c181bb6a 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 2d9052a6b879da..14aeafefcaa8f7 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 00000000000000..7f5be699c6348d --- /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 128/196] 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 6904572d095d31..55e2ce590a2577 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 00000000000000..a909bea2caffe9 --- /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 c2f7b1fe0e800a..f8574322b40c8d 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 129/196] 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 3ffdb4c837192b..bd3fefc6c9d959 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 00000000000000..a5330365e3e42e --- /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 130/196] 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 7ce5d0535b884e..185226db43a92a 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 131/196] 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 14d32279a8c4fa..b1a779777ae9fc 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 00000000000000..98edaebe992685 --- /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 4c05e4ef57dbf8..00000000000000 --- 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 132/196] 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 1c64bf888f9d27..876ecd4467b0a2 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 00000000000000..2cf83eff31056a --- /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 7f09769e12f05f..e2fea94e099626 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 be704ccf68f669..cf60d0ceadc7d1 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 133/196] 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 e0fcce8f0cbb8c..6a67bf7c8e555d 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 3db3c7a13503f4..7fc6055aa9a881 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 940d04ccc925cd..7547967c6b32f0 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 062d301f6286f7..90b8821daaf3fb 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 134/196] 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 69d667b4be47d2..188da775eb1cc7 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 5dc96bf251b384..bb473dce68f65b 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 f60f5adba5c12c..8d8bbc88e7f30a 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 135/196] 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 | 626 +++--------------- Python/dtoa.c | 6 +- Python/pylifecycle.c | 2 - configure | 13 - configure.ac | 14 +- pyconfig.h.in | 4 - 14 files changed, 129 insertions(+), 585 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 dcd545478277a8..ca8d44c25c1ece 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 317f984188bad8..62501cdaf44f07 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 f66325aa59c4c9..532c5ceafb5639 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 b182f7825a2326..e8d1098c2078fc 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 90e6625ad1fc9c..05369ef9f009e6 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 615abe103ca038..9d63ddf8a716f4 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 00000000000000..2c4da1b60c0908 --- /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 4051131f480ccb..c0ae9d3ff9b8d3 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 579765281ca484..18871a4f3c51a9 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); -#endif } +#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)); + 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; - } + 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; + for (i = 0; i < 4; i++) { + *p = s[i]; + p += incr; } - Overflow: - PyErr_SetString(PyExc_OverflowError, - "float too large to pack with f format"); - return -1; + 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; - - 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; - } + unsigned char as_bytes[8]; + memcpy(as_bytes, &x, 8); + const unsigned char *s = as_bytes; + int i, incr = 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; - - if (le) { - p += 3; - incr = -1; - } + float x; - /* First byte */ - sign = (*p >> 7) & 1; - e = (*p & 0x7F) << 1; - p += incr; + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + char buf[4]; + char *d = &buf[3]; + int i; - /* 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; + for (i = 0; i < 4; i++) { + *d-- = *p++; } - x = ldexp(x, e); - - if (sign) - x = -x; - - return x; + memcpy(&x, buf, 4); } else { - float x; - - 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); - } + 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; - - if (le) { - p += 7; - incr = -1; - } - - /* 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; + double x; - x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */ - x /= 268435456.0; /* 2**28 */ + if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) { + char buf[8]; + char *d = &buf[7]; + int i; - if (e == 0) - e = -1022; - else { - x += 1.0; - e -= 1023; + for (i = 0; i < 8; i++) { + *d-- = *p++; } - 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 3de150351a4ef8..89fadd33391cb4 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 711e7bc89b71c0..21d1e036d31540 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 95bb6ba4e84ccf..a3eeef373bf7fb 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 e049f568417335..75e81761f95e38 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 fbd5d4d625908e..9da33c954a52f8 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 136/196] 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 41b36066c62fcb..9ce996c9ccd211 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 cc07062eee6f98..d67fd13fa33bed 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 00000000000000..c17d01f36b8c64 --- /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 137/196] 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 d590a333930278..09ce09b91b7ac2 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 c7e6b941978cd5..0681163c979587 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 00000000000000..e9401bb08c6774 --- /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 138/196] 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 1d83cb6f2bb688..483e5b1d8fdba7 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 139/196] 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 732e9a876ca8ad..a193eb10f16d17 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 140/196] 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 7ecc55eee13775..569f5afb312008 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 141/196] 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 a70bda47da6f43..6b55daa9b6eae0 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 142/196] 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 7abda3653e764b..7f0b0b3c632573 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 139840dd9c1f1b..f2babaacc27d96 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 88c0a68f1e6c87..d7762f8c875fa9 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 00000000000000..1f5b8ed90b8a90 --- /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 143/196] 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 5bf60348f68250..63ec65ac0dbd8d 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 144/196] 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 563c5d96b05362..9f84e4bc6dfd91 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 5c3d44395c0039..ce6872f3c0fda3 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 813127663ed8fe..6bef290d181fc9 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 145/196] 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 2fbc2a041269f4..14a08995bf127c 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 4e809acb7a01bb..956cab49131990 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 00000000000000..d76f0873d77265 --- /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 146/196] 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 22df26bd37a5c5..1c56ad5af8072f 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 00000000000000..827224dc71e827 --- /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 a8f37bedc81247..17b8430b19c188 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 147/196] 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 | 94 +++++++++++++++++++++++++-------- 2 files changed, 124 insertions(+), 32 deletions(-) diff --git a/Lib/test/test_capi/test_dict.py b/Lib/test/test_capi/test_dict.py index cd46fea5476ca6..4cf404e9f56327 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 b5f2a682c54982..842d9be73b8792 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) { + assert(key); + assert(value); + if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); + if (PyFrozenDict_Check(op)) { + frozendict_does_not_support("assignment"); + } + else { + PyErr_BadInternalCall(); + } return -1; } - assert(key); - assert(value); + 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 148/196] 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 f3579a23afc539..1c400e970eb02d 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 dd2d7c4da459ab..94244a8b3fe244 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 e738fbff82ed43..8cce9aed9d514f 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 149/196] 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 126bc7d7102925..09588e9428281e 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 38f290df2c770f..216436604c6973 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 c08f1e24fd1c12..4a8245365f805a 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 8fa4f02afb5b45..4dd1140f7d85b7 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 79320a4bff17fb..2615b1d4dd2b5f 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 8a748fec9e4201..ac3e519398dbce 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 09004545267026..6271778bed4419 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 42098c59040f07..5d853998bf68b5 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 2f52837f058113..2b68ba4d2cde92 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 c35c77ed442d7a..f996c1f6cc70a7 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 150/196] 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 1c61524d60a1af..312699415efd9a 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 152d61c686722e..c50ff1190686c2 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 0ea785772f03b9..6b6ac238935765 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 fc69f6372028a6..5680e8971576cd 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 96779a0a219a55..4cf178b06ae11d 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 881290a0e60db8..e4719e71a5259a 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 59db6456552c35..cc6a787ba75022 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 21d1e036d31540..2b8e9a02cb6184 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 151/196] 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 6f66ed68c52e83..4ac6f6192a0806 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 00000000000000..f063ca1360d5fb --- /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 5b5949d4eff437..7ab5921c7ec298 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 e04a5f144c449b..58f597c2eb2d0c 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 152/196] 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 | 163 +++++++++++++- ...-01-10-16-23-21.gh-issue-143715.HZrfSA.rst | 3 + Modules/_struct.c | 207 +++++++++++++++--- Modules/clinic/_struct.c.h | 62 +++++- 6 files changed, 409 insertions(+), 42 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 8372432a34daa5..176e8f3f9f601c 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 e749ef2a455ea2..c979118abd0a07 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 55e2ce590a2577..e3e02097b1f550 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('>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 00000000000000..90aae6bee835f0 --- /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 f8574322b40c8d..7eddc9bdc38a89 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; + if (type->tp_new != s_new) { + /* Struct.__new__() was called explicitly in a subclass' __new__(). */ + return Struct(type, args, kwds); + } - assert(type != NULL); - allocfunc alloc_func = PyType_GetSlot(type, Py_tp_alloc); - assert(alloc_func != NULL); + 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; + } + } + } - 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; + 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 self; + 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 9c9d29748fcf28..e75698e3ed00cc 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 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) 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 153/196] 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 55e5f06c8071ea..e106ac20809f20 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 00000000000000..aa126e7e25bba7 --- /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 64e8f5383f0602..ee77479ba7bdcc 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 154/196] 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 09588e9428281e..2586ed3a5299a6 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 216436604c6973..79e62edfeed978 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 4a8245365f805a..fbcb95baf2aa60 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 2615b1d4dd2b5f..b025f7b0eb7fe5 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 ac3e519398dbce..0eff5f76740f78 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 6271778bed4419..032d6faeda6a96 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 5d853998bf68b5..de036fb964b691 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 f996c1f6cc70a7..fe083411b7b739 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 155/196] 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 1fcedd3a28c91b..1cc62764e2fd8c 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 156/196] 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 00000000000000..96eb0d9ddb07ab --- /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 336a2e57ec0179..723080ede1d9ae 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 157/196] 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 d63c26865899cc..f44c18e80758bb 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 158/196] 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 6c949c046875f3..cb1834168e881c 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 35a1733787e7a2..082215da0a3fba 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 00000000000000..280f3b742b013c --- /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 00000000000000..3c2d30d8d9813d --- /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 159/196] 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 c979118abd0a07..7daea13d31c83d 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 ee66160be63b6f..60e8c2be1e2504 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 00000000000000..55ef5206c992cd --- /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 160/196] 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 | 54 ++++++++++--------- 3 files changed, 35 insertions(+), 24 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 70a32db663b293..c0f859a23e10b8 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 00000000000000..da34b67c952c7c --- /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 bb473dce68f65b..2a818f5f0205fd 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; - } - res = find_name_in_mro(type, name, out); - END_TYPE_LOCK(); + 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); + } /* 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 (version_tag == 0 || !MCACHE_CACHEABLE_NAME(name)) { + return 0; + } + + PyObject *res_obj = PyStackRef_AsPyObjectBorrow(*out); #if Py_GIL_DISABLED - update_cache_gil_disabled(entry, name, assigned_version, res_obj); + update_cache_gil_disabled(entry, name, version_tag, res_obj); #else - PyObject *old_value = update_cache(entry, name, assigned_version, res_obj); - Py_DECREF(old_value); + PyObject *old_value = update_cache(entry, name, version_tag, res_obj); + Py_DECREF(old_value); #endif - } - return has_version ? assigned_version : 0; + 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 161/196] 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 2a818f5f0205fd..7b4318e79fb2be 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 162/196] 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 00000000000000..c5f3982cc5416c --- /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 a3eeef373bf7fb..23f24d51c79e1a 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 75e81761f95e38..635fce3f2e6fad 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 163/196] 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 185226db43a92a..7ce5d0535b884e 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 164/196] 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 1c20fa2f0b6ae5..ae21dfdbf0ac44 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 165/196] 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 c40c45594f4d80..dd2e67841651d9 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 00000000000000..ce9aa286068819 --- /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 c0ab35cda191c8..a25b127f1011b8 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 f8d6d1ce89b54d..f853d309de9180 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 a4e111972bdad5..d9236dfb22835b 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 166/196] 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 e3e02097b1f550..c7dc69defded50 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 00000000000000..35ba57a95b0e7e --- /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 7eddc9bdc38a89..2059218029ea34 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 f3a22f3f6a87cb..6cb11562476e40 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 167/196] 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 e111bd59d4152c..a0e484b1c097c3 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 168/196] 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 00000000000000..bd42f32d6ae3f5 --- /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 74360a1c73c271..1e8c9c879f9aac 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 169/196] 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 7daea13d31c83d..459846e55ccf70 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 170/196] 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 73217136f14472..8993049a720b1c 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 0d81ff6765e1ed..3367ac485a590c 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 97eec618932aa5..e264433ca590bf 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 fd8525feb88d53..dfc8ef6d2c5b7e 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 da5fd16b8b6291..be8f6b057654c2 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 00000000000000..3bebc6660df825 --- /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 171/196] 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 ff020b52da3f23..9d30a14f112937 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 459846e55ccf70..d5b14216770906 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 zcmW(+dss~C_unOiFsKZ|NC;sNMzhyyAGZ_2phF153AxW9P6%6)K{N=1Fz$me2x<1a zW)R|pLDF#@bO>?A<&gVte}8|?^UU)!&8)rNwLZ6ZNZ&qvR!-u$;lB*)J#l)XsxHTI zl{jy%PFs#M#(HtSoJxLY;<(=vedO0yejFD+E^%C}{1^HWt9Z`8d0x|;z(_IXi?-IF zd=xJb?!@k?G@xdYZMJhcux1V)5tv14PxKmK7Qd8) zC-s@n&l>1S>du~Q`HJFxe|APu)#2`OOFDUYK%{upVsCitJlO_%!>x!akxuI-5bJ&> zcVaor{v|lFC?Eh!e5#Spz6j*rEpSLJIwQx4k>6Se|L@hI+3$~CHT5DxwXYy~MvF-9 z$~{P!;!Vcy|G_%HOBDL}D=0^eq>^3NVDO4Qkp=trLRm&Scz*7Lpl3(WZLz^4Q*fkm zU@3H)l;8*}sfM9}bshQ>Z=gd<-$-N5UYPM{wvNs)-^lo$ zD=4&Y8_cdbmc+qxq>_lnWO+B2`L;d85-!bfsE!9Rb5ISkd^{;xW+7MxS*4N{jmWaw zEV(1LFw3WlQsBl`k=)v4Qk%aTIJlB^cIRx26ru<5h6J_zJ%52OH*FX?$_7H+?o^TC zg^3bi^4CVlRVu)&*7*PRQ%%5pUX}6)Uc@AkF9)_6R9U_g-mw>N01@(`U!9TnyhORcjjV3)Jxr~c2D!!eA zAL)&!Li#!iM!$nT!+&DQup>}*p*;zQ^x&Dlf-D*9dBvI9Bv!v8EmrFsxz}@8iB}_x zp4ozSnbu<5{?WvJ7%pX2n@>@#@6pKOWu&j$m=*V2O$G>K7tgGrwAfR4F({3=XQ$A1 zZUlL5`jO-aBy({QSnQiwS=dyExKWZ8O-~~+`>fqEX(4c?tM;-k2bj39-0ojLmQ=4& zq*~GHNHK4Uw5H%QiSIVrYZ|IWa%JUO+w3N2@NWXTZredIVKbEHw?wX}94u3NQPDI7 zHZSTLdH;0B|F5Sws1ru-nH%YR7l8R+22es^WvpBCE*T%@!~gnLH6jbrm((QR?4#g0 zC6e!s^Dwc3k^b&p*x}|PZOdmt%I2HM)td~?;m9ji8=>%g&q%$2fvWp?@*UufR4d65 zJB7nq+N)^oz(5R`&Wo3mAnTfgET;3kvuZQuK4p~(-}iDDxqZx8)RQHjZc3+aF|=YF zan7gRCC_}C`}rg}M=T?Ma{#$Mt|H;aMc(^XI^_-25Y3C zM(HG;TxT~8{sXx(e{J0--%wTjj`tJYBHq;Oi-p+E>Pr-}^;=xE}KV z_2fUc#r7-Qn6*-mQ0tv5ay)* z`?v*$v5n|FIvU0|tr_Y5sRM&w2oo+Wg5PF`M(SJSfMA-%{N;1;zd7RkQ57{|zhlCO z>+s=l9ER%C;r@nyNOg^v8d~y|)Y4YLPFH33rg{qOIf5wncXK&I4`B6dMH?TdQ z$(Ae(aBw?MYg^0-b_l)ye)azUdI}2_s5e()M&T)R zI#-CEx|?B7`PoEO?WH z^yAL)OR7aWbnQoi0Ec)>pT6KaaT?q&>H@!fJGq54-cw^Ya(^wi8)ptjap!xx>p&U_ zQ^F)o>%NiPO44RFuTAb}bs+4z359i=pzO*hQoJmJHy2-FenAzycC?gKts3EaYZHfS z@z4M7$6Vu0m=YW3aHegAxQgef`xpTOvxY^w%>7}@rO#B-Z7s}ixRZp-n}91l2OjkV zXnn1Eq$+3ta3fzpXfF{O-rJ3_bR3#Ei!r>t4@QPhb4)v;#D_BvlYZ+bxb#oeNad=% zuqcbjP^AS(5nYJeQ&UP(t|iOqRjj|GzN4sLAmOsTDCFy@e9&y%b3T>yKNr!%#VbkL zZYD}jCquvbaOL_661wl?KQvrKSLQy##0C8*>iP>PTksz7R#f zBDtt2DfHr65PmoE+~9{G4jvEgtxFmA&uNJ0vmCiv@1Vf*kR?p>$2jjP4)OfA|F5U| z^A(8V-%?bcEuj8a!8ncj|KArsbOOHZ0WvjR0V&nwz8bR?qMRGRwKNeXPWy)3jlm$@ z?t@X?mw=`25VV~?2Cb@iMXGjG!k?y&4sk;h{5C1bVeC~I=S}j9v{{Zp#fu(f+1?qV zdK@6`)^mILKm}DeRs8$0%#4Ip#9I%rCYr|h+7FnEWNl3Na<*pI8pJM}OHv(+U2 zjOUBG$~#THpO*ionNAz0%3t$-5+5`9r2NC&SS!jl=ZpDzsT( zB;|4fo(7@9Z#fhQK%N`EVEWmEaiP2H7x(@TH(ioywa6mHjR1CP=yNp0`Y>sO8M$ve z?3OF5B+slGz$h%%(jQ)!bh!vJ`}$z%5I?N4Vv)n__y!A1LS$L-B@ko&l59t| zfoa!GQiX;8e?6TuS^+n@&~Ckw2EoIdI25Dz09TZ$b@~{=`TJ+I%o__?gA!5fyA*6O zJ{bD+C~P=fInwthhhx+a>Hbp{?p6(QNTt>Bc&|t3d3OR-Bf5jh(Hd?RJ|XcKNCmcY z%z0)#tL^l4WKjc({j`!rKb}IFSMTGP@97kpO>E;26DfxjkhSk>a^AfrZNIaObe92= zzf7m3zviO&wJUwAw-3c|C#z5%Wt=eo40qnb5>6h5b{m2m8gFl`HQhzNTi-x-iWXzn z>;c!ybS8?8L3kWNLUMDdO~OaynglcBReAs1o4{O;qfs?{GW$6G1?n$(B*Vx6=Jf8x z>yP=$e=`GIiNAnmh6C1YU4@+Ji{1a5;xNVgV9qK#y0*Dsex4I8w+?{qT%f}>tS{_5 zHaSvog}?`s6Aj&$LZjnh4&@(K@ax)=Op7w$uQ~Fb{~iankgX_Om<#HpKcHaM9xxC8 zfwAY_0oR8oOZO%?C}WZ%q_`&fwVH^gUvgmOa}(-MHiq(cZ;8_`k%FR|kSQ*Ul^ptu zxKE8Jw|EA{{xX9KM_k7bMH!@DY*R(+6 zik6h3J%I%?vY6m1k+`4Rc=ekDOn6lSe!3szPHKRcz<9k z`8TyIn&g6^eKrc6{g9iE4%LTxs471s#U6MALeplEYPbZ$o78l;qZdNKXhozct{Yt2 z*eOzNN`?LEI*wfZVKA?~NXqXUq1JT|TD)RmN_G*dpN;{p!W7|2%Y-IgMHp4`5OmEK zgWnY;uIx6!(Q8$0R6OXwl$TCI-lu<%n;ZaH$1jk6^hU}0WHsr1cCzfh*^iKlE8k*2DoAWm->)#f%y%R!~+-JQaMOOR>Mchp^^4x_`VXN)SkI&g?@^ zuQ|-!V<1?5YY4^*2bjAjhwaB-Cz0=fbHZvml0F5Yc<8&<_gFq8oUemoji0=-$pUf@ zR}VqD*Pn0Ca=5uV=yb&C&^X>L^<-MwRE!o){lt&&3}MJC|x3`SGSaQHRpw@BCZ z88Gl^7IBSs!_ngU4$p|S5Y_$wx*H-K6l+E5mUafNpg^lo&4*J@SE2Fr1&BYl6h&Pf zv@PxJ;Of-Dd`C7#Z9M}kCwfP!Kh*|BkwD_q{Zide*GN&mhxw$0V4j;gFK)A7}BRu@xj8zr{4e?!dHT8)N|9 z3MckkO371uVBdLu4$V;&)*2od>308s3Mrkb`tJf)r@_nyO<|CtZ=`8+2YI*cvg;p+ z@Y{^G4%49oNQycM&K95fNlC3Dg%lT`t9%RGbPbfjl(tBz3+Coyv>Rm7oD<$z9Z|5xPdFVU7X%4WV}tV}gg!|orgPscTz z(fX!6S(0s1Y)D)3p$Qn;yn|8u>}A0p23WhF~du}ck8Pc?9u zRAKO8T?f*aui|Tn!I93}UHDYTW>k%>4qW^75jM|O_|`lN3rE$!v?^ODE-nNYj0khM zGdxfcF%G#SV!&zNwsmzVv{x#nwwpw%%^rS6vV6`@r{fW? zO=Ma4P4auXlt%tXq)`s1lKFYeJS~`VBh~21FJLL|G~}Ajmx_k9!`RpZptt>$V&=3( z&x9xndolu}{_%Ere0ZGkY8RFK;sD=1O;D)PQBo~E%qP9P!)#5Sv%+0nsHAv4>N5M2 z$7??5$3{|NKoBa1R3%Qc62+cj%(mt=h^2F(Y{F@lvn>$Kc{yPDXBevgk~#kS`B=f% zaeN!8!w(hJv3z$Otk_|}+{7J_xVa_?mLUFPw?`;0t|1lDH59Z1_?UeUN&n^$j}cDd zR`6Q0`@6i~j%)fkKcL?9FE5tW;?;w9fHJ?Iycg@CC;DH;2Wqf5w522FXf5Pscav1N zS3=ReY~-$F=lOjZPX%`~*{(MaDC%S&y*$2yeAZ5v`%;_tX0e${QdXiRIE(aSd&9Z+ zsWh_BQM%uA0O`BQ`b2<&va;)9K}Z%0I<^A2w`OhG^8V=Aa}|X26e-@*9r^Gk#Kp$r zmA{@*>0$vVsxMRQWqA)g+X9w@wOGZ3`=Gg0lM*_D@ap>VBh& zD<8r6qBa!{7Ezd0jm2*cK;`;_AX>XKS8xOhW9#zz_4Co18-V5NHCPh$ih}M=M%U|& zEZr{vi}fcl;dmNw={=dsu}&H@bPakM^NRdAXRuTAnvDNx9s+i(A8hkcU_NM z_#yj;DgKeB5Fbcb{Th6`o`i&2`4F`;1oaDRF~y=G_{#@*&uwjsaVIt8S$707qxK+I zvO=p0na$LBay_=)rqloxq4NTzW+aiWVhPKixPv-fUWxftc9W}#7j9w8X-1{ZT-WY^W7?xzic{s*SttRirzTv z;RAB+vjDgJq@?h~vz*_XVMSS6imJDfmG6>wQ_^-Q&PklYBI zUeOn}hozvp;vu+mCPV&b4LZ-Sm;8oI#u<%Y5I-&w0}D2g(*Go=74v1>T1`?kO9fl6 z%goxvM&$+#rN=%Z->=Jv>ljQEckZM69~WTip?#G7eiXj!no4C$;%U#?Fj~V|W!)=> zad(n zeZf@y7}KOR$Mmzm$;x1el+?^b&a|8SmX9V`Z~XxGJH=C3H#hiR`^xxbQ&0$)&-)a2 zK>zNIQNQ*RKmXG*OxV4Y&HuO^4Zc+{XZbF)9veW0&41z=aTBQrJc9f7(a7yF+G9I< zp=n}-EVv4Yzw$xmY{I~^V997P8JJcd9%OlT}zRZ<*I8$Yw0&^WBydlTt`LojG#2|0c5@%exDq_PK< zsFbUOzU>x}0d*i9-$vZ;^?CESO;ob-JQzldA})p?)P0e0L8DRcjD^x6z0f~B3Uw_O z!?Q`7QM|sMty^~xg%>$6=G-ofeSeMRTu(q_pIwwh8z70@1=HQ(EOW7pS1Je5x6-<( z$_HAr|CoHP|6_jRs-QdOfRr-uI2k^LLhRkqq-?MOd|F;W&2$fh+1{X`X*;}c>42&M z<4`|jqm*1{2^POSMq&H=Vm~aTk}WCVsEoUKWWqC$d^U@8ANJw2y(386+mshqo@J(HImG?l+wL^#NNha`k}kAIeZ7ld zy>tdsHz_deT}RA*(FK+7uQGRSEgG`dQFi@GSmo+X;`XWRs&9#8@KI4oog)xiU)EfP z5nPG45Vz_#-dVnu1p5YvOXbPvk~w%~Jqyu9VeI^iApR4By++MM{b47h&fJR?1tK$K zA41`u27pU8q9@avm9*)B^f8m%Bdt7lqZ^<5*Ar&k)dCZn_M_P2^1PooiVWX(q2c3K zmi;;kh4qd2_<2jocl3GKv%*Y8CT|pO|AEE^Dl8cE1$BJ|+_!ZFCZ32x_uN8WwRk$t z%Gyq;jXR*b=rK9@=e)j#FH?lwXIb-q$DpOr?kaJRxD(lEKvjf>qw}rHSSCJ*{2R!^^8|edI z@$Xu$AkU+bFzrZVQXEJCab&s_)UGWi`&U6*O+9)#q+;nRZybN@09y96V0xp>b$2|q zd(V|I#$Rz-SFB1aWtljtP6B{z%+0E zM3ti-Xad40endkQDh`p=zY|(#oPdP+T`=(FOVm%);zZvwSaD21<*geKez*_1mo1}S z!)jsqr1!+xjzlPm>rrBjD%7jdFm&e)BW0e1k&NBFRB$-U(55X*po7}Nh$;2NcA+aTizX(!pP8#vkgD`f;28vy>67-&hq_cK} z%r=!tU;LBjEZ%%!W_v@2K!yjuq!yVMwFB$nBhN&%3q-Jv-VkzflvAn>SOd z7N3ET+m|fU;+b#KJyv$QJ0<;F1YrZFP-tE?OsxJJB_CRWWgU03gtBy0dFO+E%^DW> zREMd9tz`UrII446vz+P?xTf)W^t}~~T}{QPU*V7WSEAA73`CWo3*|Pu50*z2r2i#F z3Ld(Ga;hoFI7Nx!NkfU(hhow0iIn@M1?>qON9R)96g5CkQt$N?x2ZpcH1UP8uKtx!M0MEpQ*yAee)&b*1pz? z8aJ9>rF!+=xY$tD?%B!`ot#(0gVk^~#@$ znv3U|X`B*^ZrphLv8BsP7?7te#KzJIea+ zKLH>P6zKkX9fnlzPwt2L(w?+PTGagvIc<@Y)QiaSRzuEBfqaSP1G_R}1FCdZ$=&@U zxPE9Mq|b0t%+`bY+7i;8sRpK?x}YCd%s&a(k0$SN;P=~V)QvbHb9#<>Rvm+j&Cii| z=Y}?adp2+PJz!koRNi$b7~Iyiyt7U_ zbgyrOwYsf9&5;;v-*PJ&±akcRs7N0KTrMAp>3nNW8q=-Vl&B=#&zz8XRXa}23( z)_{tcW2oZdYnZm873Kdk7FB=eNc&oD!fz#QQ1$H$l;224*TWf9YD_})mJ#H8UBtn7IPb&6FW4xbO=`9m?dax!OO!LEGsRD;PSfgpQ>z6#uN*S4x`u zg<+>`GEYh-uGtp8{iqCz9vqF?_a{@5Pb4NCD`3t88KCYo8N}3o?Mg#;RE*gVX^U52 z*2B)Ya(pJbV;i9`e>RE(ig|8?H@YWeOKx_A_nT9lRMSgXT=O2J{QEcJZuXb-cL$O3 z>}~MzsX>`*2cx*ito<=`6UM#hi9zzrwPtL@(11`Xyd!In)8>)t!ZUEzX#oPAr8Dfhq>at2nXGTa5uvbrp~ybmhoYd{~C%e!Yy25a{a5~^M2 zRii2xmtPj4n*1Du=B2!O)G`e9+5%zkT48SKSx9eQi)>|8p-q>2R1*H2%{}cRXGJn8 zd){VU2d|~<4-GK8QUdX&NoY8CnpN~|fQElIfcq8k6?J=~TdEGuc1Gk{zJ%i$t5C?O zC*#RjbSqbZ@1F(0?N8vjbyxE|$rqWhxP)&QDr7dErEte$!&$Cc9y$UP&{Q?@6 z)dfqDjJKP70CVsMCjKqK$nlSf`>Q4!vdJd%EnitytZwIiEQS^my#$k{u9-!rH+ z`R_@fL{}$Lmn@QJX$=x{UP`uEwOG~@S<9?65?oy}px{~x2*-Cb?)hO}Cq81%KMay5 zxFd+hAKJpFeX;D>QuvVD6;(k6;0#bR{g5aKwjUz1s(>jz7L)73Jj(1aoZcB_O=jvG zD5@Jz_ot0Olem|eZx2J&n`2<9dIGGwqS3ah8r)|~(Uy}2=KRH2u&V?L-*iV$h3u&; zTLb#X9l&khD;X-fvkGkiOKhc~imqKqZ1;hc{?n9%iotwE$1N;mj;y_{34^FV)?rfg zARKdW8IFIEiCmyk>pOcS79P@*__Z@6Os`I!q$K9oq^kVfV%U><*{Ev}2BpCVu-DFp zsIp$-&F`w?y9-Cjx&K#b(XW?C>{^$S8#X1wnx5pUKO3yqyOYj$DkPj}L1oteSZ-l+ z`S<-sn)q)_Q+ASB8Wc)G?mUP(xCGqm5<#4`3QSMxF`?*J-aU0YQ>D~ldcVy)S7p2u zs%?boyvZQ!Z;w$acfr{(l{YoX0M#OqtlM_5sDoE1r^y`ZA$!m*`)(jh^he2c;CIsZ zX@v!r4a`_F17qW^L28S}XgC>z#uyW1g)T(h(BTj=ZxXsg)1h!^V|3 zoc>=VuH9~XD6_J{kJZT>)Q}QVtB_e&jkx~h5=Ze&G50j+pL7MY&qBo7Ka zHL5r}m^J;dmv3Wo$7J%x+%VbGImMhiDub|iF^k&01l^TKK~Aef7;o30F|8(YUNUDh z#S!;yXWp}5qO$9)Xqt8*m7N_!`XyahuPZ%BELOsvJb$un7{StWs!;CEx@2uo%xp{Z zm?~|Lq?)mk7t@o$wyzrK`pyOC-;X4&ht=*0pT{iEr!uZ~Ft1AcA!WC&go>I8VEL~# zntuNb!j|b^F13RusS7z*rm*~k)8xKCkJgRfNr7S(skc66_xS{Jwfzfp57SuT`-xc4 zP0r069VFxLICSl*fTD*pvEm>38Lsb#h9-SLRrD2{OTO?be8*cJ6!M14)tPXhE$^x} zkCokJ%sTG_^WFA|Da@~!yHv+i$2u`_eJ5~UXbFki`(S27dkjrkgGah9LyxR^E1&j2 zOS7F!Jo8v9jBiP~lZu%opgyy`U&?xgwUTG+YVba`2?hO7tk^jS{crWh-0m`mn|eZ< z-F`bIM@G_&n6+eT`zHyTtCBgR2kB>TkScDxWrnyK%=PIa6GQDxkEfY#St{e|J(oB` z81K2pgQdp_-jI*-cl#=d85<>YP%3kWu4df8Hj+@k9!n~Af#KmYFf0neFj?Oc%LsI{ z-CzlP#7x;^*|kO6Y0OKJ+^rAM!RXzT$ZIL9_XIibbCef{_h9$`6R?7+qwl!{$^W^<7Y|Y=x?A;~=)c4qVw>-aXeOW7SZ*J6C?Tn$_Lan<_I)@6}9vc!cTt z-(k5cZps*E6jMy<#>A@Id2YyEKI}mt+GYo$-+(2kD^14yQn^<@|AIoSx5OQ*rp?W& zM9P=%SlN$NEXrXv3`&DQNsC%9^%{ zsxMkjrQLY)o5)j1frZ(|9cH>ZvCMFEKGRLx#B2xmFlP^*IiCa52XEn>&GUI-;wN4m zRtNNnrzN5Ih?G0Y$P#R;nfqZ)X6RdoB@8t}+1YiFeX1_zpSm8=v(!bx& zbSt(qedQXU@jV63z;N^l{1X#mN1@LKgFK6pfs5a$Rjl%-@Us6Gp%0tqo03U@e8B4Gpl&Spj-Z_7Vs zOtW+6c51nBS$BcYkY$NM-5c>2s zxD?|-m^hy|`LzN=W(($O>IJ3^xlG-#AyaRwLawV`RPgc=b3L#zm9A9o--Fu!`6p3B zK7!d>kp0csSbk{=O5Qq*?<~)zX_B2&D9@N?w5F&(m$BFvjOl!RSnR9kph``Fyr5O6 zmvwA$tn76(bpto8ha_AnkYZ-9Bh}}sR61ufWj<*~Ww~X{^GmRN_Cmq>NY3G%Jj&-k ztt|Vh&zZ8pDW-v@B)-03H%0Nx6F(8eXOqCyG6uNI)j%}u(<-`anYi|e`y?cUti4p*+tey>PnW;6J&oy&Q6-&NWSv3aRtgVY*7{D#>o)*O9rY^FG23BKQXkG ztgDwCm-8({?Z>ZeB9$?p?HeF#%@1qJ+$@V}RQ1TiXF;!DYm?04c|9s9cSIoR>OW&T zWgl{RHDE&AK&J521Fqk3;MT^2?d41mrI);-<0!`MXm7VRJ0fRYx@w(S4xU@w4DM$r zv0(TLh?VN0aI`(BD)vjB5x=plrwb{*uqAb!yN^m|j3RwXJ5q}RsfTul*yfj+?GF{Y zt6bw1?E*33g%`SinF?X;dZBRQEN|RB992t~ga7L;Sk}!2&T-elH*pQPcWvkON00HY z6_c3jQ9E}3Tvf_($k-`I{tfT*n6lzJ;~dv{=h>A~LBBVkcq{uZRbnve+z>4P711{> z8l79bq@)J-AY7p)eZNh-*dT|Ajb=$%eHAFK^5(}+%#d?v^4SYcK&978P+zVrpU1st zhU_;}tbZ1>n%9sb>=hH`43hHu52hJe09lj0Nz9$Vha9azn(19h-S#{4Up$)JyHlC% zRwKq8sn80SKZEL8dr0WC8T8$2f?@myCSDlE+iWkGFn9v5s+z*vyjnu?=hj%(d-MR)9Z`wt3J0*S{8;z1D+1>kkkoo!46YPD{=sompt3 zr_BF%PR`y0kx<#j#DTJQ)xHX-jx1*S3x9*F>R1rO2n?DWCg-cdF|5Nteyk(&q76(n zJeBlSA27?2%~I0QH%v3`Ayn*o%eeFtdFfZY$fg=dv44MI$+stxb&Z_kKDJ*HX_Qp4 zK>qxi&v=``4C;rKp=|DT=FG72$*tsUa^7LylD(T3c6R`O3!quQ1fpiOM)&Ix;PiVY zIjeS%HYP5SHN?BD@PwSn9M**tK{EHw>OrPw>maB!fN~FeqbcuqW_)V}@l-=Pg!tM&3RCDfaYB&Cu53rJU_lV|HE_)9#VeUd%<^Nxw;EE>G9%f(ZDy9Hb4j=B856%A zvwQY_X0eOzf$y>Zn5Ff0$#?x%_DvN>CAZ!)i*Y=uy$&+2Zk$~|Ctu>G%D!LqJ$&x- zG!S=qLs{q#CT_UKi@|lta-x7YMAQPEwlySV^hf=eL{Rw#qi4W)F!Yf3)rL)4%eEv^ z*!Ho);3#I2eU{KrYXldgIe(#jXACdR7^bIO1JDKm=^AIN0 z#EBP;xSJSBO`7}tHE*3VO!G`C#9 z_o+ha8$K*)O=VIH8bg+fA56GEj0$es88sBMnW7$*L zeUe3Y$bSbZL))b4DL1`SAsU3Tu$L>nE@@EnuNHoF6KsQJ-dpDi zgnX9g*XeAqEU-zgDqfIyM$WQZyRoeEgQ?(25#wSWMi}~3BlE>PDE(HK{>RT^p7~RV z-w68FxVFqq`;u5w{>{$8yyy5Zra#?C)_WRh#e9EoeX9cD$Nb4Nzcqw7y+}W#BRF-l zKt;pkXWavJ^-{pR|0{^!=Yg|He>wN{kT2(Zk-K9{W^0;2?jz5ba@P}<_@{~t*XuxR z+m__{G#-L{<k7UL3oRcXt~G&K+04R#XBp&zfWCgvSuKCK6TI-9i6P zM|8HDD@7fvjGVjH8O75{pkLCHsq0i>`g=E6iQgs0r7nz6ZS|6MHZv%PJYrnxiCeqpw#%V4fu#EcE)jN5b$ZC6U6eBmFcdHMzlmieRNZ#M|H z1j%(I4GcrN$zF9m$y%uoaolz$IGakw6%|a;b1(Q$_9uO=mPMtiD5f-;#4qxlnsHhx zIxK4oox=Ev5cv$vs)fSb97+8Aj(1nv%a1p*#Y$ayE9pMl5?EVhRh zWr3k21S;mBz{=R`#yNVY{@l% zn=_W_Y`=l{IFq-?8n`k%52AjNb*R$;sIMIZ1@$|i7<$HTtJ@m6;a{}Vev!52*{3B{ z9Rq~MK4siqkc6I_CF{I2rhc^z63$4BYrF?+-Llwybv2pG`ZCo|`5wpHQ(Eillg#s3qC<~F^9r`-Fbtf3}PRbGS|r^kiIFLxWdpp zuBa7Lot?sriZrkdmowc`C&u}ZI-?30E*xgUsF7f) zmMfKP*bQQ{p5S?(4~FlLK)5;%3OXv0%dMB^`XuMe4=DJ;IWp#56DH+ObIAO|%@pG} z;9h){oVN2)u3S$}TF8uLMo=~~ve0Fpz>w6D=?2{c{m<1>S+dMeRc#`a=if2s#RI%x zJp#Jl`$B4x4x<$N!IfPKNqrxKd-^fnH~bY;eA>f8Umb+d%yy*c?*sY{2BuPNlT?G| zfsxXfII~Qy+kGY#1ygEhJ^6k_Q}SGFNhFAh@zxLGHoVP%?2lBz-#ux=A;IGmOeJ>@0?)t%sR%(MC|ckU3`i zKlzxK^~uz=53_XLD@9HGi;35LAvd&=?9F%5CO?z$a8EC=YHlz?y>Xx$H-TACn1H*Q zrp;|6LGGYb_}{KATU81ow^bXrMAj$m-n_Z2HgXDWUctAg5W1&?Sxc6JK0A~-o3G$= z5AOg=B$LEdSv zE}EIYUP*=}Wi04PAlcf~A=Mi%RvIPa!%3ULxt=5UGH(ctaWc*2Q%rpEC(G?E(@%a^2Fk$ta;pvzdp#C!8W<#$2Syp(;vH&6Ij zzf{owy%EHsdc5&jiJYanq}6x*2*UYld{mLlgX$Ns*eY3|2p`7WwdDDjmIY!qX%*+Y zgLr+Uq`Z*_!pIR)c1Bec$9PMw5dn<*?}y!ZoRjtFb9V8Pob_yVPpeoMf$ldR-sF`J z?yFN|f3hVcq-_JYctO_s)*+O@O_ZSoQ?%Nw`ClNN7qO~?ZuK}W(?ElYEjhC z92Py+j}!^-nYv9F%bZe$bX%u^VEoKn*?}OY7c$e7jV$WICYFoY%u`p(IPDBsJLx5P z;*Nqa{{bJW%m%}e6maL~@y;&C!SG@v(+oHQy^hr;)AD!_mIM)(E%27RDrS+fn(#WG z7x-0-`@>@wemyShF;DoUuoKKOW*Rt)P0Y1023#{5G9l>@h^tN7ibtzK@gxGAbqDgE zVHOa(Y}VSgTn3eY3SY7L66nfLGF9~*;JLGunH~*+g25ZXqQ1bJ8aJ1JZ=N=xl6?L@ zH`8W)sEuN(QEO>+P~!BOh|nWH8FwYxZt5QnTvR=6@|Q4FomkIXZkz#k%~s%P&>w6W zbAbzdou?W)AAFz5{a3FO80+0&s`FcU+fI4j|M}ML9MnNl+5K72^GallOJ`9IFEZY} z!VG?~OyA@UQ`HECq)M-tdQNL_54px%a%Qg}Yd=#yKfo0EvzVBjrWNsvWY)+%4@>AX%zx;cXf1GQSmKV_fg`aC}B@1vj|DRZrZQ{=2~Z*V?b!*f1^ zAv3iWsr(v1(!nQ8pSFq@6C-7B-eTt#SCzzuZzNs4w@etAz?3^*F^}aiD_Ojhac6JI z{@)cocgWvzA4P&ey2w;b1?IVVfSG3PXC-ON822c_F7$50)Gd-h+|pV~IBWrZz$IQ^ zIRxCBM}e^VtyIu(B^Vz+mwPY~?yppmC$XYV$%xJAl@?ADTy7sNWqsbCp+~ zGlIFAk=gn$0DbX(rhhN%x6hKnIj9z>UwX?t$<7;k{R-|tE3Z4Ml<%12@xqR_yr|mC zm)v{JoXMkj_bXYeJll~^JyjFkXHxlu(TBjjx{P=4Oabvy7`WeXpzg^-{s%AO%H(YQ z%s0$Zbq()2)lkmmSF&^C*4dr=Nit{NVd{dO%vH05xkt%*{k=`hY;?#y6wdp`6f*so z0pNZoXT_G+WzJ>UOkBB3)&eq^Fuk*!*%-*we+~rqKP2f!ndSVZf)~96&`)a&To?Ji zQrSe{2K~is0r8OeL*997n}X+J2IF?m<+)e4wcL^*$+<@>=b7J2dh2pt|66P3u0BEL zPo0@-jt_V=^_b3YJ&3P1Nv4%MfJ^#At3Pmr*VmCT+zY3iO%DhCr4rsYKrcUovCQ`C z2=L%B=6Tc&JgZ{Cnd1lQT^xwDukx;Vf7uf!S)&X@Vfr2UzSCvic}@1hJKba4$Q``+ z`v?S$T!yyb>D&=YMwK!lxR$(!-!tc@ExaZ3 zF3-iV2yRmYyXu`u%4Lk1hBasUQx}%Y@?uF#c zH_AGfQF1=E$lCfRjWF&a&rLS*!ofut>0Mv_8V3UiCEc~x#_rtpzYq#yC`FvK+sqEB&ilPgpvU#neKtiwVpiZg?)eX zw&~SDAHSb>j>zCu`?mAW(Xu9z>*Q76b)eE0^RXERm^1!7&%K``xpjy5ia{s9eK&_! zKRPU9*-~Ehah;5>0zue39=KUyP!?}ywwVpUwB#cb@hZ=8A-T?imOR&Ly;dA^#jYAI zW0NyirKp34n60wFM8_HCTCkF-7UoI5KlU| zF6714V`bfY-2ZiS-ElHrU;naL-Dqp|NAHZ1*q!HGZld=giC!L2f&_~s`p>l%yXs)0 zmq+i6Rd=3q8(RW1{U66QBUjNL;?wH-@-gC~koO3S_lWHRy5oNN?K9eoI z@Ax}3rGz8Zn2g3P57;(k!!{8f0Q)_TRfsiA~n zw7%(IDr3H_Sm`_}v*98o3bX)k(b3BDq%XJXS5S7I@mzc}1x3yJAZy+*y$6~pwm%4& zjk9R&FG5DKpOhTGAB<|dkVQs=w(6if8#Y;_TZkp+2nAm^;4CNA_7T^C6}O#)(yi%S zTdj~BxROiHV>A3N9~Wn5fNY)!;(uqUx3LOz7UNpRV8D};+l4j~r@arXeK((5;28EM*^g2D1BaXs!JLd>-8Wd&%qp+_p6Z#`jJe=S$KTnnYoEvNIGC22Nvk&@T8 znsz0rJoB6Lh-{*)+2gr>aRGJOTwu3XJ67LVCA!uD;apO3#caqu@Vs(cO$TZJg?e2x z5dG^TTl$O1R!(-s*NQdfi7Td=>^v4qNhwFebpcL^J>TB=$ zf%5(;xHsoO@I(&Iy6z5na_8mUmo8SU&2u`B-+?~&76og@@Gexwy-Mm(5@B_*jiJbfM4E4^!9AaMR)H?x^T_Jl zgkuWip<$@Y-9hG0@r`8B}*t)IT{$@JNt{!dZd6X(g%`8y;>E5Kd&HLdkU3`QoXa8gaBS4r|_TB3V{_Tu3^ z;wHURpwB>_z-p*q&1f#FXP~aeQIGVazc|$s-xMdV?RlylchUp5K2uD8dq~b2g$%w7 z>4K$^t^O%wzexv{`c=qo@*3ELpiip5K(0ycxX}n^C3eikrT_r;A!1n(I?u#(6Y$Z&$&sOk^8_mVAW#COlZY*2{ ztlw}`JXr>;NkygIBw*uCm?C))=vp(0Pk#fk9aFd-yZ{1ONz^wd9dLO)SW_;7{$`~z z;1~pZleQa~3T$9Ehs|mLl5a&es<7#=-BIZSg-~~*+PGssZt>9UbH^fzCA3brn{j1y z-vn%NcO@q+Lr>OFCFfUF-l=1heIprNCxQATdw}KarC6XVw_4R#*3B61zI=sDEOW%b zc^GLhQRz~7@z5E)6S8<*PwlE=ZN!EcjG>UB%Ly311tE% z)5{>Atu?(>Mi3v12d}>c@k-*+LvMiW^Bb@WgCJZm2WO{xgVDbz7rhFpa9Uv=7|?>W zNEB%z2dqmj&1Eb#?W5!^ocx4~cbmX28sbLX&0x<-2HA2wc zoOa~Xt)zPoI&xMcWIZ-JqGDT$%Mp$}i{^dy^$D?FCxA^JWO@#D=OT{*-XF=!Zaf#< zCKPwyo&h#<6xhZ70eN8noyqhNzK79&wFvR=F3Mk;?kV_lGOghgV8NHBNI46B5AE}^ z15o{I@~y`21=bSsTLrQ) z{rjT(K%VZP+$}pmv|OZ&$1_2%n~3_S+8}o~MOJix8MZ4cd3=`>_+q-UW=+Q-zs@86 za35K2immr$lx(ydTsmLLN*{MbW_u;q6;-yUr_zItV_5bj53wSMA)hPxPXq2f9;d8f zwYZ&8h&;YWrtqFZowt^vZ$aqFU{ilVe0&=W&k4xPwUxY74c2th#$yl|o=2F`d?NP6=f<+YH`jsfwK=zVc=tihn6S zHxxrTY?>*1dlXxoA>dIQS1;88FLAzd^wf4 z)=9~US25vOS0#U2Vv1~?Rpd-L?s?#&Gs9l);U$!A-WEjhKhRS+T3P=t!QiSbN-XJx zGK;uYy@trVkC4?ai#mU66i4$Q3r#Rt=4D5Jb`{u+fsWn&0C9khKB?<)mUh)lSkj5> z?)^c&%)zbsJ3xBpfZgymXnzl2F}b*IS{#GD3Xx{-q;zlM_xl!yf{BbXPfKtI+ymqO zW^il#3ih`vIEyF8p#xR~;vl)@*;kJ2nrgBdZ;>H)?AZP^+d&w!agMT^ zrem0zX>R`G!}O|sBfO*JZ87J96Xim@-!gEiYLn`XD!KR)Go zSD)*iWt6Tn3&h38Xx#Z3#j+h3v6m@p@>H~MEmh)mSCsRJTg~Tm=fxK&^HxI^cpoor zC;h-q{R`~G zr%u9dTE}gI?lYj*S0yn}K8lM1J;10yaa?aKtvz`dTV``P{sMT1_2OFn3Sxc@)F+RC zxcw8dCtFAdpMw8*X&_@5XL;s<==BXZK3NRj!ELBstOt=u`@do>~JVhG)l^e4q! zAP$)G#9_sDo342oS>mOT6+`~yr`0gHB3ZGD8&UKxtE^_vQQXZ={JaEd(}$*~O&w*; zJdU0gocbY8(cMRNwem8@p4OUr0+|q=Mzdo%y*%OL3QB$;AFkmC)Q{(*UT_#AyHXTu zzX*fTE0oOlJqE^=R(el&)SnGOcDM<$lQE9GSO$%|+d(e8f|8_@|vQNZ9HM>mV1$XQzR6*7f*B5 z`7!u+qOyA~Le{B)(#vnsT7PUB{R%4ib6Ie^RaR{1YV^|FsP?}=JzXeSp&*8TYNm|o z3cNFXG)q{M>vqJEe?JA0=Q(Kxs3A)0SJY!hD=V}P^%}Z6Fe4e+GpZpQN1@&!QB0s1 zy}!s|ssZYA0XoycQ0}JnO#R*w8@(aZsHwm%P}eiy}cp61}5c>_AB1Yz|9@bv6L9`Ow@a!lkp*B`(( zUo`Do7eO8l)9>*ku&Y$7?`#I?Z_TYwh%4^3xUR7Ry!ShEcQLJJ*SsJzXg%BZQ~K;| zh+L-_`irpiWi^^tx@F4UsmNYb^7$uMqdB_Uj%WNhB^ORbw(3)5Kl~Y4)p*DLo$@}t zA-E}}6}vSOJ%?&5_d*1N!-*Sw*BW)WiDCt5FR#QYqeVsTv8qxZ=q6!tKE+mTaE#G^ zV0dh2(qlAp@zWAzL@h?|S51|!GMzl-0IlUWDBJ(y=)c>bLK6pO6EUSQXEIXdn# zc{wA}b^nhzTX)Kog-UbjB~L{B2s%V{EWI^|o3tJS8Myu4fKmQAdS69x`$Hxg*(l#f zmInLjThM!R()S;MTg^*7sJmc)J%#IIw`mq@B-q8TgH`GXy5)#BY)bVR8`D70eOcD) z^`NJa=fBT}gq1YsJ8C1aRmA(xZh+vZCQ4^p0Cv8%ioNa*dPO%BW3$noeTVGYD<8W~ zeX7kn9An&2%KQEpN$jYkKOJ?S0;sROM!7EzyhDmo&8vdmwpEmD`2hW_p%PzBK+)Pq zI+H%r*I2nDN^osdS8n`s2xJx_y}u~lD)tcV+Vv?e6$a)kRMyJ1bT?c_J$yHLa#tO>QUlBQJru4|gR?3NOjeWp%LQ@ZzB~h3Edmkj zM9*>pM0`nbmp%fKUtxmDxG^_7&4Fa&^5!v9K6(psBLk847{Zf1+*)%V-2RgYXYPSp z_8_pQF39DZ(drupHfoJyd>I0Fa%ryXZv%hIXWZ_*0p#bMxVw21$j3*(&P$wpE$Mfe z3SxH`y6bKLxUZ5?6e&b==k2L~C(Jt zb-?8;rPrD!LoqtPY>X?_~zf{`dozB1W9K|QlAz_w>cqX_AR zFS|JYeWf`YRnKI9mFKcuNs!wwfg7F%;z%zrhzp2QXIo!>w=FOL@aOV;@8+*Lsc zPie>5tu0_5CH`A~E66B%f8rL9zdb}&a~XIdpDVFt6y0}8eA+G#xGQa`60`Q$rH_ZHR4wsJP1aa4+jvhb*cOxJt zD-5-GUvNM+t??d21C9can0J->pBkSEDjY@kOcb4?mDscZ7 zf`s&sx#jGJgvpySk>;sA0^KvuXcl2VY5jqwaUv60;SpxAZEnJ>RP@qaV9d84bqm7% zx?P;$m>Q%l4}n{V;`V4x?x|UVbbb;9`$j4EnxwiweWGLCl@4f>pC>45!wz&micB>bhgoI2N(J1Orrc|ngz z23B}B`4M%%I8L?DNAF3>05 z2cAy|gPW!R8%sK8Z5#5*tDqErnR?t}WYy33?0vCHF5TkTqdF)(%a4(+d8j|S37L*g zw;EhS7T#m(3E7my(P(5AR(kwFw3d`p?9v4%Qo9QIAxj|qOGWbavhzT0(n&j4fN_)f z!Q857H@SoQ2jWq>`Wgi$Lei zjw0n3VCz3|!iS4-cBiSytXCixl>m3lLXhnyfhbiMT(O4!A@(;1@43(R^<97apWJ@nC^=8;NMtTx!dM|@uo20&gbN3`v`BMK$oF7e^AYo zNqLC-OmJj!b0tcCjI3IWk~f#2JUzpalh4u|<3*D_d5LC(XOfvzmwVkJ|EM%rZ7HwY7vysPA7Bq`%8k4( z=ojrkHuwW%r738vr}g}@kg4Au2G2XveecsCVRL=%rtE-(H4I{D|^|gsJ`2uLiq@v7Jba!zg>e2Z?RR03q6~y;m#-g~o1=zJ! zjvJGc>S!sS!9IZObj1`7;nl_tAa8t3HEj{Fif9@S4uNrLA&NR-(4U9UXhb?QCYNa! zy$-BbG#KhCNSCnbaR#{cn{c-e`6bzi`}}itSM7US3r4}&=Igm970mb|J- zvs&B0TZZDAyZ|xyzZygQ_nQYO;sf9rU{LKFKwOyg$@5qcF9BumIi?;!IsMbAkk!4e z(uJeZh^|UKWAdbQdt^t_Pl zB71+z6n}K5T9ydnN_n(jEvFg&y^iijm>sawMHR;7z`dq5eHYECQVx%AN__-c`#)}* zR*l^t3im~$;Avo$PSD<8q<=Fw{?70NCa}xA)`nnazEhMjXrvl^a%b>rk zN%ik6_5F@Hj8XlZOB}!DZU}x|iA%m2j9?{hH`)Mhfj!`+t^qf859(+0L4H+%=83-o z5lz_ox;(Jv)lpVjYr2CposX>;^0JCbUZFm2y&A+52cmm^CRzsJaktH;mGc7r=c(D{ zUZ5EH0~!yb=`76z^zWw{vUQXxUKCSC&La@HSV*~peuc0vO3CtfOr3ZS<@v)X$DTy} zw4IWBc4P2%W5rIdK{kCK8fzAy&Xb$?*;HixCYX9^50w9m2B9iZ4g{!YdDO91lD5n} zGi22NKv8GYcs+*ViRNz#l~e!q{j4gxke#gz`tLHxhU_8FatmROC!T#lda2iO z$3MJ=5;gq9TWBpitVFi5rzr=YA|I${oST@1_LwAO%d#uG>kM=c=2y(0%NM-hQO0*$ z!N|<7bioT?4(Xw3rxD4dbd!W-7gNV&d&riAkZH!_UzXEsD zaq`Zpf%u4?V~#TI*Tk(WxAq0>+=?~bF110;cuN1P_cRuTT zx)b%cFX?`qw}eTvQJ#vX^(^B==H^#27@)ICgl!wb;P(2L>V+R{r1uBAp)rj3(%qWM z`e!qG)-+MJSc10qI_iTdC?oYy?EIc^zJ9u1+J$OQGmv8`K6gm!%b#~x8Uj0+-7(@{ z0xQtYWY>>@&XW&V-ob=d{eYFr2kxLBXzeRGqAKO&t27i@he>20Pl`xuDK zFTgmhAw0hbH~!S%?U|Q+&m+LfJoAaANc&=vPTEa+p(YsQ&snc>a%;~L2plfSb>Btc zPIw9KGs>CUxg6vEOo~V9Z+ca(+%GsV{;s9Cgr^# zJ^l6XD6S_Xi@6#yqW95zJ~t)%4YlP%+2AS7cFo0v*V$-sdLOSU6l zyBf$=<*5dK2eL%ivGNfodSBR)-5&v)Rm&8al$$p`nBvcGLI2nVgj)#QM)Sx!jfpq> z+rVA12CZN^>A*f{@A?tgwnS6+R=`@<1M5jTM9O5Rnejv5wk*u8ZRsFAH182lakWGgNOP#52=ef7*j``ijqbcoSK+;f}XL8S>i8qKJ8d+AmS|TvxTDTiIXMLo%ark#th zWBDV~Sda)T+yeC3qF|&@ZFo`K6kXQ?%S=XnXfOG5RFf(H+2L67C=U{MC<^js8gaVY zU|%4eKDZcnJ$pdrZ9u)zouI$1gVrRfvBmP6#&hyr_Ff_HIfeL@ha2hBKn%;yMZsyb zr$s<49}l7*J=^cSsER7EdAnQHKw09jP969V5yIrcIvr)W>P|oH 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 172/196] 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 6b55daa9b6eae0..7ae399eb95ba6e 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 7ab5921c7ec298..4f2eda19b85e07 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 173/196] 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 9622151143cd78..74506fc54de50e 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 00000000000000..476be205da8001 --- /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 b8bb041f0cff21..8fa9cbba3bcce3 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 174/196] 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 9d30a14f112937..ff020b52da3f23 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 d5b14216770906..459846e55ccf70 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 zcmW(+dss~C_unOiFsKZ|NC;sNMzhyyAGZ_2phF153AxW9P6%6)K{N=1Fz$me2x<1a zW)R|pLDF#@bO>?A<&gVte}8|?^UU)!&8)rNwLZ6ZNZ&qvR!-u$;lB*)J#l)XsxHTI zl{jy%PFs#M#(HtSoJxLY;<(=vedO0yejFD+E^%C}{1^HWt9Z`8d0x|;z(_IXi?-IF zd=xJb?!@k?G@xdYZMJhcux1V)5tv14PxKmK7Qd8) zC-s@n&l>1S>du~Q`HJFxe|APu)#2`OOFDUYK%{upVsCitJlO_%!>x!akxuI-5bJ&> zcVaor{v|lFC?Eh!e5#Spz6j*rEpSLJIwQx4k>6Se|L@hI+3$~CHT5DxwXYy~MvF-9 z$~{P!;!Vcy|G_%HOBDL}D=0^eq>^3NVDO4Qkp=trLRm&Scz*7Lpl3(WZLz^4Q*fkm zU@3H)l;8*}sfM9}bshQ>Z=gd<-$-N5UYPM{wvNs)-^lo$ zD=4&Y8_cdbmc+qxq>_lnWO+B2`L;d85-!bfsE!9Rb5ISkd^{;xW+7MxS*4N{jmWaw zEV(1LFw3WlQsBl`k=)v4Qk%aTIJlB^cIRx26ru<5h6J_zJ%52OH*FX?$_7H+?o^TC zg^3bi^4CVlRVu)&*7*PRQ%%5pUX}6)Uc@AkF9)_6R9U_g-mw>N01@(`U!9TnyhORcjjV3)Jxr~c2D!!eA zAL)&!Li#!iM!$nT!+&DQup>}*p*;zQ^x&Dlf-D*9dBvI9Bv!v8EmrFsxz}@8iB}_x zp4ozSnbu<5{?WvJ7%pX2n@>@#@6pKOWu&j$m=*V2O$G>K7tgGrwAfR4F({3=XQ$A1 zZUlL5`jO-aBy({QSnQiwS=dyExKWZ8O-~~+`>fqEX(4c?tM;-k2bj39-0ojLmQ=4& zq*~GHNHK4Uw5H%QiSIVrYZ|IWa%JUO+w3N2@NWXTZredIVKbEHw?wX}94u3NQPDI7 zHZSTLdH;0B|F5Sws1ru-nH%YR7l8R+22es^WvpBCE*T%@!~gnLH6jbrm((QR?4#g0 zC6e!s^Dwc3k^b&p*x}|PZOdmt%I2HM)td~?;m9ji8=>%g&q%$2fvWp?@*UufR4d65 zJB7nq+N)^oz(5R`&Wo3mAnTfgET;3kvuZQuK4p~(-}iDDxqZx8)RQHjZc3+aF|=YF zan7gRCC_}C`}rg}M=T?Ma{#$Mt|H;aMc(^XI^_-25Y3C zM(HG;TxT~8{sXx(e{J0--%wTjj`tJYBHq;Oi-p+E>Pr-}^;=xE}KV z_2fUc#r7-Qn6*-mQ0tv5ay)* z`?v*$v5n|FIvU0|tr_Y5sRM&w2oo+Wg5PF`M(SJSfMA-%{N;1;zd7RkQ57{|zhlCO z>+s=l9ER%C;r@nyNOg^v8d~y|)Y4YLPFH33rg{qOIf5wncXK&I4`B6dMH?TdQ z$(Ae(aBw?MYg^0-b_l)ye)azUdI}2_s5e()M&T)R zI#-CEx|?B7`PoEO?WH z^yAL)OR7aWbnQoi0Ec)>pT6KaaT?q&>H@!fJGq54-cw^Ya(^wi8)ptjap!xx>p&U_ zQ^F)o>%NiPO44RFuTAb}bs+4z359i=pzO*hQoJmJHy2-FenAzycC?gKts3EaYZHfS z@z4M7$6Vu0m=YW3aHegAxQgef`xpTOvxY^w%>7}@rO#B-Z7s}ixRZp-n}91l2OjkV zXnn1Eq$+3ta3fzpXfF{O-rJ3_bR3#Ei!r>t4@QPhb4)v;#D_BvlYZ+bxb#oeNad=% zuqcbjP^AS(5nYJeQ&UP(t|iOqRjj|GzN4sLAmOsTDCFy@e9&y%b3T>yKNr!%#VbkL zZYD}jCquvbaOL_661wl?KQvrKSLQy##0C8*>iP>PTksz7R#f zBDtt2DfHr65PmoE+~9{G4jvEgtxFmA&uNJ0vmCiv@1Vf*kR?p>$2jjP4)OfA|F5U| z^A(8V-%?bcEuj8a!8ncj|KArsbOOHZ0WvjR0V&nwz8bR?qMRGRwKNeXPWy)3jlm$@ z?t@X?mw=`25VV~?2Cb@iMXGjG!k?y&4sk;h{5C1bVeC~I=S}j9v{{Zp#fu(f+1?qV zdK@6`)^mILKm}DeRs8$0%#4Ip#9I%rCYr|h+7FnEWNl3Na<*pI8pJM}OHv(+U2 zjOUBG$~#THpO*ionNAz0%3t$-5+5`9r2NC&SS!jl=ZpDzsT( zB;|4fo(7@9Z#fhQK%N`EVEWmEaiP2H7x(@TH(ioywa6mHjR1CP=yNp0`Y>sO8M$ve z?3OF5B+slGz$h%%(jQ)!bh!vJ`}$z%5I?N4Vv)n__y!A1LS$L-B@ko&l59t| zfoa!GQiX;8e?6TuS^+n@&~Ckw2EoIdI25Dz09TZ$b@~{=`TJ+I%o__?gA!5fyA*6O zJ{bD+C~P=fInwthhhx+a>Hbp{?p6(QNTt>Bc&|t3d3OR-Bf5jh(Hd?RJ|XcKNCmcY z%z0)#tL^l4WKjc({j`!rKb}IFSMTGP@97kpO>E;26DfxjkhSk>a^AfrZNIaObe92= zzf7m3zviO&wJUwAw-3c|C#z5%Wt=eo40qnb5>6h5b{m2m8gFl`HQhzNTi-x-iWXzn z>;c!ybS8?8L3kWNLUMDdO~OaynglcBReAs1o4{O;qfs?{GW$6G1?n$(B*Vx6=Jf8x z>yP=$e=`GIiNAnmh6C1YU4@+Ji{1a5;xNVgV9qK#y0*Dsex4I8w+?{qT%f}>tS{_5 zHaSvog}?`s6Aj&$LZjnh4&@(K@ax)=Op7w$uQ~Fb{~iankgX_Om<#HpKcHaM9xxC8 zfwAY_0oR8oOZO%?C}WZ%q_`&fwVH^gUvgmOa}(-MHiq(cZ;8_`k%FR|kSQ*Ul^ptu zxKE8Jw|EA{{xX9KM_k7bMH!@DY*R(+6 zik6h3J%I%?vY6m1k+`4Rc=ekDOn6lSe!3szPHKRcz<9k z`8TyIn&g6^eKrc6{g9iE4%LTxs471s#U6MALeplEYPbZ$o78l;qZdNKXhozct{Yt2 z*eOzNN`?LEI*wfZVKA?~NXqXUq1JT|TD)RmN_G*dpN;{p!W7|2%Y-IgMHp4`5OmEK zgWnY;uIx6!(Q8$0R6OXwl$TCI-lu<%n;ZaH$1jk6^hU}0WHsr1cCzfh*^iKlE8k*2DoAWm->)#f%y%R!~+-JQaMOOR>Mchp^^4x_`VXN)SkI&g?@^ zuQ|-!V<1?5YY4^*2bjAjhwaB-Cz0=fbHZvml0F5Yc<8&<_gFq8oUemoji0=-$pUf@ zR}VqD*Pn0Ca=5uV=yb&C&^X>L^<-MwRE!o){lt&&3}MJC|x3`SGSaQHRpw@BCZ z88Gl^7IBSs!_ngU4$p|S5Y_$wx*H-K6l+E5mUafNpg^lo&4*J@SE2Fr1&BYl6h&Pf zv@PxJ;Of-Dd`C7#Z9M}kCwfP!Kh*|BkwD_q{Zide*GN&mhxw$0V4j;gFK)A7}BRu@xj8zr{4e?!dHT8)N|9 z3MckkO371uVBdLu4$V;&)*2od>308s3Mrkb`tJf)r@_nyO<|CtZ=`8+2YI*cvg;p+ z@Y{^G4%49oNQycM&K95fNlC3Dg%lT`t9%RGbPbfjl(tBz3+Coyv>Rm7oD<$z9Z|5xPdFVU7X%4WV}tV}gg!|orgPscTz z(fX!6S(0s1Y)D)3p$Qn;yn|8u>}A0p23WhF~du}ck8Pc?9u zRAKO8T?f*aui|Tn!I93}UHDYTW>k%>4qW^75jM|O_|`lN3rE$!v?^ODE-nNYj0khM zGdxfcF%G#SV!&zNwsmzVv{x#nwwpw%%^rS6vV6`@r{fW? zO=Ma4P4auXlt%tXq)`s1lKFYeJS~`VBh~21FJLL|G~}Ajmx_k9!`RpZptt>$V&=3( z&x9xndolu}{_%Ere0ZGkY8RFK;sD=1O;D)PQBo~E%qP9P!)#5Sv%+0nsHAv4>N5M2 z$7??5$3{|NKoBa1R3%Qc62+cj%(mt=h^2F(Y{F@lvn>$Kc{yPDXBevgk~#kS`B=f% zaeN!8!w(hJv3z$Otk_|}+{7J_xVa_?mLUFPw?`;0t|1lDH59Z1_?UeUN&n^$j}cDd zR`6Q0`@6i~j%)fkKcL?9FE5tW;?;w9fHJ?Iycg@CC;DH;2Wqf5w522FXf5Pscav1N zS3=ReY~-$F=lOjZPX%`~*{(MaDC%S&y*$2yeAZ5v`%;_tX0e${QdXiRIE(aSd&9Z+ zsWh_BQM%uA0O`BQ`b2<&va;)9K}Z%0I<^A2w`OhG^8V=Aa}|X26e-@*9r^Gk#Kp$r zmA{@*>0$vVsxMRQWqA)g+X9w@wOGZ3`=Gg0lM*_D@ap>VBh& zD<8r6qBa!{7Ezd0jm2*cK;`;_AX>XKS8xOhW9#zz_4Co18-V5NHCPh$ih}M=M%U|& zEZr{vi}fcl;dmNw={=dsu}&H@bPakM^NRdAXRuTAnvDNx9s+i(A8hkcU_NM z_#yj;DgKeB5Fbcb{Th6`o`i&2`4F`;1oaDRF~y=G_{#@*&uwjsaVIt8S$707qxK+I zvO=p0na$LBay_=)rqloxq4NTzW+aiWVhPKixPv-fUWxftc9W}#7j9w8X-1{ZT-WY^W7?xzic{s*SttRirzTv z;RAB+vjDgJq@?h~vz*_XVMSS6imJDfmG6>wQ_^-Q&PklYBI zUeOn}hozvp;vu+mCPV&b4LZ-Sm;8oI#u<%Y5I-&w0}D2g(*Go=74v1>T1`?kO9fl6 z%goxvM&$+#rN=%Z->=Jv>ljQEckZM69~WTip?#G7eiXj!no4C$;%U#?Fj~V|W!)=> zad(n zeZf@y7}KOR$Mmzm$;x1el+?^b&a|8SmX9V`Z~XxGJH=C3H#hiR`^xxbQ&0$)&-)a2 zK>zNIQNQ*RKmXG*OxV4Y&HuO^4Zc+{XZbF)9veW0&41z=aTBQrJc9f7(a7yF+G9I< zp=n}-EVv4Yzw$xmY{I~^V997P8JJcd9%OlT}zRZ<*I8$Yw0&^WBydlTt`LojG#2|0c5@%exDq_PK< zsFbUOzU>x}0d*i9-$vZ;^?CESO;ob-JQzldA})p?)P0e0L8DRcjD^x6z0f~B3Uw_O z!?Q`7QM|sMty^~xg%>$6=G-ofeSeMRTu(q_pIwwh8z70@1=HQ(EOW7pS1Je5x6-<( z$_HAr|CoHP|6_jRs-QdOfRr-uI2k^LLhRkqq-?MOd|F;W&2$fh+1{X`X*;}c>42&M z<4`|jqm*1{2^POSMq&H=Vm~aTk}WCVsEoUKWWqC$d^U@8ANJw2y(386+mshqo@J(HImG?l+wL^#NNha`k}kAIeZ7ld zy>tdsHz_deT}RA*(FK+7uQGRSEgG`dQFi@GSmo+X;`XWRs&9#8@KI4oog)xiU)EfP z5nPG45Vz_#-dVnu1p5YvOXbPvk~w%~Jqyu9VeI^iApR4By++MM{b47h&fJR?1tK$K zA41`u27pU8q9@avm9*)B^f8m%Bdt7lqZ^<5*Ar&k)dCZn_M_P2^1PooiVWX(q2c3K zmi;;kh4qd2_<2jocl3GKv%*Y8CT|pO|AEE^Dl8cE1$BJ|+_!ZFCZ32x_uN8WwRk$t z%Gyq;jXR*b=rK9@=e)j#FH?lwXIb-q$DpOr?kaJRxD(lEKvjf>qw}rHSSCJ*{2R!^^8|edI z@$Xu$AkU+bFzrZVQXEJCab&s_)UGWi`&U6*O+9)#q+;nRZybN@09y96V0xp>b$2|q zd(V|I#$Rz-SFB1aWtljtP6B{z%+0E zM3ti-Xad40endkQDh`p=zY|(#oPdP+T`=(FOVm%);zZvwSaD21<*geKez*_1mo1}S z!)jsqr1!+xjzlPm>rrBjD%7jdFm&e)BW0e1k&NBFRB$-U(55X*po7}Nh$;2NcA+aTizX(!pP8#vkgD`f;28vy>67-&hq_cK} z%r=!tU;LBjEZ%%!W_v@2K!yjuq!yVMwFB$nBhN&%3q-Jv-VkzflvAn>SOd z7N3ET+m|fU;+b#KJyv$QJ0<;F1YrZFP-tE?OsxJJB_CRWWgU03gtBy0dFO+E%^DW> zREMd9tz`UrII446vz+P?xTf)W^t}~~T}{QPU*V7WSEAA73`CWo3*|Pu50*z2r2i#F z3Ld(Ga;hoFI7Nx!NkfU(hhow0iIn@M1?>qON9R)96g5CkQt$N?x2ZpcH1UP8uKtx!M0MEpQ*yAee)&b*1pz? z8aJ9>rF!+=xY$tD?%B!`ot#(0gVk^~#@$ znv3U|X`B*^ZrphLv8BsP7?7te#KzJIea+ zKLH>P6zKkX9fnlzPwt2L(w?+PTGagvIc<@Y)QiaSRzuEBfqaSP1G_R}1FCdZ$=&@U zxPE9Mq|b0t%+`bY+7i;8sRpK?x}YCd%s&a(k0$SN;P=~V)QvbHb9#<>Rvm+j&Cii| z=Y}?adp2+PJz!koRNi$b7~Iyiyt7U_ zbgyrOwYsf9&5;;v-*PJ&±akcRs7N0KTrMAp>3nNW8q=-Vl&B=#&zz8XRXa}23( z)_{tcW2oZdYnZm873Kdk7FB=eNc&oD!fz#QQ1$H$l;224*TWf9YD_})mJ#H8UBtn7IPb&6FW4xbO=`9m?dax!OO!LEGsRD;PSfgpQ>z6#uN*S4x`u zg<+>`GEYh-uGtp8{iqCz9vqF?_a{@5Pb4NCD`3t88KCYo8N}3o?Mg#;RE*gVX^U52 z*2B)Ya(pJbV;i9`e>RE(ig|8?H@YWeOKx_A_nT9lRMSgXT=O2J{QEcJZuXb-cL$O3 z>}~MzsX>`*2cx*ito<=`6UM#hi9zzrwPtL@(11`Xyd!In)8>)t!ZUEzX#oPAr8Dfhq>at2nXGTa5uvbrp~ybmhoYd{~C%e!Yy25a{a5~^M2 zRii2xmtPj4n*1Du=B2!O)G`e9+5%zkT48SKSx9eQi)>|8p-q>2R1*H2%{}cRXGJn8 zd){VU2d|~<4-GK8QUdX&NoY8CnpN~|fQElIfcq8k6?J=~TdEGuc1Gk{zJ%i$t5C?O zC*#RjbSqbZ@1F(0?N8vjbyxE|$rqWhxP)&QDr7dErEte$!&$Cc9y$UP&{Q?@6 z)dfqDjJKP70CVsMCjKqK$nlSf`>Q4!vdJd%EnitytZwIiEQS^my#$k{u9-!rH+ z`R_@fL{}$Lmn@QJX$=x{UP`uEwOG~@S<9?65?oy}px{~x2*-Cb?)hO}Cq81%KMay5 zxFd+hAKJpFeX;D>QuvVD6;(k6;0#bR{g5aKwjUz1s(>jz7L)73Jj(1aoZcB_O=jvG zD5@Jz_ot0Olem|eZx2J&n`2<9dIGGwqS3ah8r)|~(Uy}2=KRH2u&V?L-*iV$h3u&; zTLb#X9l&khD;X-fvkGkiOKhc~imqKqZ1;hc{?n9%iotwE$1N;mj;y_{34^FV)?rfg zARKdW8IFIEiCmyk>pOcS79P@*__Z@6Os`I!q$K9oq^kVfV%U><*{Ev}2BpCVu-DFp zsIp$-&F`w?y9-Cjx&K#b(XW?C>{^$S8#X1wnx5pUKO3yqyOYj$DkPj}L1oteSZ-l+ z`S<-sn)q)_Q+ASB8Wc)G?mUP(xCGqm5<#4`3QSMxF`?*J-aU0YQ>D~ldcVy)S7p2u zs%?boyvZQ!Z;w$acfr{(l{YoX0M#OqtlM_5sDoE1r^y`ZA$!m*`)(jh^he2c;CIsZ zX@v!r4a`_F17qW^L28S}XgC>z#uyW1g)T(h(BTj=ZxXsg)1h!^V|3 zoc>=VuH9~XD6_J{kJZT>)Q}QVtB_e&jkx~h5=Ze&G50j+pL7MY&qBo7Ka zHL5r}m^J;dmv3Wo$7J%x+%VbGImMhiDub|iF^k&01l^TKK~Aef7;o30F|8(YUNUDh z#S!;yXWp}5qO$9)Xqt8*m7N_!`XyahuPZ%BELOsvJb$un7{StWs!;CEx@2uo%xp{Z zm?~|Lq?)mk7t@o$wyzrK`pyOC-;X4&ht=*0pT{iEr!uZ~Ft1AcA!WC&go>I8VEL~# zntuNb!j|b^F13RusS7z*rm*~k)8xKCkJgRfNr7S(skc66_xS{Jwfzfp57SuT`-xc4 zP0r069VFxLICSl*fTD*pvEm>38Lsb#h9-SLRrD2{OTO?be8*cJ6!M14)tPXhE$^x} zkCokJ%sTG_^WFA|Da@~!yHv+i$2u`_eJ5~UXbFki`(S27dkjrkgGah9LyxR^E1&j2 zOS7F!Jo8v9jBiP~lZu%opgyy`U&?xgwUTG+YVba`2?hO7tk^jS{crWh-0m`mn|eZ< z-F`bIM@G_&n6+eT`zHyTtCBgR2kB>TkScDxWrnyK%=PIa6GQDxkEfY#St{e|J(oB` z81K2pgQdp_-jI*-cl#=d85<>YP%3kWu4df8Hj+@k9!n~Af#KmYFf0neFj?Oc%LsI{ z-CzlP#7x;^*|kO6Y0OKJ+^rAM!RXzT$ZIL9_XIibbCef{_h9$`6R?7+qwl!{$^W^<7Y|Y=x?A;~=)c4qVw>-aXeOW7SZ*J6C?Tn$_Lan<_I)@6}9vc!cTt z-(k5cZps*E6jMy<#>A@Id2YyEKI}mt+GYo$-+(2kD^14yQn^<@|AIoSx5OQ*rp?W& zM9P=%SlN$NEXrXv3`&DQNsC%9^%{ zsxMkjrQLY)o5)j1frZ(|9cH>ZvCMFEKGRLx#B2xmFlP^*IiCa52XEn>&GUI-;wN4m zRtNNnrzN5Ih?G0Y$P#R;nfqZ)X6RdoB@8t}+1YiFeX1_zpSm8=v(!bx& zbSt(qedQXU@jV63z;N^l{1X#mN1@LKgFK6pfs5a$Rjl%-@Us6Gp%0tqo03U@e8B4Gpl&Spj-Z_7Vs zOtW+6c51nBS$BcYkY$NM-5c>2s zxD?|-m^hy|`LzN=W(($O>IJ3^xlG-#AyaRwLawV`RPgc=b3L#zm9A9o--Fu!`6p3B zK7!d>kp0csSbk{=O5Qq*?<~)zX_B2&D9@N?w5F&(m$BFvjOl!RSnR9kph``Fyr5O6 zmvwA$tn76(bpto8ha_AnkYZ-9Bh}}sR61ufWj<*~Ww~X{^GmRN_Cmq>NY3G%Jj&-k ztt|Vh&zZ8pDW-v@B)-03H%0Nx6F(8eXOqCyG6uNI)j%}u(<-`anYi|e`y?cUti4p*+tey>PnW;6J&oy&Q6-&NWSv3aRtgVY*7{D#>o)*O9rY^FG23BKQXkG ztgDwCm-8({?Z>ZeB9$?p?HeF#%@1qJ+$@V}RQ1TiXF;!DYm?04c|9s9cSIoR>OW&T zWgl{RHDE&AK&J521Fqk3;MT^2?d41mrI);-<0!`MXm7VRJ0fRYx@w(S4xU@w4DM$r zv0(TLh?VN0aI`(BD)vjB5x=plrwb{*uqAb!yN^m|j3RwXJ5q}RsfTul*yfj+?GF{Y zt6bw1?E*33g%`SinF?X;dZBRQEN|RB992t~ga7L;Sk}!2&T-elH*pQPcWvkON00HY z6_c3jQ9E}3Tvf_($k-`I{tfT*n6lzJ;~dv{=h>A~LBBVkcq{uZRbnve+z>4P711{> z8l79bq@)J-AY7p)eZNh-*dT|Ajb=$%eHAFK^5(}+%#d?v^4SYcK&978P+zVrpU1st zhU_;}tbZ1>n%9sb>=hH`43hHu52hJe09lj0Nz9$Vha9azn(19h-S#{4Up$)JyHlC% zRwKq8sn80SKZEL8dr0WC8T8$2f?@myCSDlE+iWkGFn9v5s+z*vyjnu?=hj%(d-MR)9Z`wt3J0*S{8;z1D+1>kkkoo!46YPD{=sompt3 zr_BF%PR`y0kx<#j#DTJQ)xHX-jx1*S3x9*F>R1rO2n?DWCg-cdF|5Nteyk(&q76(n zJeBlSA27?2%~I0QH%v3`Ayn*o%eeFtdFfZY$fg=dv44MI$+stxb&Z_kKDJ*HX_Qp4 zK>qxi&v=``4C;rKp=|DT=FG72$*tsUa^7LylD(T3c6R`O3!quQ1fpiOM)&Ix;PiVY zIjeS%HYP5SHN?BD@PwSn9M**tK{EHw>OrPw>maB!fN~FeqbcuqW_)V}@l-=Pg!tM&3RCDfaYB&Cu53rJU_lV|HE_)9#VeUd%<^Nxw;EE>G9%f(ZDy9Hb4j=B856%A zvwQY_X0eOzf$y>Zn5Ff0$#?x%_DvN>CAZ!)i*Y=uy$&+2Zk$~|Ctu>G%D!LqJ$&x- zG!S=qLs{q#CT_UKi@|lta-x7YMAQPEwlySV^hf=eL{Rw#qi4W)F!Yf3)rL)4%eEv^ z*!Ho);3#I2eU{KrYXldgIe(#jXACdR7^bIO1JDKm=^AIN0 z#EBP;xSJSBO`7}tHE*3VO!G`C#9 z_o+ha8$K*)O=VIH8bg+fA56GEj0$es88sBMnW7$*L zeUe3Y$bSbZL))b4DL1`SAsU3Tu$L>nE@@EnuNHoF6KsQJ-dpDi zgnX9g*XeAqEU-zgDqfIyM$WQZyRoeEgQ?(25#wSWMi}~3BlE>PDE(HK{>RT^p7~RV z-w68FxVFqq`;u5w{>{$8yyy5Zra#?C)_WRh#e9EoeX9cD$Nb4Nzcqw7y+}W#BRF-l zKt;pkXWavJ^-{pR|0{^!=Yg|He>wN{kT2(Zk-K9{W^0;2?jz5ba@P}<_@{~t*XuxR z+m__{G#-L{<k7UL3oRcXt~G&K+04R#XBp&zfWCgvSuKCK6TI-9i6P zM|8HDD@7fvjGVjH8O75{pkLCHsq0i>`g=E6iQgs0r7nz6ZS|6MHZv%PJYrnxiCeqpw#%V4fu#EcE)jN5b$ZC6U6eBmFcdHMzlmieRNZ#M|H z1j%(I4GcrN$zF9m$y%uoaolz$IGakw6%|a;b1(Q$_9uO=mPMtiD5f-;#4qxlnsHhx zIxK4oox=Ev5cv$vs)fSb97+8Aj(1nv%a1p*#Y$ayE9pMl5?EVhRh zWr3k21S;mBz{=R`#yNVY{@l% zn=_W_Y`=l{IFq-?8n`k%52AjNb*R$;sIMIZ1@$|i7<$HTtJ@m6;a{}Vev!52*{3B{ z9Rq~MK4siqkc6I_CF{I2rhc^z63$4BYrF?+-Llwybv2pG`ZCo|`5wpHQ(Eillg#s3qC<~F^9r`-Fbtf3}PRbGS|r^kiIFLxWdpp zuBa7Lot?sriZrkdmowc`C&u}ZI-?30E*xgUsF7f) zmMfKP*bQQ{p5S?(4~FlLK)5;%3OXv0%dMB^`XuMe4=DJ;IWp#56DH+ObIAO|%@pG} z;9h){oVN2)u3S$}TF8uLMo=~~ve0Fpz>w6D=?2{c{m<1>S+dMeRc#`a=if2s#RI%x zJp#Jl`$B4x4x<$N!IfPKNqrxKd-^fnH~bY;eA>f8Umb+d%yy*c?*sY{2BuPNlT?G| zfsxXfII~Qy+kGY#1ygEhJ^6k_Q}SGFNhFAh@zxLGHoVP%?2lBz-#ux=A;IGmOeJ>@0?)t%sR%(MC|ckU3`i zKlzxK^~uz=53_XLD@9HGi;35LAvd&=?9F%5CO?z$a8EC=YHlz?y>Xx$H-TACn1H*Q zrp;|6LGGYb_}{KATU81ow^bXrMAj$m-n_Z2HgXDWUctAg5W1&?Sxc6JK0A~-o3G$= z5AOg=B$LEdSv zE}EIYUP*=}Wi04PAlcf~A=Mi%RvIPa!%3ULxt=5UGH(ctaWc*2Q%rpEC(G?E(@%a^2Fk$ta;pvzdp#C!8W<#$2Syp(;vH&6Ij zzf{owy%EHsdc5&jiJYanq}6x*2*UYld{mLlgX$Ns*eY3|2p`7WwdDDjmIY!qX%*+Y zgLr+Uq`Z*_!pIR)c1Bec$9PMw5dn<*?}y!ZoRjtFb9V8Pob_yVPpeoMf$ldR-sF`J z?yFN|f3hVcq-_JYctO_s)*+O@O_ZSoQ?%Nw`ClNN7qO~?ZuK}W(?ElYEjhC z92Py+j}!^-nYv9F%bZe$bX%u^VEoKn*?}OY7c$e7jV$WICYFoY%u`p(IPDBsJLx5P z;*Nqa{{bJW%m%}e6maL~@y;&C!SG@v(+oHQy^hr;)AD!_mIM)(E%27RDrS+fn(#WG z7x-0-`@>@wemyShF;DoUuoKKOW*Rt)P0Y1023#{5G9l>@h^tN7ibtzK@gxGAbqDgE zVHOa(Y}VSgTn3eY3SY7L66nfLGF9~*;JLGunH~*+g25ZXqQ1bJ8aJ1JZ=N=xl6?L@ zH`8W)sEuN(QEO>+P~!BOh|nWH8FwYxZt5QnTvR=6@|Q4FomkIXZkz#k%~s%P&>w6W zbAbzdou?W)AAFz5{a3FO80+0&s`FcU+fI4j|M}ML9MnNl+5K72^GallOJ`9IFEZY} z!VG?~OyA@UQ`HECq)M-tdQNL_54px%a%Qg}Yd=#yKfo0EvzVBjrWNsvWY)+%4@>AX%zx;cXf1GQSmKV_fg`aC}B@1vj|DRZrZQ{=2~Z*V?b!*f1^ zAv3iWsr(v1(!nQ8pSFq@6C-7B-eTt#SCzzuZzNs4w@etAz?3^*F^}aiD_Ojhac6JI z{@)cocgWvzA4P&ey2w;b1?IVVfSG3PXC-ON822c_F7$50)Gd-h+|pV~IBWrZz$IQ^ zIRxCBM}e^VtyIu(B^Vz+mwPY~?yppmC$XYV$%xJAl@?ADTy7sNWqsbCp+~ zGlIFAk=gn$0DbX(rhhN%x6hKnIj9z>UwX?t$<7;k{R-|tE3Z4Ml<%12@xqR_yr|mC zm)v{JoXMkj_bXYeJll~^JyjFkXHxlu(TBjjx{P=4Oabvy7`WeXpzg^-{s%AO%H(YQ z%s0$Zbq()2)lkmmSF&^C*4dr=Nit{NVd{dO%vH05xkt%*{k=`hY;?#y6wdp`6f*so z0pNZoXT_G+WzJ>UOkBB3)&eq^Fuk*!*%-*we+~rqKP2f!ndSVZf)~96&`)a&To?Ji zQrSe{2K~is0r8OeL*997n}X+J2IF?m<+)e4wcL^*$+<@>=b7J2dh2pt|66P3u0BEL zPo0@-jt_V=^_b3YJ&3P1Nv4%MfJ^#At3Pmr*VmCT+zY3iO%DhCr4rsYKrcUovCQ`C z2=L%B=6Tc&JgZ{Cnd1lQT^xwDukx;Vf7uf!S)&X@Vfr2UzSCvic}@1hJKba4$Q``+ z`v?S$T!yyb>D&=YMwK!lxR$(!-!tc@ExaZ3 zF3-iV2yRmYyXu`u%4Lk1hBasUQx}%Y@?uF#c zH_AGfQF1=E$lCfRjWF&a&rLS*!ofut>0Mv_8V3UiCEc~x#_rtpzYq#yC`FvK+sqEB&ilPgpvU#neKtiwVpiZg?)eX zw&~SDAHSb>j>zCu`?mAW(Xu9z>*Q76b)eE0^RXERm^1!7&%K``xpjy5ia{s9eK&_! zKRPU9*-~Ehah;5>0zue39=KUyP!?}ywwVpUwB#cb@hZ=8A-T?imOR&Ly;dA^#jYAI zW0NyirKp34n60wFM8_HCTCkF-7UoI5KlU| zF6714V`bfY-2ZiS-ElHrU;naL-Dqp|NAHZ1*q!HGZld=giC!L2f&_~s`p>l%yXs)0 zmq+i6Rd=3q8(RW1{U66QBUjNL;?wH-@-gC~koO3S_lWHRy5oNN?K9eoI z@Ax}3rGz8Zn2g3P57;(k!!{8f0Q)_TRfsiA~n zw7%(IDr3H_Sm`_}v*98o3bX)k(b3BDq%XJXS5S7I@mzc}1x3yJAZy+*y$6~pwm%4& zjk9R&FG5DKpOhTGAB<|dkVQs=w(6if8#Y;_TZkp+2nAm^;4CNA_7T^C6}O#)(yi%S zTdj~BxROiHV>A3N9~Wn5fNY)!;(uqUx3LOz7UNpRV8D};+l4j~r@arXeK((5;28EM*^g2D1BaXs!JLd>-8Wd&%qp+_p6Z#`jJe=S$KTnnYoEvNIGC22Nvk&@T8 znsz0rJoB6Lh-{*)+2gr>aRGJOTwu3XJ67LVCA!uD;apO3#caqu@Vs(cO$TZJg?e2x z5dG^TTl$O1R!(-s*NQdfi7Td=>^v4qNhwFebpcL^J>TB=$ zf%5(;xHsoO@I(&Iy6z5na_8mUmo8SU&2u`B-+?~&76og@@Gexwy-Mm(5@B_*jiJbfM4E4^!9AaMR)H?x^T_Jl zgkuWip<$@Y-9hG0@r`8B}*t)IT{$@JNt{!dZd6X(g%`8y;>E5Kd&HLdkU3`QoXa8gaBS4r|_TB3V{_Tu3^ z;wHURpwB>_z-p*q&1f#FXP~aeQIGVazc|$s-xMdV?RlylchUp5K2uD8dq~b2g$%w7 z>4K$^t^O%wzexv{`c=qo@*3ELpiip5K(0ycxX}n^C3eikrT_r;A!1n(I?u#(6Y$Z&$&sOk^8_mVAW#COlZY*2{ ztlw}`JXr>;NkygIBw*uCm?C))=vp(0Pk#fk9aFd-yZ{1ONz^wd9dLO)SW_;7{$`~z z;1~pZleQa~3T$9Ehs|mLl5a&es<7#=-BIZSg-~~*+PGssZt>9UbH^fzCA3brn{j1y z-vn%NcO@q+Lr>OFCFfUF-l=1heIprNCxQATdw}KarC6XVw_4R#*3B61zI=sDEOW%b zc^GLhQRz~7@z5E)6S8<*PwlE=ZN!EcjG>UB%Ly311tE% z)5{>Atu?(>Mi3v12d}>c@k-*+LvMiW^Bb@WgCJZm2WO{xgVDbz7rhFpa9Uv=7|?>W zNEB%z2dqmj&1Eb#?W5!^ocx4~cbmX28sbLX&0x<-2HA2wc zoOa~Xt)zPoI&xMcWIZ-JqGDT$%Mp$}i{^dy^$D?FCxA^JWO@#D=OT{*-XF=!Zaf#< zCKPwyo&h#<6xhZ70eN8noyqhNzK79&wFvR=F3Mk;?kV_lGOghgV8NHBNI46B5AE}^ z15o{I@~y`21=bSsTLrQ) z{rjT(K%VZP+$}pmv|OZ&$1_2%n~3_S+8}o~MOJix8MZ4cd3=`>_+q-UW=+Q-zs@86 za35K2immr$lx(ydTsmLLN*{MbW_u;q6;-yUr_zItV_5bj53wSMA)hPxPXq2f9;d8f zwYZ&8h&;YWrtqFZowt^vZ$aqFU{ilVe0&=W&k4xPwUxY74c2th#$yl|o=2F`d?NP6=f<+YH`jsfwK=zVc=tihn6S zHxxrTY?>*1dlXxoA>dIQS1;88FLAzd^wf4 z)=9~US25vOS0#U2Vv1~?Rpd-L?s?#&Gs9l);U$!A-WEjhKhRS+T3P=t!QiSbN-XJx zGK;uYy@trVkC4?ai#mU66i4$Q3r#Rt=4D5Jb`{u+fsWn&0C9khKB?<)mUh)lSkj5> z?)^c&%)zbsJ3xBpfZgymXnzl2F}b*IS{#GD3Xx{-q;zlM_xl!yf{BbXPfKtI+ymqO zW^il#3ih`vIEyF8p#xR~;vl)@*;kJ2nrgBdZ;>H)?AZP^+d&w!agMT^ zrem0zX>R`G!}O|sBfO*JZ87J96Xim@-!gEiYLn`XD!KR)Go zSD)*iWt6Tn3&h38Xx#Z3#j+h3v6m@p@>H~MEmh)mSCsRJTg~Tm=fxK&^HxI^cpoor zC;h-q{R`~G zr%u9dTE}gI?lYj*S0yn}K8lM1J;10yaa?aKtvz`dTV``P{sMT1_2OFn3Sxc@)F+RC zxcw8dCtFAdpMw8*X&_@5XL;s<==BXZK3NRj!ELBstOt=u`@do>~JVhG)l^e4q! zAP$)G#9_sDo342oS>mOT6+`~yr`0gHB3ZGD8&UKxtE^_vQQXZ={JaEd(}$*~O&w*; zJdU0gocbY8(cMRNwem8@p4OUr0+|q=Mzdo%y*%OL3QB$;AFkmC)Q{(*UT_#AyHXTu zzX*fTE0oOlJqE^=R(el&)SnGOcDM<$lQE9GSO$%|+d(e8f|8_@|vQNZ9HM>mV1$XQzR6*7f*B5 z`7!u+qOyA~Le{B)(#vnsT7PUB{R%4ib6Ie^RaR{1YV^|FsP?}=JzXeSp&*8TYNm|o z3cNFXG)q{M>vqJEe?JA0=Q(Kxs3A)0SJY!hD=V}P^%}Z6Fe4e+GpZpQN1@&!QB0s1 zy}!s|ssZYA0XoycQ0}JnO#R*w8@(aZsHwm%P}eiy}cp61}5c>_AB1Yz|9@bv6L9`Ow@a!lkp*B`(( zUo`Do7eO8l)9>*ku&Y$7?`#I?Z_TYwh%4^3xUR7Ry!ShEcQLJJ*SsJzXg%BZQ~K;| zh+L-_`irpiWi^^tx@F4UsmNYb^7$uMqdB_Uj%WNhB^ORbw(3)5Kl~Y4)p*DLo$@}t zA-E}}6}vSOJ%?&5_d*1N!-*Sw*BW)WiDCt5FR#QYqeVsTv8qxZ=q6!tKE+mTaE#G^ zV0dh2(qlAp@zWAzL@h?|S51|!GMzl-0IlUWDBJ(y=)c>bLK6pO6EUSQXEIXdn# zc{wA}b^nhzTX)Kog-UbjB~L{B2s%V{EWI^|o3tJS8Myu4fKmQAdS69x`$Hxg*(l#f zmInLjThM!R()S;MTg^*7sJmc)J%#IIw`mq@B-q8TgH`GXy5)#BY)bVR8`D70eOcD) z^`NJa=fBT}gq1YsJ8C1aRmA(xZh+vZCQ4^p0Cv8%ioNa*dPO%BW3$noeTVGYD<8W~ zeX7kn9An&2%KQEpN$jYkKOJ?S0;sROM!7EzyhDmo&8vdmwpEmD`2hW_p%PzBK+)Pq zI+H%r*I2nDN^osdS8n`s2xJx_y}u~lD)tcV+Vv?e6$a)kRMyJ1bT?c_J$yHLa#tO>QUlBQJru4|gR?3NOjeWp%LQ@ZzB~h3Edmkj zM9*>pM0`nbmp%fKUtxmDxG^_7&4Fa&^5!v9K6(psBLk847{Zf1+*)%V-2RgYXYPSp z_8_pQF39DZ(drupHfoJyd>I0Fa%ryXZv%hIXWZ_*0p#bMxVw21$j3*(&P$wpE$Mfe z3SxH`y6bKLxUZ5?6e&b==k2L~C(Jt zb-?8;rPrD!LoqtPY>X?_~zf{`dozB1W9K|QlAz_w>cqX_AR zFS|JYeWf`YRnKI9mFKcuNs!wwfg7F%;z%zrhzp2QXIo!>w=FOL@aOV;@8+*Lsc zPie>5tu0_5CH`A~E66B%f8rL9zdb}&a~XIdpDVFt6y0}8eA+G#xGQa`60`Q$rH_ZHR4wsJP1aa4+jvhb*cOxJt zD-5-GUvNM+t??d21C9can0J->pBkSEDjY@kOcb4?mDscZ7 zf`s&sx#jGJgvpySk>;sA0^KvuXcl2VY5jqwaUv60;SpxAZEnJ>RP@qaV9d84bqm7% zx?P;$m>Q%l4}n{V;`V4x?x|UVbbb;9`$j4EnxwiweWGLCl@4f>pC>45!wz&micB>bhgoI2N(J1Orrc|ngz z23B}B`4M%%I8L?DNAF3>05 z2cAy|gPW!R8%sK8Z5#5*tDqErnR?t}WYy33?0vCHF5TkTqdF)(%a4(+d8j|S37L*g zw;EhS7T#m(3E7my(P(5AR(kwFw3d`p?9v4%Qo9QIAxj|qOGWbavhzT0(n&j4fN_)f z!Q857H@SoQ2jWq>`Wgi$Lei zjw0n3VCz3|!iS4-cBiSytXCixl>m3lLXhnyfhbiMT(O4!A@(;1@43(R^<97apWJ@nC^=8;NMtTx!dM|@uo20&gbN3`v`BMK$oF7e^AYo zNqLC-OmJj!b0tcCjI3IWk~f#2JUzpalh4u|<3*D_d5LC(XOfvzmwVkJ|EM%rZ7HwY7vysPA7Bq`%8k4( z=ojrkHuwW%r738vr}g}@kg4Au2G2XveecsCVRL=%rtE-(H4I{D|^|gsJ`2uLiq@v7Jba!zg>e2Z?RR03q6~y;m#-g~o1=zJ! zjvJGc>S!sS!9IZObj1`7;nl_tAa8t3HEj{Fif9@S4uNrLA&NR-(4U9UXhb?QCYNa! zy$-BbG#KhCNSCnbaR#{cn{c-e`6bzi`}}itSM7US3r4}&=Igm970mb|J- zvs&B0TZZDAyZ|xyzZygQ_nQYO;sf9rU{LKFKwOyg$@5qcF9BumIi?;!IsMbAkk!4e z(uJeZh^|UKWAdbQdt^t_Pl zB71+z6n}K5T9ydnN_n(jEvFg&y^iijm>sawMHR;7z`dq5eHYECQVx%AN__-c`#)}* zR*l^t3im~$;Avo$PSD<8q<=Fw{?70NCa}xA)`nnazEhMjXrvl^a%b>rk zN%ik6_5F@Hj8XlZOB}!DZU}x|iA%m2j9?{hH`)Mhfj!`+t^qf859(+0L4H+%=83-o z5lz_ox;(Jv)lpVjYr2CposX>;^0JCbUZFm2y&A+52cmm^CRzsJaktH;mGc7r=c(D{ zUZ5EH0~!yb=`76z^zWw{vUQXxUKCSC&La@HSV*~peuc0vO3CtfOr3ZS<@v)X$DTy} zw4IWBc4P2%W5rIdK{kCK8fzAy&Xb$?*;HixCYX9^50w9m2B9iZ4g{!YdDO91lD5n} zGi22NKv8GYcs+*ViRNz#l~e!q{j4gxke#gz`tLHxhU_8FatmROC!T#lda2iO z$3MJ=5;gq9TWBpitVFi5rzr=YA|I${oST@1_LwAO%d#uG>kM=c=2y(0%NM-hQO0*$ z!N|<7bioT?4(Xw3rxD4dbd!W-7gNV&d&riAkZH!_UzXEsD zaq`Zpf%u4?V~#TI*Tk(WxAq0>+=?~bF110;cuN1P_cRuTT zx)b%cFX?`qw}eTvQJ#vX^(^B==H^#27@)ICgl!wb;P(2L>V+R{r1uBAp)rj3(%qWM z`e!qG)-+MJSc10qI_iTdC?oYy?EIc^zJ9u1+J$OQGmv8`K6gm!%b#~x8Uj0+-7(@{ z0xQtYWY>>@&XW&V-ob=d{eYFr2kxLBXzeRGqAKO&t27i@he>20Pl`xuDK zFTgmhAw0hbH~!S%?U|Q+&m+LfJoAaANc&=vPTEa+p(YsQ&snc>a%;~L2plfSb>Btc zPIw9KGs>CUxg6vEOo~V9Z+ca(+%GsV{;s9Cgr^# zJ^l6XD6S_Xi@6#yqW95zJ~t)%4YlP%+2AS7cFo0v*V$-sdLOSU6l zyBf$=<*5dK2eL%ivGNfodSBR)-5&v)Rm&8al$$p`nBvcGLI2nVgj)#QM)Sx!jfpq> z+rVA12CZN^>A*f{@A?tgwnS6+R=`@<1M5jTM9O5Rnejv5wk*u8ZRsFAH182lakWGgNOP#52=ef7*j``ijqbcoSK+;f}XL8S>i8qKJ8d+AmS|TvxTDTiIXMLo%ark#th zWBDV~Sda)T+yeC3qF|&@ZFo`K6kXQ?%S=XnXfOG5RFf(H+2L67C=U{MC<^js8gaVY zU|%4eKDZcnJ$pdrZ9u)zouI$1gVrRfvBmP6#&hyr_Ff_HIfeL@ha2hBKn%;yMZsyb zr$s<49}l7*J=^cSsER7EdAnQHKw09jP969V5yIrcIvr)W>P|oH 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 175/196] 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 82c2557368371f..b3cd26a8504715 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 3f3695d50f2754..c076b12fb149b2 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 176/196] 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 b565b1d8a9e226..0930ef403c6c4b 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 00000000000000..bc239ce58c9eed --- /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 177/196] 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 7ae399eb95ba6e..6e2c72daf7ac44 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 178/196] 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 39d57c5f5b61c9..2084b30d71ff6c 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 00000000000000..4d5249ffe3a206 --- /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 201cb8a7df8da1..3803c41027dd85 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 179/196] 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 2586ed3a5299a6..c64d4e8ba85b3d 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 79e62edfeed978..0fdeb56122ecc7 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 fbcb95baf2aa60..9a0852f872d763 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 4dd1140f7d85b7..e5fada1f40ce43 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 00000000000000..5b7293b567109a --- /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 b025f7b0eb7fe5..9e86bc42f20074 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 0eff5f76740f78..43a512611fb1ee 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 032d6faeda6a96..7a698e422abd77 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 de036fb964b691..72619fd3afa91a 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 2b68ba4d2cde92..6092da8c04e708 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 fe083411b7b739..2df50ebbcaa1c0 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 180/196] 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 7f3376f8ddb1e2..e68a07382d5884 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 181/196] 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 c017ee04d67f07..2fa2ab768dc48b 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 bab1ca67d538ad..b95bd6a0184ea7 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 1986f5fb2cc640..6cd9c26037f527 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 b70f9b4b0d6259..79a4ded09fc9ca 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 febb2dd823a8fe..915b1acd33f814 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 182/196] 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 6cb11562476e40..02afb01d3731fb 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 183/196] 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 0930ef403c6c4b..77c70aaa7b986e 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 5bd0f7e2af4f84..581ea47d2dec97 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 00000000000000..04e6a377dd816c --- /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 184/196] 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 b3db1189e5dcbc..06c1ae40da5e67 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 185/196] 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 3bbc3fa127abb3..7cc9d0bf262af1 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 9e7fa7a7f58f95..341667d2f0bff9 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 73236767374378..af5cbaa7689f33 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 186/196] 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 6e2c72daf7ac44..24f53a3a272d73 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 4f2eda19b85e07..8063c2ea5011e7 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 187/196] 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 00000000000000..0d74776ff900c1 --- /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 f16c460052151c..00000000000000 --- 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 cbad9b72dc713c..038f842e0bc02e 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 3e6d8a4629a455..00000000000000 --- 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 188/196] 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 36688ce43917ce..dcfcbcc95a39be 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 69aa628db7c34c..9648624b267a54 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 00000000000000..9eae1dc400838a --- /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 189/196] 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 8974361c2537d2..a729efee18c3a1 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 893a116565e37e..646b8a1c3c3a84 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 190/196] 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 00000000000000..17b0f2d797fa48 --- /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 038f842e0bc02e..1993c58ad8c960 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 02cceb62021453..00000000000000 --- 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 191/196] 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 31bcee293b2b69..f8afc16d3cb4cb 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 00000000000000..79536d1fef543f --- /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 e9255038eee5b5..cadc6706243524 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 192/196] 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 459846e55ccf70..c286e3fc4f2bda 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 193/196] 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 e106ac20809f20..c1dc59677896a5 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 00000000000000..f66c156b4bc916 --- /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 57629ff8c57380..eff37fc32b4947 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 194/196] 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 c1dc59677896a5..5f035c35367d64 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 00000000000000..21b9a524d005f9 --- /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 eff37fc32b4947..caf42f5247c2f2 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 195/196] 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 c6a44d946284ef..d36f55a40905d2 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 196/196] 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 a73261cde856bb..e1d251456024c0 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 d67fd13fa33bed..490c7ae5e8076c 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 00000000000000..6077de8ac9ae51 --- /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`.